PluginProbe ʕ •ᴥ•ʔ
Admin and Site Enhancements (ASE) / 8.8.6
Admin and Site Enhancements (ASE) v8.8.6
9.1.0 9.0.2 9.0.1 9.0.0 8.9.2 8.9.1 8.9.0 8.8.8 8.8.7 8.8.6 8.8.5 8.8.4 8.8.3 8.8.2 8.8.1 8.8.0 8.7.3 8.7.2 8.7.1 8.2.1 8.2.2 8.2.3 8.3.0 8.3.1 8.3.2 8.4.0 8.4.1 8.4.2 8.5.0 8.5.1 8.5.2 8.6.0 8.6.1 8.6.2 8.7.0 5.0.1 5.0.2 5.0.2.1 5.0.2.2 5.0.2.3 5.0.2.4 5.1.0 5.2.0 5.2.1 5.2.10 5.2.11 5.2.2 5.2.3 5.2.4 5.2.5 5.2.6 5.2.7 5.2.8 5.2.9 5.3.0 5.3.1 5.3.2 5.4.0 5.4.1 5.5.0 5.5.1 5.5.2 5.6.0 5.6.1 5.6.2 5.7.0 5.7.1 5.8.0 5.8.1 6.0.0 6.0.3 6.0.4 6.0.5 6.0.5.1 6.0.6 6.0.7 6.0.8.1 6.1.0 6.1.3 6.2.0 6.2.1 6.2.2 6.2.3 6.2.4 6.2.5 6.2.6 6.2.7 6.3.0 6.3.1 6.3.2 6.4.0 6.5.0 6.5.1 6.6.0 6.7.0 6.8.0 6.8.2 6.8.3 6.9.0 6.9.1 6.9.10 6.9.11 6.9.12 6.9.13.1 6.9.13.2 6.9.2 6.9.3 6.9.4 6.9.5 6.9.6 6.9.7 6.9.8 6.9.9 7.0.0 7.0.2 7.0.2.1 7.0.2.2 7.0.2.3 7.0.3 7.1.0 7.1.1 7.1.2 7.1.3 7.1.4 7.1.5 7.2.0 7.2.1 7.3.0 7.3.1 7.3.2 7.3.3 7.4.0 7.4.2 7.4.4 7.4.5 7.4.6 7.4.7 7.4.8 7.5.0 7.5.1 7.5.2 7.5.3 7.5.4 7.6.0 7.6.1 7.6.1.1 7.6.10 7.6.11 7.6.2 7.6.3 7.6.4 7.6.5 7.6.6 7.6.7 7.6.7.1 7.6.8 7.6.9 7.7.0 7.8.0 7.8.1 7.8.10 7.8.11 7.8.12 7.8.13 7.8.14 7.8.15 7.8.16 7.8.17 7.8.18 7.8.2 7.8.3 7.8.4 7.8.5 7.8.5.1 7.8.6 7.8.7 7.8.8 7.8.9 7.9.0 7.9.1 7.9.10 7.9.11 7.9.2 7.9.3 7.9.4 7.9.5 7.9.6 7.9.7 7.9.8 7.9.9 8.0.0 8.0.1 8.0.2 8.0.3 8.0.4 8.0.5 8.0.6 8.0.7 8.0.8 8.1.0 8.1.1 8.1.2 8.1.3 8.1.4 8.2.0 trunk 1.0.0 1.1.0 1.2.0 1.3.0 1.4.0 1.5.0 1.6.0 1.7.0 1.8.0 1.9.0 2.0.0 2.1.0 2.2.0 2.3.0 2.4.0 2.5.0 2.6.0 2.7.0 2.8.0 2.8.1 2.8.2 2.8.3 2.9.0 3.0.0 3.0.1 3.0.2 3.0.3 3.0.4 3.0.5 3.0.6 3.1.0 3.2.0 3.3.0 3.4.0 3.5.0 3.6.1 3.7.0 3.8.0 3.9.0 3.9.1 3.9.2 4.0.0 4.0.1 4.1.0 4.2.0 4.2.1 4.2.2 4.3.0 4.3.1 4.4.0 4.5.0 4.6.0 4.7.0 4.7.1 4.7.2 4.7.3 4.7.4 4.8.0 4.8.1 4.8.2 4.8.3 4.9.0 4.9.1 4.9.2 4.9.3 5.0.0
admin-site-enhancements / settings.php
admin-site-enhancements Last commit date
assets 2 months ago classes 2 months ago includes 2 months ago languages 2 months ago vendor 2 months ago CHANGELOG.md 2 months ago LICENSE.md 2 months ago README.md 2 months ago admin-site-enhancements.php 2 months ago bootstrap.php 2 months ago functions.php 2 months ago settings.php 2 months ago
settings.php
1683 lines
1 <?php
2
3 /**
4 * Initialize options. [TODO] Move this into activation class at v7.
5 *
6 * @since 6.4.1
7 */
8 /**
9 * Get an ASE option as an array and normalize malformed values.
10 *
11 * Some sites may store malformed option payloads (e.g. strings), which can
12 * trigger fatal errors on PHP 8+ when string offsets are accessed as arrays.
13 *
14 * @since 8.4.2
15 *
16 * @param string $option_name Option name.
17 * @param bool|null $autoload Whether to autoload option.
18 * @return array
19 */
20 function asenha_get_option_array( $option_name, $autoload = null ) {
21 $option_value = get_option( $option_name, array() );
22 if ( is_array( $option_value ) ) {
23 return $option_value;
24 }
25 $normalized_value = array();
26 if ( is_object( $option_value ) ) {
27 $normalized_value = (array) $option_value;
28 } elseif ( is_string( $option_value ) && '' !== trim( $option_value ) ) {
29 $maybe_unserialized = maybe_unserialize( $option_value );
30 if ( is_array( $maybe_unserialized ) ) {
31 $normalized_value = $maybe_unserialized;
32 } elseif ( is_object( $maybe_unserialized ) ) {
33 $normalized_value = (array) $maybe_unserialized;
34 } elseif ( is_string( $maybe_unserialized ) && '' !== trim( $maybe_unserialized ) ) {
35 $maybe_json = json_decode( $maybe_unserialized, true );
36 if ( is_array( $maybe_json ) ) {
37 $normalized_value = $maybe_json;
38 }
39 }
40 }
41 if ( null === $autoload ) {
42 update_option( $option_name, $normalized_value );
43 } else {
44 update_option( $option_name, $normalized_value, $autoload );
45 }
46 return $normalized_value;
47 }
48
49 if ( false === get_option( ASENHA_SLUG_U ) ) {
50 global $wpdb;
51 // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
52 $asenha_exists_in_db = $wpdb->get_var( $wpdb->prepare( "SELECT COUNT(*) FROM {$wpdb->options} WHERE option_name = %s", ASENHA_SLUG_U ) );
53 if ( !$asenha_exists_in_db ) {
54 add_option(
55 ASENHA_SLUG_U,
56 array(),
57 '',
58 true
59 );
60 } else {
61 // Option exists in DB but cache returned false (stale persistent cache).
62 // Aggressively invalidate all cache layers including local in-process caches
63 // that some Redis/Memcached backends maintain separately from the external store.
64 wp_cache_delete( 'alloptions', 'options' );
65 wp_cache_delete( 'notoptions', 'options' );
66 if ( function_exists( 'wp_cache_flush' ) ) {
67 wp_cache_flush();
68 }
69 global $wp_object_cache;
70 if ( is_object( $wp_object_cache ) ) {
71 if ( property_exists( $wp_object_cache, 'local_cache' ) && is_array( $wp_object_cache->local_cache ) ) {
72 unset($wp_object_cache->local_cache['options']);
73 }
74 if ( property_exists( $wp_object_cache, 'cache' ) && is_array( $wp_object_cache->cache ) ) {
75 unset($wp_object_cache->cache['options']);
76 }
77 }
78 }
79 }
80 if ( false === get_option( ASENHA_SLUG_U . '_stats' ) ) {
81 global $wpdb;
82 // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
83 $asenha_stats_exists_in_db = $wpdb->get_var( $wpdb->prepare( "SELECT COUNT(*) FROM {$wpdb->options} WHERE option_name = %s", ASENHA_SLUG_U . '_stats' ) );
84 if ( !$asenha_stats_exists_in_db ) {
85 add_option(
86 ASENHA_SLUG_U . '_stats',
87 array(),
88 '',
89 false
90 );
91 } else {
92 // Option exists in DB but cache returned false (stale persistent cache).
93 // Aggressively invalidate all cache layers including local in-process caches.
94 wp_cache_delete( 'alloptions', 'options' );
95 wp_cache_delete( 'notoptions', 'options' );
96 if ( function_exists( 'wp_cache_flush' ) ) {
97 wp_cache_flush();
98 }
99 global $wp_object_cache;
100 if ( is_object( $wp_object_cache ) ) {
101 if ( property_exists( $wp_object_cache, 'local_cache' ) && is_array( $wp_object_cache->local_cache ) ) {
102 unset($wp_object_cache->local_cache['options']);
103 }
104 if ( property_exists( $wp_object_cache, 'cache' ) && is_array( $wp_object_cache->cache ) ) {
105 unset($wp_object_cache->cache['options']);
106 }
107 }
108 }
109 }
110 if ( false === get_option( ASENHA_SLUG_U . '_extra' ) ) {
111 global $wpdb;
112 // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
113 $asenha_extra_exists_in_db = $wpdb->get_var( $wpdb->prepare( "SELECT COUNT(*) FROM {$wpdb->options} WHERE option_name = %s", ASENHA_SLUG_U . '_extra' ) );
114 if ( !$asenha_extra_exists_in_db ) {
115 add_option(
116 ASENHA_SLUG_U . '_extra',
117 array(),
118 '',
119 true
120 );
121 } else {
122 // Option exists in DB but cache returned false (stale persistent cache).
123 // Aggressively invalidate all cache layers including local in-process caches.
124 wp_cache_delete( 'alloptions', 'options' );
125 wp_cache_delete( 'notoptions', 'options' );
126 if ( function_exists( 'wp_cache_flush' ) ) {
127 wp_cache_flush();
128 }
129 global $wp_object_cache;
130 if ( is_object( $wp_object_cache ) ) {
131 if ( property_exists( $wp_object_cache, 'local_cache' ) && is_array( $wp_object_cache->local_cache ) ) {
132 unset($wp_object_cache->local_cache['options']);
133 }
134 if ( property_exists( $wp_object_cache, 'cache' ) && is_array( $wp_object_cache->cache ) ) {
135 unset($wp_object_cache->cache['options']);
136 }
137 }
138 }
139 }
140 // Bugfix in v7.1.2 for Custom Content Type module
141 $options_extra = asenha_get_option_array( ASENHA_SLUG_U . '_extra', true );
142 if ( !isset( $options_extra['cfgroup_next_field_id'] ) ) {
143 $options_extra['cfgroup_next_field_id'] = 1;
144 update_option( ASENHA_SLUG_U . '_extra', $options_extra, true );
145 }
146 // Move Admin Menu Organizer options storage to extra table since v7.8.5
147 if ( !isset( $options_extra['admin_menu'] ) ) {
148 $options = asenha_get_option_array( ASENHA_SLUG_U, true );
149 $options_extra['admin_menu']['custom_menu_order'] = ( isset( $options['custom_menu_order'] ) ? $options['custom_menu_order'] : '' );
150 unset($options['custom_menu_order']);
151 $options_extra['admin_menu']['custom_menu_titles'] = ( isset( $options['custom_menu_titles'] ) ? $options['custom_menu_titles'] : '' );
152 unset($options['custom_menu_titles']);
153 $options_extra['admin_menu']['custom_menu_hidden'] = ( isset( $options['custom_menu_hidden'] ) ? trim( $options['custom_menu_hidden'], ',' ) : '' );
154 unset($options['custom_menu_hidden']);
155 update_option( ASENHA_SLUG_U . '_extra', $options_extra, true );
156 update_option( ASENHA_SLUG_U, $options, true );
157 }
158 /**
159 * Get the SMTP password storage status with backward-compatible fallbacks.
160 *
161 * This avoids fatal errors during mixed-version deployments where newer
162 * settings code may temporarily run against an older Email_Delivery class
163 * definition that does not yet provide the newer helper method/constants.
164 *
165 * @since 8.5.1
166 *
167 * @param string|null $stored_password Stored option value.
168 * @return string
169 */
170 function asenha_get_smtp_password_status_compat( $stored_password = null ) {
171 if ( null === $stored_password ) {
172 $options = asenha_get_option_array( ASENHA_SLUG_U, true );
173 $stored_password = ( isset( $options['smtp_password'] ) ? $options['smtp_password'] : '' );
174 }
175 $email_delivery = new \ASENHA\Classes\Email_Delivery();
176 if ( method_exists( $email_delivery, 'get_smtp_password_status' ) ) {
177 return $email_delivery->get_smtp_password_status( $stored_password );
178 }
179 if ( empty( $stored_password ) ) {
180 return 'empty';
181 }
182 if ( is_string( $stored_password ) && (0 === strpos( $stored_password, 'asenha_encrypted::smtp_password::v1::' ) || 0 === strpos( $stored_password, 'asenha_encrypted::smtp_password::v2::' )) ) {
183 return 'encrypted_invalid';
184 }
185 if ( is_string( $stored_password ) && 0 === strpos( $stored_password, 'asenha_encrypted::smtp_password::' ) ) {
186 return 'encrypted_invalid';
187 }
188 return 'legacy_plaintext';
189 }
190
191 /**
192 * Encrypt the SMTP password when the runtime supports the newer helper.
193 *
194 * @since 8.5.1
195 *
196 * @param \ASENHA\Classes\Email_Delivery $email_delivery Email delivery instance.
197 * @param string $password Plaintext SMTP password.
198 * @return string Encrypted payload or empty string when unsupported.
199 */
200 function asenha_encrypt_smtp_password_compat( $email_delivery, $password ) {
201 if ( !method_exists( $email_delivery, 'encrypt_smtp_password' ) ) {
202 return '';
203 }
204 return $email_delivery->encrypt_smtp_password( $password );
205 }
206
207 /**
208 * Migrate SMTP password storage to the current encrypted format.
209 *
210 * Upgrades legacy plaintext and decryptable v1 ciphertext to v2 automatically.
211 *
212 * @since 8.5.1
213 */
214 function asenha_migrate_smtp_password_storage() {
215 $options = asenha_get_option_array( ASENHA_SLUG_U, true );
216 if ( empty( $options['smtp_password'] ) ) {
217 return;
218 }
219 $email_delivery = new \ASENHA\Classes\Email_Delivery();
220 $stored_password = $options['smtp_password'];
221 if ( method_exists( $email_delivery, 'is_smtp_password_storage_version_v2' ) && $email_delivery->is_smtp_password_storage_version_v2() && method_exists( $email_delivery, 'is_smtp_password_v2_encrypted' ) && $email_delivery->is_smtp_password_v2_encrypted( $stored_password ) ) {
222 return;
223 }
224 $updated = false;
225 if ( method_exists( $email_delivery, 'is_smtp_password_v2_encrypted' ) && $email_delivery->is_smtp_password_v2_encrypted( $stored_password ) ) {
226 $plaintext_password = ( method_exists( $email_delivery, 'unwrap_smtp_password_to_plaintext' ) ? $email_delivery->unwrap_smtp_password_to_plaintext( $stored_password ) : false );
227 if ( false !== $plaintext_password && method_exists( $email_delivery, 'is_probable_smtp_ciphertext' ) && !$email_delivery->is_probable_smtp_ciphertext( $plaintext_password ) ) {
228 $email_delivery->mark_smtp_password_storage_version_v2();
229 return;
230 }
231 if ( false === $plaintext_password || method_exists( $email_delivery, 'is_probable_smtp_ciphertext' ) && $email_delivery->is_probable_smtp_ciphertext( $plaintext_password ) ) {
232 $email_delivery->set_smtp_password_unavailable_flag();
233 return;
234 }
235 } elseif ( method_exists( $email_delivery, 'is_smtp_password_v1_encrypted' ) && $email_delivery->is_smtp_password_v1_encrypted( $stored_password ) ) {
236 $plaintext_password = $email_delivery->decrypt_smtp_password( $stored_password );
237 if ( false !== $plaintext_password && method_exists( $email_delivery, 'is_probable_smtp_ciphertext' ) && !$email_delivery->is_probable_smtp_ciphertext( $plaintext_password ) ) {
238 $encrypted_smtp_password = asenha_encrypt_smtp_password_compat( $email_delivery, $plaintext_password );
239 if ( !empty( $encrypted_smtp_password ) ) {
240 $options['smtp_password'] = $encrypted_smtp_password;
241 $updated = true;
242 }
243 } elseif ( false !== $plaintext_password && method_exists( $email_delivery, 'is_probable_smtp_ciphertext' ) && $email_delivery->is_probable_smtp_ciphertext( $plaintext_password ) ) {
244 $email_delivery->set_smtp_password_unavailable_flag();
245 return;
246 }
247 } elseif ( method_exists( $email_delivery, 'is_probable_smtp_ciphertext' ) && $email_delivery->is_probable_smtp_ciphertext( $stored_password ) ) {
248 $email_delivery->set_smtp_password_unavailable_flag();
249 return;
250 } else {
251 $encrypted_smtp_password = asenha_encrypt_smtp_password_compat( $email_delivery, $stored_password );
252 if ( !empty( $encrypted_smtp_password ) ) {
253 $options['smtp_password'] = $encrypted_smtp_password;
254 $updated = true;
255 }
256 }
257 if ( $updated ) {
258 update_option( ASENHA_SLUG_U, $options, true );
259 if ( method_exists( $email_delivery, 'mark_smtp_password_storage_version_v2' ) ) {
260 $email_delivery->mark_smtp_password_storage_version_v2();
261 }
262 }
263 }
264
265 /**
266 * Repair nested SMTP password storage after migration.
267 *
268 * @since 8.8.6
269 */
270 function asenha_repair_nested_smtp_password_storage() {
271 $email_delivery = new \ASENHA\Classes\Email_Delivery();
272 if ( method_exists( $email_delivery, 'repair_nested_smtp_password_storage' ) ) {
273 $email_delivery->repair_nested_smtp_password_storage();
274 }
275 }
276
277 /**
278 * Run SMTP password storage migration and nested repair.
279 *
280 * @since 8.8.6
281 */
282 function asenha_run_smtp_password_storage_upgrades() {
283 asenha_migrate_smtp_password_storage();
284 asenha_repair_nested_smtp_password_storage();
285 }
286
287 if ( did_action( 'plugins_loaded' ) ) {
288 asenha_run_smtp_password_storage_upgrades();
289 } else {
290 add_action( 'plugins_loaded', 'asenha_run_smtp_password_storage_upgrades' );
291 }
292 /**
293 * Register admin menu
294 *
295 * @since 1.0.0
296 */
297 function asenha_register_admin_menu() {
298 add_submenu_page(
299 'tools.php',
300 // Parent page/menu
301 'Admin and Site Enhancements',
302 // Browser tab/window title
303 __( 'Enhancements', 'admin-site-enhancements' ),
304 // Sube menu title
305 'manage_options',
306 // Minimal user capabililty
307 ASENHA_SLUG,
308 // Page slug. Shows up in URL.
309 'asenha_add_settings_page'
310 );
311 }
312
313 /**
314 * Create the settings page of the plugin
315 *
316 * @since 1.0.0
317 */
318 function asenha_add_settings_page() {
319 $options = asenha_get_option_array( ASENHA_SLUG_U, true );
320 ?>
321 <div class="wrap asenha">
322
323 <div id="asenha-header" class="asenha-header">
324 <div class="asenha-header-left">
325 <img src="<?php
326 echo esc_html( ASENHA_URL ) . 'assets/img/ase_icon.png';
327 ?>" class="asenha-icon"/>
328 <h1 class="asenha-heading">
329 <?php
330 echo esc_html( get_admin_page_title() );
331 ?>
332 (ASE)
333 <?php
334 ?>
335 </h1>
336 <input id="module-search-input" type="search" placeholder="<?php
337 echo esc_attr__( 'Search...', 'admin-site-enhancements' );
338 ?>" />
339 <!-- <a href="https://wordpress.org/plugins/admin-site-enhancements/" target="_blank" class="asenha-header-action"><span>&#8505;</span> <?php
340 // esc_html_e( 'Info', 'admin-site-enhancements' );
341 ?></a> -->
342 </div>
343 <div class="asenha-header-right">
344 <?php
345 // https://icon-sets.iconify.design/iconamoon/star-bold/
346 $svg_star = '<svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24"><path fill="none" stroke="currentColor" stroke-linejoin="round" stroke-width="2.5" d="m12 2l3.104 6.728l7.358.873l-5.44 5.03l1.444 7.268L12 18.28L5.534 21.9l1.444-7.268L1.538 9.6l7.359-.873L12 2Z"/></svg>';
347 // https://icon-sets.iconify.design/octicon/question-16/
348 $svg_support = '<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16"><path fill="currentColor" d="M0 8a8 8 0 1 1 16 0A8 8 0 0 1 0 8Zm8-6.5a6.5 6.5 0 1 0 0 13a6.5 6.5 0 0 0 0-13ZM6.92 6.085h.001a.749.749 0 1 1-1.342-.67c.169-.339.436-.701.849-.977C6.845 4.16 7.369 4 8 4a2.756 2.756 0 0 1 1.637.525c.503.377.863.965.863 1.725c0 .448-.115.83-.329 1.15c-.205.307-.47.513-.692.662c-.109.072-.22.138-.313.195l-.006.004a6.24 6.24 0 0 0-.26.16a.952.952 0 0 0-.276.245a.75.75 0 0 1-1.248-.832c.184-.264.42-.489.692-.661c.103-.067.207-.132.313-.195l.007-.004c.1-.061.182-.11.258-.161a.969.969 0 0 0 .277-.245C8.96 6.514 9 6.427 9 6.25a.612.612 0 0 0-.262-.525A1.27 1.27 0 0 0 8 5.5c-.369 0-.595.09-.74.187a1.01 1.01 0 0 0-.34.398ZM9 11a1 1 0 1 1-2 0a1 1 0 0 1 2 0Z"/></svg>';
349 // https://icon-sets.iconify.design/octicon/comment-16/
350 $svg_feedback = '<svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 16 16"><path fill="currentColor" d="M1 2.75C1 1.784 1.784 1 2.75 1h10.5c.966 0 1.75.784 1.75 1.75v7.5A1.75 1.75 0 0 1 13.25 12H9.06l-2.573 2.573A1.458 1.458 0 0 1 4 13.543V12H2.75A1.75 1.75 0 0 1 1 10.25Zm1.75-.25a.25.25 0 0 0-.25.25v7.5c0 .138.112.25.25.25h2a.75.75 0 0 1 .75.75v2.19l2.72-2.72a.749.749 0 0 1 .53-.22h4.5a.25.25 0 0 0 .25-.25v-7.5a.25.25 0 0 0-.25-.25Z"/></svg>';
351 // https://icon-sets.iconify.design/ic/baseline-translate/
352 $svg_translate = '<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24"><path fill="currentColor" d="m12.87 15.07l-2.54-2.51l.03-.03A17.52 17.52 0 0 0 14.07 6H17V4h-7V2H8v2H1v1.99h11.17C11.5 7.92 10.44 9.75 9 11.35C8.07 10.32 7.3 9.19 6.69 8h-2c.73 1.63 1.73 3.17 2.98 4.56l-5.09 5.02L4 19l5-5l3.11 3.11zM18.5 10h-2L12 22h2l1.12-3h4.75L21 22h2zm-2.62 7l1.62-4.33L19.12 17z"/></svg>';
353 // https://icon-sets.iconify.design/iconamoon/file-document/
354 $svg_docs = '<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24"><g fill="none" stroke="currentColor" stroke-linejoin="round" stroke-width="2"><path stroke-linecap="round" d="M7 21a2 2 0 0 1-2-2V3h9l5 5v11a2 2 0 0 1-2 2H7Z"/><path d="M13 3v6h6"/><path stroke-linecap="round" d="M9 13h6m-6 4h6"/></g></svg>';
355 // https://icon-sets.iconify.design/pajamas/heart/
356 $svg_sponsor = '<svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 16 16"><path fill="currentColor" fill-rule="evenodd" d="M8.753 2.247L8 3l-.753-.753A4.243 4.243 0 0 0 1.25 8.25l5.69 5.69L8 15l1.06-1.06l5.69-5.69a4.243 4.243 0 0 0-5.997-6.003ZM8 12.879l5.69-5.69a2.743 2.743 0 0 0-3.877-3.881l-.752.753L8 5.12L6.94 4.06l-.753-.752v-.001A2.743 2.743 0 0 0 2.31 7.189L8 12.88Z" clip-rule="evenodd"/></svg>';
357 ?>
358 <a href="https://wordpress.org/plugins/admin-site-enhancements/#reviews" target="_blank" class="asenha-header-action review"><?php
359 echo wp_kses( $svg_star, get_kses_with_svg_ruleset() ) . esc_html__( 'Review', 'admin-site-enhancements' );
360 ?></a>
361 <a href="https://wordpress.org/support/plugin/admin-site-enhancements/" target="_blank" class="asenha-header-action feedback"><?php
362 echo wp_kses( $svg_feedback, get_kses_with_svg_ruleset() ) . esc_html__( 'Feedback', 'admin-site-enhancements' );
363 ?></a>
364 <a href="https://www.wpase.com/trnslt-plgnhdr" target="_blank" class="asenha-header-action translate"><?php
365 echo wp_kses( $svg_translate, get_kses_with_svg_ruleset() ) . esc_html__( 'Translate', 'admin-site-enhancements' );
366 ?></a>
367 <!--<a href="https://www.wpasenha.com/docs/" target="_blank" class="asenha-header-action docs"><?php
368 // echo $svg_docs . esc_html__( 'Docs', 'admin-site-enhancements' );
369 ?></a>-->
370 <!--<a id="plugin-sponsor" href="#" class="asenha-header-action sponsor"><?php
371 // echo $svg_sponsor . esc_html__( 'Sponsor', 'admin-site-enhancements' );
372 ?></a>-->
373 <a href="https://www.wpase.com/upgrade-btn" target="_blank" id="plugin-upgrade" class="button button-primary plugin-upgrade"><?php
374 echo esc_html__( 'Get ASE Pro', 'admin-site-enhancements' );
375 ?></a>
376 <?php
377 ?>
378 <a class="button button-primary asenha-save-button"><?php
379 echo esc_html__( 'Save Changes', 'admin-site-enhancements' );
380 ?></a>
381 <!-- https://icon-sets.iconify.design/svg-spinners/180-ring-with-bg/ -->
382 <div class="asenha-saving-changes" style="display:none;"><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><path fill="#2271b1" d="M12,1A11,11,0,1,0,23,12,11,11,0,0,0,12,1Zm0,19a8,8,0,1,1,8-8A8,8,0,0,1,12,20Z" opacity=".25"/><path fill="#2271b1" d="M12,4a8,8,0,0,1,7.89,6.7A1.53,1.53,0,0,0,21.38,12h0a1.5,1.5,0,0,0,1.48-1.75,11,11,0,0,0-21.72,0A1.5,1.5,0,0,0,2.62,12h0a1.53,1.53,0,0,0,1.49-1.3A8,8,0,0,1,12,4Z"><animateTransform attributeName="transform" dur="0.75s" repeatCount="indefinite" type="rotate" values="0 12 12;360 12 12"/></path></svg></div>
383 <div class="asenha-changes-saved" style="display:none;"><svg xmlns="http://www.w3.org/2000/svg" width="28" height="28" viewBox="0 0 24 24"><path fill="seagreen" d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10s10-4.48 10-10S17.52 2 12 2zM9.29 16.29L5.7 12.7a.996.996 0 1 1 1.41-1.41L10 14.17l6.88-6.88a.996.996 0 1 1 1.41 1.41l-7.59 7.59a.996.996 0 0 1-1.41 0z"/></svg></div>
384 </div>
385 </div>
386
387 <div class="asenha-body">
388 <?php
389 $is_yearend_promo_period = is_yearend_promo_period();
390 ?>
391 <?php
392 if ( $is_yearend_promo_period ) {
393 ?>
394 <!-- <div class="asenha-upgrade-nudge" style="display: none;">
395 <div class="asenha-upgrade-nudge__message"><?php
396 // echo esc_html__( 'Lifetime Deal (LTD) is available for the Pro version of ASE.', 'admin-site-enhancements' );
397 ?></div>
398 <a href="https://www.wpase.com/upgrade-ndg" class="button asenha-upgrade-nudge__button" target="_blank"><?php
399 // echo esc_html__( 'Find Out More', 'admin-site-enhancements' );
400 ?></a>
401 <a href="#" id="dismiss-upgrade-nudge" class="asenha-upgrade-nudge__dismiss">
402 <svg xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24"><path fill="currentColor" d="M24 2.4L21.6 0L12 9.6L2.4 0L0 2.4L9.6 12L0 21.6L2.4 24l9.6-9.6l9.6 9.6l2.4-2.4l-9.6-9.6z"/></svg>
403 </a>
404 </div> -->
405 <div class="asenha-promo-nudge" style="display: none;">
406 <div class="asenha-promo-nudge__message"><?php
407 echo esc_html__( 'ASE Pro YEAR-END SALE! 20% DISCOUNT. Lifetime Deal (LTD) available.', 'admin-site-enhancements' );
408 ?></div>
409 <a href="https://www.wpase.com/promo-ndg" class="button asenha-promo-nudge__button" target="_blank"><?php
410 echo esc_html__( 'Get It Now', 'admin-site-enhancements' );
411 ?></a>
412 <a href="#" id="dismiss-promo-nudge" class="asenha-promo-nudge__dismiss">
413 <svg xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24"><path fill="currentColor" d="M24 2.4L21.6 0L12 9.6L2.4 0L0 2.4L9.6 12L0 21.6L2.4 24l9.6-9.6l9.6 9.6l2.4-2.4l-9.6-9.6z"/></svg>
414 </a>
415 </div>
416 <?php
417 } else {
418 ?>
419 <div class="asenha-upgrade-nudge" style="display: none;">
420 <div class="asenha-upgrade-nudge__message"><?php
421 echo esc_html__( 'Lifetime Deal (LTD) is available for the Pro version of ASE.', 'admin-site-enhancements' );
422 ?></div>
423 <a href="https://www.wpase.com/upgrade-ndg" class="button asenha-upgrade-nudge__button" target="_blank"><?php
424 echo esc_html__( 'Find Out More', 'admin-site-enhancements' );
425 ?></a>
426 <a href="#" id="dismiss-upgrade-nudge" class="asenha-upgrade-nudge__dismiss">
427 <svg xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24"><path fill="currentColor" d="M24 2.4L21.6 0L12 9.6L2.4 0L0 2.4L9.6 12L0 21.6L2.4 24l9.6-9.6l9.6 9.6l2.4-2.4l-9.6-9.6z"/></svg>
428 </a>
429 </div>
430 <?php
431 }
432 ?>
433 <?php
434 ?>
435 <div class="asenha-support-nudge nudge-show-more is-enabled" style="display: none;">
436 <h3><?php
437 _e( 'Looks like some of these free enhancements have been useful for your site?', 'admin-site-enhancements' );
438 ?></h3>
439 <p class="nudge-description intro"><?php
440 _e( 'Please consider supporting ASE.', 'admin-site-enhancements' );
441 ?></p>
442 <div class="nudge-content">
443 <div class="nudge-primary">
444 <h4><?php
445 _e( 'Write a quick, 5-star review for ASE', 'admin-site-enhancements' );
446 ?></h4>
447 <div class="nudge-ctas">
448 <a href="https://wordpress.org/plugins/admin-site-enhancements/#reviews" target="_blank" class="button button-outline asenha-review-button"><?php
449 _e( 'Add Your Review', 'admin-site-enhancements' );
450 ?></a>
451 <a href="#" id="have-reviewed" class="asenha-have-supported"><?php
452 _e( 'I\'ve reviewed', 'admin-site-enhancements' );
453 ?></a>
454 </div>
455 <p class="nudge-description"><?php
456 _e( 'Or, help improve ASE by <a href="https://wordpress.org/support/plugin/admin-site-enhancements/" target="_blank">providing feedback</a>.', 'admin-site-enhancements' );
457 ?></p>
458 </div>
459 <div class="nudge-secondary">
460 <h4><?php
461 _e( 'Share about ASE on:', 'admin-site-enhancements' );
462 ?></h4>
463 <div class="nudge-ctas">
464 <a href="https://www.facebook.com/sharer.php?u=<?php
465 echo urlencode( 'https://www.wpase.com' );
466 ?>" target="_blank" class="button button-outline asenha-share-button"><?php
467 _e( 'Facebook', 'admin-site-enhancements' );
468 ?></a>
469 <a href="https://twitter.com/intent/post?url=<?php
470 echo urlencode( 'https://www.wpase.com' );
471 ?>&text=<?php
472 echo esc_attr( urlencode( 'Admin and Site Enhancements (ASE)' ) );
473 ?>" target="_blank" class="button button-outline asenha-share-button"><?php
474 _e( 'X / Twitter', 'admin-site-enhancements' );
475 ?></a>
476 <a href="https://www.wpase.com/video-reviews/" target="_blank" class="button button-outline asenha-share-button"><?php
477 _e( 'YouTube', 'admin-site-enhancements' );
478 ?></a>
479 <a href="#" id="have-shared" class="asenha-have-supported"><?php
480 _e( 'I\'ve shared', 'admin-site-enhancements' );
481 ?></a>
482 </div>
483 <div class="nudge-info">
484 <p class="nudge-description"><?php
485 _e( 'Help others discover ASE and maybe <a href="https://www.wpase.com/trnslt-plgnndg" target="_blank">translate</a> to your language.', 'admin-site-enhancements' );
486 ?></p>
487 </div>
488 </div>
489 </div>
490 <div class="dismiss-support-nudge"><a href="#" id="support-nudge-dismiss" class="asenha-support-nudge-dismiss"><?php
491 _e( 'Dismiss', 'admin-site-enhancements' );
492 ?></a></div>
493 </div>
494 <?php
495 ?>
496 <form action="options.php" method="post">
497 <div class="asenha-vertical-tabs">
498 <div class="asenha-tab-buttons">
499 <?php
500 // https://icon-sets.iconify.design/mdi/database-check-outline/ -- db check
501 // https://icon-sets.iconify.design/mdi/file-document-box-multiple-outline/ -- docs
502 // https://icon-sets.iconify.design/fluent/content-view-28-regular/ -- content
503 // https://icon-sets.iconify.design/lucide/shapes/ -- shapes
504 $icon_content_management = '<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"><path d="M8.3 10a.7.7 0 0 1-.626-1.079L11.4 3a.7.7 0 0 1 1.198-.043L16.3 8.9a.7.7 0 0 1-.572 1.1Z"/><rect width="7" height="7" x="3" y="14" rx="1"/><circle cx="17.5" cy="17.5" r="3.5"/></g></svg>';
505 // https://icon-sets.iconify.design/mingcute/layout-line/
506 $icon_admin_interface = '<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="none" fill-rule="evenodd"><path d="M24 0v24H0V0h24ZM12.593 23.258l-.011.002l-.071.035l-.02.004l-.014-.004l-.071-.035c-.01-.004-.019-.001-.024.005l-.004.01l-.017.428l.005.02l.01.013l.104.074l.015.004l.012-.004l.104-.074l.012-.016l.004-.017l-.017-.427c-.002-.01-.009-.017-.017-.018Zm.265-.113l-.013.002l-.185.093l-.01.01l-.003.011l.018.43l.005.012l.008.007l.201.093c.012.004.023 0 .029-.008l.004-.014l-.034-.614c-.003-.012-.01-.02-.02-.022Zm-.715.002a.023.023 0 0 0-.027.006l-.006.014l-.034.614c0 .012.007.02.017.024l.015-.002l.201-.093l.01-.008l.004-.011l.017-.43l-.003-.012l-.01-.01l-.184-.092Z"/><path fill="currentColor" d="M3 5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2v14a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V5Zm16 0H5v3h14V5ZM5 19v-9h4v9H5Zm6 0h8v-9h-8v9Z"/></g></svg>';
507 // https://icon-sets.iconify.design/ri/login-circle-line/
508 $icon_login_logout = '<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><path fill="currentColor" d="m10.998 16l5-4l-5-4v3h-9v2h9z"/><path fill="currentColor" d="M12.999 2.999a8.938 8.938 0 0 0-6.364 2.637L8.049 7.05c1.322-1.322 3.08-2.051 4.95-2.051s3.628.729 4.95 2.051S20 10.13 20 12s-.729 3.628-2.051 4.95s-3.08 2.051-4.95 2.051s-3.628-.729-4.95-2.051l-1.414 1.414c1.699 1.7 3.959 2.637 6.364 2.637s4.665-.937 6.364-2.637C21.063 16.665 22 14.405 22 12s-.937-4.665-2.637-6.364a8.938 8.938 0 0 0-6.364-2.637z"/></svg>';
509 // https://icon-sets.iconify.design/mingcute/code-line/
510 $icon_custom_code = '<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="none"><path d="M0 0h24v24H0z"/><path fill="currentColor" d="M14.486 3.143a1 1 0 0 1 .692 1.233l-4.43 15.788a1 1 0 0 1-1.926-.54l4.43-15.788a1 1 0 0 1 1.234-.693ZM7.207 7.05a1 1 0 0 1 0 1.414L3.672 12l3.535 3.535a1 1 0 1 1-1.414 1.415L1.55 12.707a1 1 0 0 1 0-1.414L5.793 7.05a1 1 0 0 1 1.414 0Zm9.586 1.414a1 1 0 1 1 1.414-1.414l4.243 4.243a1 1 0 0 1 0 1.414l-4.243 4.242a1 1 0 0 1-1.414-1.414L20.328 12l-3.535-3.536Z"/></g></svg>';
511 // https://icon-sets.iconify.design/mdi/forbid/
512 $icon_disable_components = '<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><path fill="currentColor" d="M12 2c5.5 0 10 4.5 10 10s-4.5 10-10 10S2 17.5 2 12S6.5 2 12 2m0 2c-1.9 0-3.6.6-4.9 1.7l11.2 11.2c1-1.4 1.7-3.1 1.7-4.9c0-4.4-3.6-8-8-8m4.9 14.3L5.7 7.1C4.6 8.4 4 10.1 4 12c0 4.4 3.6 8 8 8c1.9 0 3.6-.6 4.9-1.7Z"/></svg>';
513 // https://icon-sets.iconify.design/jam/shield-check/
514 $icon_security = '<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 16 16"><g fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5"><path d="m8 1.75l5.25 2v5c0 2.25-2 4.5-5.25 5.5c-3.25-1-5.25-3-5.25-5.5v-5z"/><path d="m5.75 7.75l1.5 1.5l3-3.5"/></g></svg>';
515 // https://icon-sets.iconify.design/streamline/image-flash-1-flash-power-connect-charge-electricity-lightning/
516 $icon_optimizations = '<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 14 14"><path fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" d="M4.25.5L2 5.81a.5.5 0 0 0 .46.69h2.79l-2 7l8.59-8.14a.5.5 0 0 0-.34-.86H7.75l2-4Z"/></svg>';
517 // https://icon-sets.iconify.design/iconoir/tools/
518 $icon_utilities = '<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5"><path d="m10.05 10.607l-7.07 7.07a2 2 0 0 0 0 2.83v0a2 2 0 0 0 2.828 0l7.07-7.072m4.315.365l3.878 3.878a2 2 0 0 1 0 2.828v0a2 2 0 0 1-2.828 0l-6.209-6.208M6.733 5.904L4.61 6.61L2.49 3.075l1.414-1.414L7.44 3.782l-.707 2.122Zm0 0l2.83 2.83"/><path d="M10.05 10.607c-.844-2.153-.679-4.978 1.061-6.718c1.74-1.74 4.95-2.121 6.717-1.06l-3.04 3.04l-.283 3.111l3.111-.282l3.04-3.041c1.062 1.768.68 4.978-1.06 6.717c-1.74 1.74-4.564 1.905-6.717 1.061"/></g></svg>';
519 ?>
520 <input id="tab-content-management" type="radio" name="tabs" checked><label for="tab-content-management" class="modules-tab"><?php
521 echo wp_kses( $icon_content_management, get_kses_with_svg_ruleset() );
522 ?><span><?php
523 echo esc_html__( 'Content Management', 'admin-site-enhancements' );
524 ?></span></label>
525 <input id="tab-admin-interface" type="radio" name="tabs"><label for="tab-admin-interface" class="modules-tab"><?php
526 echo wp_kses( $icon_admin_interface, get_kses_with_svg_ruleset() );
527 ?><span><?php
528 echo esc_html__( 'Admin Interface', 'admin-site-enhancements' );
529 ?></span></label>
530 <input id="tab-login-logout" type="radio" name="tabs"><label for="tab-login-logout" class="modules-tab"><?php
531 echo wp_kses( $icon_login_logout, get_kses_with_svg_ruleset() );
532 ?><span><?php
533 echo esc_html__( 'Log In/Out | Register', 'admin-site-enhancements' );
534 ?></span></label>
535 <input id="tab-custom-code" type="radio" name="tabs"><label for="tab-custom-code" class="modules-tab"><?php
536 echo wp_kses( $icon_custom_code, get_kses_with_svg_ruleset() );
537 ?><span><?php
538 echo esc_html__( 'Custom Code', 'admin-site-enhancements' );
539 ?></span></label>
540 <input id="tab-disable-components" type="radio" name="tabs"><label for="tab-disable-components" class="modules-tab"><?php
541 echo wp_kses( $icon_disable_components, get_kses_with_svg_ruleset() );
542 ?><span><?php
543 echo esc_html__( 'Disable Components', 'admin-site-enhancements' );
544 ?></span></label>
545 <input id="tab-security" type="radio" name="tabs"><label for="tab-security" class="modules-tab"><?php
546 echo wp_kses( $icon_security, get_kses_with_svg_ruleset() );
547 ?><span><?php
548 echo esc_html__( 'Security', 'admin-site-enhancements' );
549 ?></span></label>
550 <input id="tab-optimizations" type="radio" name="tabs"><label for="tab-optimizations" class="modules-tab"><?php
551 echo wp_kses( $icon_optimizations, get_kses_with_svg_ruleset() );
552 ?><span><?php
553 echo esc_html__( 'Optimizations', 'admin-site-enhancements' );
554 ?></span></label>
555 <input id="tab-utilities" type="radio" name="tabs"><label for="tab-utilities" class="modules-tab"><?php
556 echo wp_kses( $icon_utilities, get_kses_with_svg_ruleset() );
557 ?><span><?php
558 echo esc_html__( 'Utilities', 'admin-site-enhancements' );
559 ?></span></label>
560 <label for="tab-search" class="search-tab" style="display:none;height:52px;"><span><?php
561 echo esc_html__( 'Search results:', 'admin-site-enhancements' );
562 ?></span></label>
563 </div>
564 <div class="asenha-tab-contents">
565 <section class="asenha-fields fields-content-management">
566 <table class="form-table" role="presentation">
567 <tbody></tbody>
568 </table>
569 </section>
570 <section class="asenha-fields fields-admin-interface">
571 <table class="form-table" role="presentation">
572 <tbody></tbody>
573 </table>
574 </section>
575 <section class="asenha-fields fields-login-logout">
576 <table class="form-table" role="presentation">
577 <tbody></tbody>
578 </table>
579 </section>
580 <section class="asenha-fields fields-custom-code">
581 <table class="form-table" role="presentation">
582 <tbody></tbody>
583 </table>
584 </section>
585 <section class="asenha-fields fields-disable-components">
586 <table class="form-table" role="presentation">
587 <tbody></tbody>
588 </table>
589 </section>
590 <section class="asenha-fields fields-security">
591 <table class="form-table" role="presentation">
592 <tbody></tbody>
593 </table>
594 </section>
595 <section class="asenha-fields fields-optimizations">
596 <table class="form-table" role="presentation">
597 <tbody></tbody>
598 </table>
599 </section>
600 <section class="asenha-fields fields-utilities">
601 <table class="form-table" role="presentation">
602 <tbody></tbody>
603 </table>
604 </section>
605 </div>
606 </div>
607 <div style="display:none;"><!-- Hide to prevent flash of fields appearing at the bottom of the page -->
608 <?php
609 settings_fields( ASENHA_ID );
610 ?>
611 <?php
612 do_settings_sections( ASENHA_SLUG );
613 ?>
614 <?php
615 submit_button(
616 __( 'Save Changes', 'admin-site-enhancements' ),
617 // Button copy
618 'primary',
619 // Type: 'primary', 'small', or 'large'
620 'submit',
621 // The 'name' attribute
622 true,
623 // Whether to wrap in <p> tag
624 array(
625 'id' => 'asenha-submit',
626 )
627 );
628 ?>
629 </div>
630 </form>
631 <?php
632 ?>
633 <div id="bottom-upgrade-nudge" class="asenha-upgrade-nudge-bottom" style="display:none;">
634 <div class="asenha-upgrade-nudge-bottom__message"><?php
635 echo __( 'Do more with <a href="https://www.wpase.com/upgrade-ndg-btm" target="_blank">ASE Pro</a>. Lifetime deal (LTD) <a href="https://www.wpase.com/upgrade-ndg-btm-prc" target="_blank">available</a>.', 'admin-site-enhancements' );
636 ?> <?php
637 if ( $is_yearend_promo_period ) {
638 echo __( 'Currently on YEAR-END SALE. <a href="https://www.wpase.com/promo-ndg" target="_blank">20% discount</a>.', 'admin-site-enhancements' );
639 }
640 ?></div>
641 </div>
642 <?php
643 ?>
644 </div>
645
646 <?php
647 ?>
648
649 </div>
650 <?php
651 // Record the number of times changes were saved as well as the date of last save
652 $asenha_stats = asenha_get_option_array( ASENHA_SLUG_U . '_stats', false );
653 $changes_saved = ( isset( $_GET['settings-updated'] ) && 'true' == $_GET['settings-updated'] ? true : false );
654 if ( $changes_saved ) {
655 $current_date = date( 'Y-m-d', time() );
656 if ( !isset( $asenha_stats['first_save_date'] ) ) {
657 $asenha_stats['first_save_date'] = $current_date;
658 $asenha_stats['last_save_date'] = $current_date;
659 $asenha_stats['save_count'] = 1;
660 $asenha_stats['have_supported'] = false;
661 $asenha_stats['support_nudge_dismissed'] = false;
662 $asenha_stats['support_nudge_last_shown_date'] = '';
663 $asenha_stats['support_nudge_last_shown_save_count'] = 0;
664 } else {
665 $asenha_stats['last_save_date'] = $current_date;
666 $save_count = $asenha_stats['save_count'];
667 $save_count++;
668 $asenha_stats['save_count'] = $save_count;
669 }
670 update_option( ASENHA_SLUG_U . '_stats', $asenha_stats, false );
671 }
672 }
673
674 /**
675 * Check whether it's the year-end promo period
676 *
677 * @since 7.8.11
678 */
679 function is_yearend_promo_period() {
680 // For year end promo between October 1 to December 31
681 $current_month = intval( date( 'n', time() ) );
682 // n is for numeric value of month, 1 to 12
683 if ( $current_month >= 10 ) {
684 $is_yearend_promo_period = true;
685 // Clear out last year's promo nudge dismissal data
686 $current_year = date( 'Y', time() );
687 $asenha_stats = asenha_get_option_array( ASENHA_SLUG_U . '_stats', false );
688 if ( isset( $asenha_stats['promo_nudge_dismissed'] ) && $asenha_stats['promo_nudge_dismissed'] ) {
689 $last_dismissed_year = date( 'Y', strtotime( $asenha_stats['promo_nudge_dismissed_date'] ) );
690 if ( $current_year > $last_dismissed_year ) {
691 $asenha_stats['promo_nudge_dismissed'] = false;
692 $asenha_stats['promo_nudge_dismissed_date'] = '';
693 update_option( ASENHA_SLUG_U . '_stats', $asenha_stats, false );
694 }
695 }
696 } else {
697 $is_yearend_promo_period = false;
698 }
699 // For year end promo between November 15 to December 31
700 // $tz = wp_timezone(); // WordPress timezone; or: new DateTimeZone('UTC')
701 // $current_date = new DateTimeImmutable('now', $tz);
702 // // $current_date = new DateTimeImmutable('2025-11-15', $tz); // For testing
703 // // $current_date = new DateTimeImmutable('2026-01-01', $tz); // For testing
704 // // $current_date = new DateTimeImmutable('2027-11-15', $tz); // For testing
705 // $year = (int) $current_date->format('Y');
706 // $start = new DateTimeImmutable("$year-11-15 00:00:00", $tz);
707 // $end = new DateTimeImmutable("$year-12-31 23:59:59", $tz);
708 // $is_between = ($current_date >= $start && $current_date <= $end);
709 // if ( $is_between ) {
710 // $is_yearend_promo_period = true;
711 // } else {
712 // $is_yearend_promo_period = false;
713 // }
714 // // Clear out last year's promo nudge dismissal data
715 // if ( $is_yearend_promo_period ) {
716 // $current_year = $year;
717 // $asenha_stats = get_option( ASENHA_SLUG_U . '_stats', array() );
718 // if ( isset( $asenha_stats['promo_nudge_dismissed'] ) && $asenha_stats['promo_nudge_dismissed'] ) {
719 // $last_dismissed_year = date( 'Y', strtotime( $asenha_stats['promo_nudge_dismissed_date'] ) );
720 // if ( $current_year > $last_dismissed_year ) {
721 // $asenha_stats['promo_nudge_dismissed'] = false;
722 // $asenha_stats['promo_nudge_dismissed_date'] = '';
723 // update_option( ASENHA_SLUG_U . '_stats', $asenha_stats, false );
724 // }
725 // }
726 // }
727 return $is_yearend_promo_period;
728 }
729
730 /**
731 * Suppress all notices, then add notice for successful settings update
732 *
733 * @since 1.1.0
734 */
735 function asenha_suppress_add_notices() {
736 global $plugin_page;
737 // Suppress all notices
738 if ( ASENHA_SLUG === $plugin_page ) {
739 remove_all_actions( 'admin_notices' );
740 }
741 // Add notice for successful settings update
742 if ( isset( $_GET['page'] ) && ASENHA_SLUG == $_GET['page'] && isset( $_GET['settings-updated'] ) && true == $_GET['settings-updated'] ) {
743 ?>
744 <script>
745 jQuery(document).ready( function() {
746 jQuery('.asenha-changes-saved').fadeIn(400).delay(2500).fadeOut(400);
747 });
748 </script>
749
750 <?php
751 }
752 }
753
754 /**
755 * Suppress all generic notices on the plugin settings page
756 *
757 * @since 2.7.0
758 */
759 function asenha_suppress_generic_notices() {
760 global $plugin_page;
761 // Suppress all notices
762 if ( ASENHA_SLUG === $plugin_page ) {
763 remove_all_actions( 'all_admin_notices' );
764 }
765 }
766
767 /**
768 * Enqueue admin scripts
769 *
770 * @since 1.0.0
771 */
772 function asenha_admin_scripts( $hook_suffix ) {
773 global
774 $wp_version,
775 $pagenow,
776 $typenow,
777 $taxnow,
778 $hook_suffix,
779 $current_user
780 ;
781 $current_screen = get_current_screen();
782 // Get all WP Enhancements options, default to empty array in case it's not been created yet
783 $options = asenha_get_option_array( 'admin_site_enhancements', true );
784 // For main page of this plugin
785 if ( is_asenha() ) {
786 wp_enqueue_style(
787 'asenha-jbox',
788 ASENHA_URL . 'assets/css/jBox.all.min.css',
789 array(),
790 ASENHA_VERSION
791 );
792 wp_enqueue_script(
793 'asenha-jbox',
794 ASENHA_URL . 'assets/js/jBox.all.min.js',
795 array(),
796 ASENHA_VERSION,
797 false
798 );
799 wp_enqueue_script(
800 'asenha-jsticky',
801 ASENHA_URL . 'assets/js/jquery.jsticky.mod.min.js',
802 array('jquery'),
803 ASENHA_VERSION,
804 false
805 );
806 wp_enqueue_script(
807 'asenha-js-cookie',
808 ASENHA_URL . 'assets/js/js.cookie.min.js',
809 array(),
810 ASENHA_VERSION,
811 false
812 );
813 // First, we unload the CodeMirror libraries included in WP core
814 wp_deregister_script( 'wp-codemirror' );
815 wp_deregister_script( 'code-editor' );
816 wp_deregister_script( 'htmlhint' );
817 wp_deregister_script( 'csslint' );
818 wp_deregister_script( 'esprima' );
819 wp_deregister_script( 'jshint' );
820 // Then, we load ASENHA's CodeMirror libraries. In use, e.g. for Utilities >> Enable Custom Admin / Frontend CSS / ads.txt / app-ads.txt
821 wp_enqueue_style(
822 'asenha-codemirror',
823 ASENHA_URL . 'assets/css/codemirror/codemirror.min.css',
824 array(),
825 ASENHA_VERSION
826 );
827 wp_enqueue_script(
828 'asenha-codemirror',
829 ASENHA_URL . 'assets/js/codemirror/codemirror.min.js',
830 array('jquery'),
831 ASENHA_VERSION,
832 true
833 );
834 wp_enqueue_script(
835 'asenha-codemirror-htmlmixed-mode',
836 ASENHA_URL . 'assets/js/codemirror/htmlmixed.js',
837 array('asenha-codemirror'),
838 ASENHA_VERSION,
839 true
840 );
841 wp_enqueue_script(
842 'asenha-codemirror-xml-mode',
843 ASENHA_URL . 'assets/js/codemirror/xml.js',
844 array('asenha-codemirror'),
845 ASENHA_VERSION,
846 true
847 );
848 wp_enqueue_script(
849 'asenha-codemirror-javascript-mode',
850 ASENHA_URL . 'assets/js/codemirror/javascript.js',
851 array('asenha-codemirror'),
852 ASENHA_VERSION,
853 true
854 );
855 wp_enqueue_script(
856 'asenha-codemirror-css-mode',
857 ASENHA_URL . 'assets/js/codemirror/css.js',
858 array('asenha-codemirror'),
859 ASENHA_VERSION,
860 true
861 );
862 wp_enqueue_script(
863 'asenha-codemirror-markdown-mode',
864 ASENHA_URL . 'assets/js/codemirror/markdown.js',
865 array('asenha-codemirror'),
866 ASENHA_VERSION,
867 true
868 );
869 // DataTables. In use, e.g. for Security >> Limit Login Attempts
870 wp_enqueue_style(
871 'asenha-datatables',
872 ASENHA_URL . 'assets/css/datatables/datatables.min.css',
873 array(),
874 ASENHA_VERSION
875 );
876 wp_enqueue_script(
877 'asenha-datatables',
878 ASENHA_URL . 'assets/js/datatables/datatables.min.js',
879 array('jquery'),
880 ASENHA_VERSION,
881 false
882 );
883 // Add WP media library assets
884 wp_enqueue_media();
885 // Add WP color picker assets
886 wp_enqueue_style( 'wp-color-picker' );
887 wp_enqueue_script( 'wp-color-picker' );
888 // We force loading the uncompressed version of TinyMCE. This ensures we load 'wp-tinymce-root' and then 'wp-tinymce',
889 // which prevents issue where the Visual tab is unusable in some scenarios
890 $wp_scripts = wp_scripts();
891 $wp_scripts->remove( 'wp-tinymce' );
892 wp_register_tinymce_scripts( $wp_scripts, true );
893 $admin_page_script_dependencies = array(
894 'asenha-jsticky',
895 'asenha-jbox',
896 'asenha-js-cookie',
897 'asenha-codemirror-htmlmixed-mode',
898 'asenha-codemirror-xml-mode',
899 'asenha-codemirror-javascript-mode',
900 'asenha-codemirror-css-mode',
901 'asenha-codemirror-markdown-mode',
902 'asenha-datatables',
903 'wp-color-picker',
904 'wp-mediaelement',
905 'wp-tinymce-root',
906 'wp-tinymce'
907 );
908 // Main style and script for the admin page
909 wp_enqueue_style(
910 'asenha-admin-page',
911 ASENHA_URL . 'assets/css/admin-page.css',
912 array(
913 'asenha-jbox',
914 'asenha-codemirror',
915 'asenha-datatables',
916 'wp-color-picker'
917 ),
918 ASENHA_VERSION
919 );
920 wp_enqueue_script(
921 'asenha-admin-page',
922 ASENHA_URL . 'assets/js/admin-page.js',
923 $admin_page_script_dependencies,
924 ASENHA_VERSION,
925 false
926 );
927 $jsvars = array(
928 'nonce' => wp_create_nonce( 'asenha-' . get_current_user_id() ),
929 'siteUrl' => get_site_url(),
930 'wpcontentUrl' => content_url(),
931 'mediaFrameTitle' => __( 'Select an Image', 'admin-site-enhancements' ),
932 'mediaFrameButtonText' => __( 'Use Selected Image', 'admin-site-enhancements' ),
933 'resetMenuNonce' => wp_create_nonce( 'reset-menu-nonce' ),
934 'sendTestEmailNonce' => wp_create_nonce( 'send-test-email-nonce_' . get_current_user_id() ),
935 'formBuilderSendTestEmailNonce' => wp_create_nonce( 'formbuilder_ajax' ),
936 'expandText' => __( 'Expand', 'admin-site-enhancements' ),
937 'collapseText' => __( 'Collapse', 'admin-site-enhancements' ),
938 'dataTable' => array(
939 'emptyTable' => __( 'No data available in table', 'admin-site-enhancements' ),
940 'info' => __( 'Showing _START_ to _END_ of _TOTAL_ entries', 'admin-site-enhancements' ),
941 'infoEmpty' => __( 'Showing 0 to 0 of 0 entries', 'admin-site-enhancements' ),
942 'infoFiltered' => __( '(filtered from _MAX_ total entries)', 'admin-site-enhancements' ),
943 'lengthMenu' => __( 'Show _MENU_ entries', 'admin-site-enhancements' ),
944 'search' => __( 'Search:', 'admin-site-enhancements' ),
945 'zeroRecords' => __( 'No matching records found', 'admin-site-enhancements' ),
946 'paginate' => array(
947 'first' => __( 'First', 'admin-site-enhancements' ),
948 'last' => __( 'Last', 'admin-site-enhancements' ),
949 'next' => __( 'Next', 'admin-site-enhancements' ),
950 'previous' => __( 'Previous', 'admin-site-enhancements' ),
951 ),
952 ),
953 'limitLoginAttempts' => array(
954 'releaseLockSuccess' => __( 'Lock released for %s.', 'admin-site-enhancements' ),
955 'releaseLockError' => __( 'Could not release lock. Please try again.', 'admin-site-enhancements' ),
956 ),
957 );
958 wp_localize_script( 'asenha-admin-page', 'adminPageVars', $jsvars );
959 }
960 // Enqueue on all wp-admin
961 wp_enqueue_style(
962 'asenha-wp-admin',
963 ASENHA_URL . 'assets/css/wp-admin.css',
964 array(),
965 ASENHA_VERSION
966 );
967 // Content Management >> Show IDs, for list tables in wp-admin, e.g. All Posts page
968 if ( false !== strpos( $current_screen->base, 'edit' ) || false !== strpos( $current_screen->base, 'users' ) || false !== strpos( $current_screen->base, 'upload' ) ) {
969 wp_enqueue_style(
970 'asenha-list-table',
971 ASENHA_URL . 'assets/css/list-table.css',
972 array(),
973 ASENHA_VERSION
974 );
975 }
976 // Content Management >> Enable Media Replacement
977 if ( $current_screen->base == 'upload' || $current_screen->id == 'attachment' ) {
978 // wp_enqueue_style( 'asenha-jbox', ASENHA_URL . 'assets/css/jBox.all.min.css', array(), ASENHA_VERSION );
979 // wp_enqueue_script( 'asenha-jbox', ASENHA_URL . 'assets/js/jBox.all.min.js', array(), ASENHA_VERSION, false );
980 wp_enqueue_media();
981 wp_enqueue_style(
982 'asenha-media-replace',
983 ASENHA_URL . 'assets/css/media-replace.css',
984 array(),
985 ASENHA_VERSION
986 );
987 wp_enqueue_script(
988 'asenha-media-replace',
989 ASENHA_URL . 'assets/js/media-replace.js',
990 array('media-editor'),
991 ASENHA_VERSION,
992 false
993 );
994 $media_replace = array(
995 'selectMediaText' => __( 'Select New Media File', 'admin-site-enhancements' ),
996 'performReplacementText' => __( 'Perform Replacement', 'admin-site-enhancements' ),
997 );
998 wp_localize_script( 'asenha-media-replace', 'mediaReplace', $media_replace );
999 }
1000 // Admin Interface >> Admin Menu Organizer
1001 if ( 'settings_page_admin-menu-organizer' == $current_screen->base ) {
1002 // Re-register and re-enqueue jQuery UI Core and plugins required for sortable, draggable and droppable when ordering menu items
1003 wp_deregister_script( 'jquery-ui-core' );
1004 wp_register_script(
1005 'jquery-ui-core',
1006 get_site_url() . '/wp-includes/js/jquery/ui/core.min.js',
1007 array('jquery'),
1008 ASENHA_VERSION,
1009 false
1010 );
1011 wp_enqueue_script( 'jquery-ui-core' );
1012 if ( version_compare( $wp_version, '5.6.0', '>=' ) ) {
1013 wp_deregister_script( 'jquery-ui-mouse' );
1014 wp_register_script(
1015 'jquery-ui-mouse',
1016 get_site_url() . '/wp-includes/js/jquery/ui/mouse.min.js',
1017 array('jquery-ui-core'),
1018 ASENHA_VERSION,
1019 false
1020 );
1021 wp_enqueue_script( 'jquery-ui-mouse' );
1022 } else {
1023 wp_deregister_script( 'jquery-ui-widget' );
1024 wp_register_script(
1025 'jquery-ui-widget',
1026 get_site_url() . '/wp-includes/js/jquery/ui/widget.min.js',
1027 array('jquery'),
1028 ASENHA_VERSION,
1029 false
1030 );
1031 wp_enqueue_script( 'jquery-ui-widget' );
1032 wp_deregister_script( 'jquery-ui-mouse' );
1033 wp_register_script(
1034 'jquery-ui-mouse',
1035 get_site_url() . '/wp-includes/js/jquery/ui/mouse.min.js',
1036 array('jquery-ui-core', 'jquery-ui-widget'),
1037 ASENHA_VERSION,
1038 false
1039 );
1040 wp_enqueue_script( 'jquery-ui-mouse' );
1041 }
1042 wp_deregister_script( 'jquery-ui-sortable' );
1043 wp_register_script(
1044 'jquery-ui-sortable',
1045 get_site_url() . '/wp-includes/js/jquery/ui/sortable.min.js',
1046 array('jquery-ui-mouse'),
1047 ASENHA_VERSION,
1048 false
1049 );
1050 wp_enqueue_script( 'jquery-ui-sortable' );
1051 wp_deregister_script( 'jquery-ui-draggable' );
1052 wp_register_script(
1053 'jquery-ui-draggable',
1054 get_site_url() . '/wp-includes/js/jquery/ui/draggable.min.js',
1055 array('jquery-ui-mouse'),
1056 ASENHA_VERSION,
1057 false
1058 );
1059 wp_enqueue_script( 'jquery-ui-draggable' );
1060 wp_deregister_script( 'jquery-ui-droppable' );
1061 wp_register_script(
1062 'jquery-ui-droppable',
1063 get_site_url() . '/wp-includes/js/jquery/ui/droppable.min.js',
1064 array('jquery-ui-draggable'),
1065 ASENHA_VERSION,
1066 false
1067 );
1068 wp_enqueue_script( 'jquery-ui-droppable' );
1069 // Script to set behaviour and actions of the sortable menu
1070 wp_enqueue_script(
1071 'asenha-custom-admin-menu',
1072 ASENHA_URL . 'assets/js/custom-admin-menu.js',
1073 array('jquery-ui-draggable'),
1074 ASENHA_VERSION,
1075 false
1076 );
1077 wp_enqueue_style(
1078 'asenha-admin-menu-organizer',
1079 ASENHA_URL . 'assets/css/admin-menu-organizer.css',
1080 array(),
1081 ASENHA_VERSION
1082 );
1083 wp_enqueue_script(
1084 'asenha-admin-menu-organizer',
1085 ASENHA_URL . 'assets/js/admin-menu-organizer.js',
1086 array('asenha-custom-admin-menu'),
1087 ASENHA_VERSION,
1088 false
1089 );
1090 $amo_page_vars = array(
1091 'saveMenuNonce' => wp_create_nonce( 'save-menu-nonce' ),
1092 'strings' => array(
1093 'saveChangesError' => __( 'Unable to save changes. Please reload the page and try again.', 'admin-site-enhancements' ),
1094 ),
1095 );
1096 wp_localize_script( 'asenha-custom-admin-menu', 'amoPageVars', $amo_page_vars );
1097 }
1098 // Admin Interface >> Admin Bar Custom Elements (Pro)
1099 if ( $current_screen && 'settings_page_asenha-admin-bar' === $current_screen->base ) {
1100 wp_deregister_script( 'jquery-ui-core' );
1101 wp_register_script(
1102 'jquery-ui-core',
1103 get_site_url() . '/wp-includes/js/jquery/ui/core.min.js',
1104 array('jquery'),
1105 ASENHA_VERSION,
1106 false
1107 );
1108 wp_enqueue_script( 'jquery-ui-core' );
1109 if ( version_compare( $wp_version, '5.6.0', '>=' ) ) {
1110 wp_deregister_script( 'jquery-ui-mouse' );
1111 wp_register_script(
1112 'jquery-ui-mouse',
1113 get_site_url() . '/wp-includes/js/jquery/ui/mouse.min.js',
1114 array('jquery-ui-core'),
1115 ASENHA_VERSION,
1116 false
1117 );
1118 wp_enqueue_script( 'jquery-ui-mouse' );
1119 } else {
1120 wp_deregister_script( 'jquery-ui-widget' );
1121 wp_register_script(
1122 'jquery-ui-widget',
1123 get_site_url() . '/wp-includes/js/jquery/ui/widget.min.js',
1124 array('jquery'),
1125 ASENHA_VERSION,
1126 false
1127 );
1128 wp_enqueue_script( 'jquery-ui-widget' );
1129 wp_deregister_script( 'jquery-ui-mouse' );
1130 wp_register_script(
1131 'jquery-ui-mouse',
1132 get_site_url() . '/wp-includes/js/jquery/ui/mouse.min.js',
1133 array('jquery-ui-core', 'jquery-ui-widget'),
1134 ASENHA_VERSION,
1135 false
1136 );
1137 wp_enqueue_script( 'jquery-ui-mouse' );
1138 }
1139 wp_deregister_script( 'jquery-ui-sortable' );
1140 wp_register_script(
1141 'jquery-ui-sortable',
1142 get_site_url() . '/wp-includes/js/jquery/ui/sortable.min.js',
1143 array('jquery-ui-mouse'),
1144 ASENHA_VERSION,
1145 false
1146 );
1147 wp_enqueue_script( 'jquery-ui-sortable' );
1148 wp_enqueue_style(
1149 'asenha-admin-bar-custom-elements',
1150 ASENHA_URL . 'assets/premium/css/admin-bar-custom-elements.css',
1151 array(),
1152 ASENHA_VERSION
1153 );
1154 wp_enqueue_script(
1155 'asenha-admin-bar-custom-elements',
1156 ASENHA_URL . 'assets/premium/js/admin-bar-custom-elements.js',
1157 array('jquery-ui-sortable'),
1158 ASENHA_VERSION,
1159 false
1160 );
1161 }
1162 // Utilities >> Email Delivery Log
1163 if ( 'tools_page_email-delivery-log' == $hook_suffix ) {
1164 wp_enqueue_style( 'jquery-ui-css', ASENHA_URL . 'assets/premium/css/jquery-ui/jquery-ui.min.css' );
1165 wp_enqueue_style( 'asenha-email-delivery-log', ASENHA_URL . 'assets/premium/css/email-delivery-log.css' );
1166 wp_enqueue_script( 'jquery-ui' );
1167 // wp_enqueue_script( 'jquery-ui-datepicker' );
1168 wp_enqueue_script( 'jquery-ui-tabs' );
1169 wp_enqueue_script( 'asenha-email-delivery-log', ASENHA_URL . 'assets/premium/js/email-delivery-log.js' );
1170 $nonce = wp_create_nonce( 'email-delivery-log' . get_current_user_id() );
1171 wp_localize_script( 'asenha-email-delivery-log', 'emailLog', array(
1172 'nonce' => $nonce,
1173 ) );
1174 }
1175 // Utilities >> Image Sizes Panel∂
1176 if ( 'post' == $current_screen->base && 'attachment' == $current_screen->id ) {
1177 global $post;
1178 // Only enqueue if the attachment is an image
1179 if ( property_exists( $post, 'post_mime_type' ) && false !== strpos( $post->post_mime_type, 'image' ) ) {
1180 wp_enqueue_style( 'asenha-image-sizes-panel', ASENHA_URL . 'assets/css/image-sizes-panel.css' );
1181 }
1182 }
1183 // Code Snippets Manager
1184 if ( 'post' == $current_screen->base && 'asenha_code_snippet' == $current_screen->id || 'edit' == $current_screen->base && 'edit-asenha_code_snippet' == $current_screen->id ) {
1185 }
1186 // Content Management >> Hide Admin Notices
1187 if ( array_key_exists( 'hide_admin_notices', $options ) && $options['hide_admin_notices'] ) {
1188 $hide_for_nonadmins = ( isset( $options['hide_admin_notices_for_nonadmins'] ) ? $options['hide_admin_notices_for_nonadmins'] : false );
1189 $minimum_capability = 'manage_options';
1190 if ( current_user_can( $minimum_capability ) ) {
1191 wp_enqueue_style(
1192 'asenha-jbox',
1193 ASENHA_URL . 'assets/css/jBox.all.min.css',
1194 array(),
1195 ASENHA_VERSION
1196 );
1197 wp_enqueue_script(
1198 'asenha-jbox',
1199 ASENHA_URL . 'assets/js/jBox.all.min.js',
1200 array(),
1201 ASENHA_VERSION,
1202 false
1203 );
1204 wp_enqueue_style(
1205 'asenha-hide-admin-notices',
1206 ASENHA_URL . 'assets/css/hide-admin-notices.css',
1207 array(),
1208 ASENHA_VERSION
1209 );
1210 wp_enqueue_script(
1211 'asenha-hide-admin-notices',
1212 ASENHA_URL . 'assets/js/hide-admin-notices.js',
1213 array('asenha-jbox'),
1214 ASENHA_VERSION,
1215 false
1216 );
1217 }
1218 }
1219 if ( array_key_exists( 'disable_user_account', $options ) && $options['disable_user_account'] && 'users.php' === $pagenow ) {
1220 wp_enqueue_script(
1221 'asenha-disable-user-account',
1222 ASENHA_URL . 'assets/js/disable-user-account.js',
1223 array('jquery'),
1224 ASENHA_VERSION,
1225 true
1226 );
1227 wp_localize_script( 'asenha-disable-user-account', 'asenhaDisableUserAccount', array(
1228 'ajaxUrl' => admin_url( 'admin-ajax.php' ),
1229 'nonce' => wp_create_nonce( 'asenha_user_account_toggle' ),
1230 ) );
1231 }
1232 // Utilities >> Multiple User Roles
1233 if ( array_key_exists( 'multiple_user_roles', $options ) && $options['multiple_user_roles'] ) {
1234 if ( 'user-edit.php' == $hook_suffix || 'user-new.php' == $hook_suffix ) {
1235 // Only replace roles dropdown with checkboxes for users that can assign roles to other users, e.g. administrators
1236 if ( current_user_can( 'promote_users', get_current_user_id() ) ) {
1237 wp_enqueue_script(
1238 'asenha-multiple-user-roles',
1239 ASENHA_URL . 'assets/js/multiple-user-roles.js',
1240 array('jquery'),
1241 ASENHA_VERSION,
1242 false
1243 );
1244 }
1245 }
1246 }
1247 $asenha_stats = asenha_get_option_array( ASENHA_SLUG_U . '_stats', false );
1248 $hide_promo_nudge = false;
1249 $is_yearend_promo_period = is_yearend_promo_period();
1250 // Pass on ASENHA stats to admin-page.js to determine whether to show support nudge
1251 $current_date = date( 'Y-m-d', time() );
1252 $show_support_nudge = false;
1253 $asenha_stats_localized = array(
1254 'firstSaveDate' => '',
1255 'lastSaveDate' => '',
1256 'saveCount' => 0,
1257 'hideUpgradeNudge' => false,
1258 'hidePromoNudge' => false,
1259 'showSupportNudge' => false,
1260 );
1261 if ( !empty( $asenha_stats ) ) {
1262 $hide_upgrade_nudge = ( isset( $asenha_stats['upgrade_nudge_dismissed'] ) ? $asenha_stats['upgrade_nudge_dismissed'] : false );
1263 $hide_promo_nudge = ( isset( $asenha_stats['promo_nudge_dismissed'] ) ? $asenha_stats['promo_nudge_dismissed'] : false );
1264 $have_supported = ( isset( $asenha_stats['have_supported'] ) ? $asenha_stats['have_supported'] : false );
1265 $changes_saved = ( isset( $_GET['settings-updated'] ) && 'true' == sanitize_text_field( $_GET['settings-updated'] ) ? true : false );
1266 $save_count = ( isset( $asenha_stats['save_count'] ) ? $asenha_stats['save_count'] : 0 );
1267 // Compensate for redirect from settings-updated=true URL
1268 if ( $changes_saved ) {
1269 $save_count = $save_count + 1;
1270 } else {
1271 $save_count = $save_count;
1272 }
1273 $saves_to_nudge_support = 10;
1274 if ( $save_count < $saves_to_nudge_support ) {
1275 $save_count_modulo = -1;
1276 } else {
1277 $save_count_modulo = $save_count % $saves_to_nudge_support;
1278 }
1279 // User have not supported ASE
1280 if ( false === $have_supported ) {
1281 // Support nudge have not been dismissed
1282 if ( isset( $asenha_stats['support_nudge_dismissed'] ) && false === $asenha_stats['support_nudge_dismissed'] ) {
1283 // Show support nudge after every x saves
1284 if ( $save_count_modulo >= 0 ) {
1285 $show_support_nudge = true;
1286 } else {
1287 $show_support_nudge = false;
1288 }
1289 if ( $show_support_nudge && $save_count_modulo >= 0 ) {
1290 $asenha_stats['support_nudge_last_shown_date'] = $current_date;
1291 $asenha_stats['support_nudge_last_shown_save_count'] = $save_count;
1292 update_option( ASENHA_SLUG_U . '_stats', $asenha_stats, false );
1293 }
1294 } else {
1295 if ( $save_count_modulo == 0 ) {
1296 $support_nudge_last_shown_save_count = ( isset( $asenha_stats['support_nudge_last_shown_save_count'] ) ? $asenha_stats['support_nudge_last_shown_save_count'] : 0 );
1297 if ( $save_count > $support_nudge_last_shown_save_count ) {
1298 $asenha_stats['support_nudge_dismissed'] = false;
1299 update_option( ASENHA_SLUG_U . '_stats', $asenha_stats, false );
1300 $show_support_nudge = true;
1301 } else {
1302 $show_support_nudge = false;
1303 }
1304 } else {
1305 $show_support_nudge = false;
1306 }
1307 }
1308 }
1309 $first_save_date = ( isset( $asenha_stats['first_save_date'] ) ? $asenha_stats['first_save_date'] : '' );
1310 $last_save_date = ( isset( $asenha_stats['last_save_date'] ) ? $asenha_stats['last_save_date'] : '' );
1311 $asenha_stats_localized = array(
1312 'firstSaveDate' => $first_save_date,
1313 'lastSaveDate' => $last_save_date,
1314 'saveCount' => $save_count,
1315 'isYearEndPromoPeriod' => $is_yearend_promo_period,
1316 'hideUpgradeNudge' => $hide_upgrade_nudge,
1317 'hidePromoNudge' => $hide_promo_nudge,
1318 'showSupportNudge' => $show_support_nudge,
1319 );
1320 }
1321 wp_localize_script( 'asenha-admin-page', 'asenhaStats', $asenha_stats_localized );
1322 }
1323
1324 /**
1325 * Enqueue block editor scripts and styles.
1326 *
1327 * Loaded via the `enqueue_block_editor_assets` hook so assets are scoped
1328 * strictly to block-editor post-edit screens (post.php / post-new.php).
1329 *
1330 * @since 7.11.0
1331 */
1332 function asenha_block_editor_scripts() {
1333 $current_screen = get_current_screen();
1334 // Only load on post edit / new post block editor screens.
1335 if ( !$current_screen instanceof \WP_Screen || 'post' !== $current_screen->base || !method_exists( $current_screen, 'is_block_editor' ) || !$current_screen->is_block_editor() ) {
1336 return;
1337 }
1338 wp_enqueue_style(
1339 'asenha-wp-block-editor',
1340 ASENHA_URL . 'assets/css/wp-block-editor.css',
1341 array(),
1342 ASENHA_VERSION
1343 );
1344 }
1345
1346 /**
1347 * Inline CSS for Admin Menu Organizer in all wp-admin pages. Previously loaded externally as part of wp-admin.css file
1348 *
1349 * @since 7.6.11
1350 */
1351 function asenha_admin_menu_organizer_css() {
1352 ?>
1353 <style type="text/css">
1354 /* Admin Interface >> Admin Menu Organizer */
1355 #adminmenuwrap {
1356 height: auto !important;
1357 }
1358
1359 .toplevel_page_wpide #adminmenuwrap {
1360 height: calc(100vh - var(--wpide-admin-bar-height)) !important;
1361 } /* Fix for when in WPIDE plugin's menu / admin page */
1362
1363 /* Hide "Show Less" toggle by default to avoid initial flash before JS runs. */
1364 #toplevel_page_asenha_hide_hidden_menu {
1365 display: none;
1366 }
1367
1368 .current.menu-top.hidden,
1369 .wp-has-current-submenu.hidden {
1370 display: list-item;
1371 }
1372
1373 #adminmenu a.menu-top.hidden,
1374 ul#adminmenu a.wp-has-current-submenu.hidden {
1375 display: block;
1376 }
1377
1378 /*! <fs_premium_only> */
1379 .always-hidden {
1380 display: none !important;
1381 }
1382
1383 #adminmenu .wp-submenu a.hidden {
1384 display: none;
1385 }
1386 /*! </fs_premium_only> */
1387 </style>
1388 <?php
1389 }
1390
1391 /**
1392 * Dequeue scripts that prevents ASE settings page from working properly. Usually from plugins.
1393 *
1394 * @since 6.3.3
1395 */
1396 function asenha_dequeue_scritps() {
1397 if ( is_asenha() ) {
1398 // https://wordpress.org/plugins/user-activity-log/
1399 wp_dequeue_script( 'chats-js' );
1400 wp_dequeue_script( 'custom_wp_admin_js' );
1401 // https://wordpress.org/plugins/print-invoices-packing-slip-labels-for-woocommerce/
1402 wp_dequeue_script( 'print-invoices-packing-slip-labels-for-woocommerce' );
1403 wp_dequeue_script( 'print-invoices-packing-slip-labels-for-woocommerce-form-wizard' );
1404 // https://wordpress.org/plugins/wp-reading-progress/
1405 wp_dequeue_script( 'ruigehond006_admin_javascript' );
1406 // WordPress Mentions Légales plugin v1.2.3 by Jean-Baptiste Aramendy - http://jba-development.fr/
1407 wp_dequeue_script( 'jquery-ui' );
1408 wp_dequeue_script( 'wordpress-mentions-legales' );
1409 // https://wordpress.org/plugins/us-weather-widget-willyweather/
1410 wp_dequeue_script( 'self' );
1411 // iThemes Security Pro / Solid Security Pro
1412 wp_dequeue_script( 'itsec-core-admin-notices' );
1413 // WPML
1414 wp_dequeue_script( 'wpml-ate-jobs-sync-ui' );
1415 wp_dequeue_script( 'wpml-purify' );
1416 wp_dequeue_script( 'sitepress-scripts' );
1417 wp_dequeue_script( 'sitepress' );
1418 wp_dequeue_script( 'wpml-dismiss-notice' );
1419 wp_dequeue_script( 'wpml-tm-scripts' );
1420 wp_dequeue_script( 'otgs-installer-components-save-setting' );
1421 wp_dequeue_script( 'installer-dismiss-nag' );
1422 wp_dequeue_script( 'install-recommended_plugin' );
1423 wp_dequeue_script( 'icl-admin-notifier' );
1424 wp_dequeue_script( 'otgsPopoverTooltip' );
1425 // WPML String Translation
1426 wp_dequeue_script( 'wpml-theme-plugin-localization-scan' );
1427 // Asset Cleanup
1428 wp_dequeue_script( 'wpassetcleanup-script' );
1429 }
1430 }
1431
1432 /**
1433 * Enqueue public scripts
1434 *
1435 * @since 3.9.0
1436 */
1437 function asenha_public_scripts( $hook_suffix ) {
1438 // Get all WP Enhancements options, default to empty array in case it's not been created yet
1439 $options = get_option( 'admin_site_enhancements', array() );
1440 // External Permalinks
1441 $enable_external_permalinks = ( array_key_exists( 'enable_external_permalinks', $options ) ? $options['enable_external_permalinks'] : false );
1442 if ( $enable_external_permalinks ) {
1443 $external_permalinks = new ASENHA\Classes\External_Permalinks();
1444 wp_register_script(
1445 'asenha-external-permalinks',
1446 false,
1447 array(),
1448 ASENHA_VERSION,
1449 false
1450 );
1451 wp_enqueue_script( 'asenha-external-permalinks' );
1452 wp_add_inline_script( 'asenha-external-permalinks', $external_permalinks->get_frontend_inline_script_for_options( $options ) );
1453 }
1454 // Media Categories
1455 $enable_media_categories = ( array_key_exists( 'enable_media_categories', $options ) ? $options['enable_media_categories'] : false );
1456 if ( $enable_media_categories && !is_admin() && is_user_logged_in() ) {
1457 wp_enqueue_style(
1458 'asenha-media-categories-frontend',
1459 ASENHA_URL . 'assets/css/media-categories-frontend.css',
1460 array(),
1461 ASENHA_VERSION
1462 );
1463 }
1464 }
1465
1466 /**
1467 * Add admin bar styles for wp-admin and frontend
1468 *
1469 * @since 6.2.1
1470 */
1471 function asenha_admin_bar_item_js_css() {
1472 if ( is_user_logged_in() ) {
1473 ?>
1474 <!--<script></script>-->
1475 <style>
1476 #wp-admin-bar-user-info .avatar {
1477 object-fit: cover;
1478 }
1479 </style>
1480 <?php
1481 }
1482 }
1483
1484 /**
1485 * Add 'Access now' plugin action link.
1486 *
1487 * @since 1.0.0
1488 */
1489 function asenha_plugin_action_links( $links ) {
1490 $settings_link = '<a href="tools.php?page=' . ASENHA_SLUG . '">' . __( 'Configure', 'admin-site-enhancements' ) . '</a>';
1491 array_unshift( $links, $settings_link );
1492 return $links;
1493 }
1494
1495 /**
1496 * Modify footer text
1497 *
1498 * @since 1.0.0
1499 */
1500 function asenha_footer_text() {
1501 // Show nothing
1502 ?>
1503 <?php
1504 }
1505
1506 /**
1507 * Change WP version number text in footer
1508 *
1509 * @since 4.8.3
1510 */
1511 function asenha_footer_version_text() {
1512 ?>
1513 ASE <a href="https://www.wpase.com/documentation/changelog/" target="_blank">v<?php
1514 echo esc_html( ASENHA_VERSION );
1515 ?></a>
1516 <?php
1517 }
1518
1519 /**
1520 * Check if current screen is this plugin's main page
1521 *
1522 * @since 1.0.0
1523 */
1524 function is_asenha() {
1525 $request_uri = sanitize_text_field( $_SERVER['REQUEST_URI'] );
1526 // e.g. /wp-admin/index.php?page=page-slug
1527 if ( strpos( $request_uri, 'page=' . ASENHA_SLUG ) !== false ) {
1528 return true;
1529 // Yes, this is the plugin's main page
1530 } else {
1531 return false;
1532 // Nope, this is NOT the plugin's page
1533 }
1534 }
1535
1536 /**
1537 * Mark that user have supported ASE
1538 *
1539 * @since 5.2.7
1540 */
1541 function asenha_have_supported() {
1542 if ( isset( $_REQUEST ) && current_user_can( 'manage_options' ) ) {
1543 if ( wp_verify_nonce( sanitize_text_field( $_REQUEST['nonce'] ), 'asenha-' . get_current_user_id() ) ) {
1544 $asenha_stats = asenha_get_option_array( ASENHA_SLUG_U . '_stats', false );
1545 $asenha_stats['have_supported'] = true;
1546 $asenha_stats['support_nudge_dismissed'] = true;
1547 $success = update_option( ASENHA_SLUG_U . '_stats', $asenha_stats, false );
1548 if ( $success ) {
1549 echo json_encode( array(
1550 'success' => true,
1551 ) );
1552 } else {
1553 echo json_encode( array(
1554 'success' => false,
1555 ) );
1556 }
1557 }
1558 }
1559 }
1560
1561 /**
1562 * Dismiss support nudge
1563 *
1564 * @since 5.8.2
1565 */
1566 function asenha_dismiss_upgrade_nudge() {
1567 if ( isset( $_REQUEST ) && current_user_can( 'manage_options' ) ) {
1568 if ( wp_verify_nonce( sanitize_text_field( $_REQUEST['nonce'] ), 'asenha-' . get_current_user_id() ) ) {
1569 $current_date = date( 'Y-m-d', time() );
1570 $asenha_stats = asenha_get_option_array( ASENHA_SLUG_U . '_stats', false );
1571 $asenha_stats['upgrade_nudge_dismissed'] = true;
1572 $asenha_stats['upgrade_nudge_dismissed_date'] = $current_date;
1573 $success = update_option( ASENHA_SLUG_U . '_stats', $asenha_stats, false );
1574 if ( $success ) {
1575 echo json_encode( array(
1576 'success' => true,
1577 ) );
1578 } else {
1579 echo json_encode( array(
1580 'success' => false,
1581 ) );
1582 }
1583 }
1584 }
1585 }
1586
1587 /**
1588 * Dismiss promo nudge
1589 *
1590 * @since 7.5.1
1591 */
1592 function asenha_dismiss_promo_nudge() {
1593 if ( isset( $_REQUEST ) && current_user_can( 'manage_options' ) ) {
1594 if ( wp_verify_nonce( sanitize_text_field( $_REQUEST['nonce'] ), 'asenha-' . get_current_user_id() ) ) {
1595 $current_date = date( 'Y-m-d', time() );
1596 $asenha_stats = asenha_get_option_array( ASENHA_SLUG_U . '_stats', false );
1597 $asenha_stats['promo_nudge_dismissed'] = true;
1598 $asenha_stats['promo_nudge_dismissed_date'] = $current_date;
1599 $success = update_option( ASENHA_SLUG_U . '_stats', $asenha_stats, false );
1600 if ( $success ) {
1601 echo json_encode( array(
1602 'success' => true,
1603 ) );
1604 } else {
1605 echo json_encode( array(
1606 'success' => false,
1607 ) );
1608 }
1609 }
1610 }
1611 }
1612
1613 /**
1614 * Dismiss support nudge
1615 *
1616 * @since 5.2.7
1617 */
1618 function asenha_dismiss_support_nudge() {
1619 if ( isset( $_REQUEST ) && current_user_can( 'manage_options' ) ) {
1620 if ( wp_verify_nonce( sanitize_text_field( $_REQUEST['nonce'] ), 'asenha-' . get_current_user_id() ) ) {
1621 $asenha_stats = asenha_get_option_array( ASENHA_SLUG_U . '_stats', false );
1622 $asenha_stats['support_nudge_dismissed'] = true;
1623 $success = update_option( ASENHA_SLUG_U . '_stats', $asenha_stats, false );
1624 if ( $success ) {
1625 echo json_encode( array(
1626 'success' => true,
1627 ) );
1628 } else {
1629 echo json_encode( array(
1630 'success' => false,
1631 ) );
1632 }
1633 }
1634 }
1635 }
1636
1637 /**
1638 * Release lock for an IP address in Limit Login Attempts.
1639 *
1640 * Deletes the IP entry from the failed login attempts table, which immediately
1641 * releases the lockout for that IP address.
1642 *
1643 * @since 8.3.1
1644 */
1645 function asenha_release_login_lock() {
1646 if ( !current_user_can( 'manage_options' ) ) {
1647 wp_send_json_error( array(
1648 'message' => __( 'Insufficient permissions.', 'admin-site-enhancements' ),
1649 ) );
1650 }
1651 if ( !isset( $_REQUEST['nonce'] ) || !isset( $_REQUEST['ip_address'] ) ) {
1652 wp_send_json_error( array(
1653 'message' => __( 'Missing required data.', 'admin-site-enhancements' ),
1654 ) );
1655 }
1656 $nonce = sanitize_text_field( wp_unslash( $_REQUEST['nonce'] ) );
1657 if ( !wp_verify_nonce( $nonce, 'asenha-' . get_current_user_id() ) ) {
1658 wp_send_json_error( array(
1659 'message' => __( 'Invalid security token.', 'admin-site-enhancements' ),
1660 ) );
1661 }
1662 $ip_address = sanitize_text_field( wp_unslash( $_REQUEST['ip_address'] ) );
1663 $common_methods = new \ASENHA\Classes\Common_Methods();
1664 if ( !$common_methods->is_ip_valid( $ip_address ) ) {
1665 wp_send_json_error( array(
1666 'message' => __( 'Invalid IP address.', 'admin-site-enhancements' ),
1667 ) );
1668 }
1669 global $wpdb;
1670 $table_name = $wpdb->prefix . 'asenha_failed_logins';
1671 $deleted = $wpdb->delete( $table_name, array(
1672 'ip_address' => $ip_address,
1673 ), array('%s') );
1674 if ( false === $deleted ) {
1675 wp_send_json_error( array(
1676 'message' => __( 'Could not release lock.', 'admin-site-enhancements' ),
1677 ) );
1678 }
1679 wp_send_json_success( array(
1680 'deleted' => (int) $deleted,
1681 ) );
1682 }
1683