1376 lines
70 KiB
PHP
1376 lines
70 KiB
PHP
<?php
|
|
|
|
namespace ASENHA\Classes;
|
|
|
|
/**
|
|
* Class related to rendering of settings fields on the admin page
|
|
*
|
|
* @since 2.2.0
|
|
*/
|
|
class Settings_Fields_Render {
|
|
/**
|
|
* Render checkbox field as a toggle/switcher
|
|
*
|
|
* @since 1.0.0
|
|
*/
|
|
function render_checkbox_toggle( $args ) {
|
|
$option_name = ( isset( $args['option_name'] ) ? $args['option_name'] : '' );
|
|
if ( !empty( $option_name ) ) {
|
|
$options = get_option( $option_name, array() );
|
|
} else {
|
|
$options = get_option( ASENHA_SLUG_U, array() );
|
|
}
|
|
$field_name = $args['field_name'];
|
|
$field_title = ( isset( $args['field_title'] ) ? $args['field_title'] : '' );
|
|
$field_description = $args['field_description'];
|
|
$field_option_value = ( array_key_exists( $args['field_id'], $options ) ? $options[$args['field_id']] : false );
|
|
echo '<input type="checkbox" id="' . esc_attr( $field_name ) . '" class="asenha-field-checkbox" name="' . esc_attr( $field_name ) . '" ' . checked( $field_option_value, true, false ) . '>';
|
|
echo '<label for="' . esc_attr( $field_name ) . '"></label>';
|
|
// For field with additional options / sub-fields, we add a wrapper to enclose field descriptions
|
|
if ( array_key_exists( 'field_options_wrapper', $args ) && $args['field_options_wrapper'] ) {
|
|
// For when the options / sub-fields occupy lengthy vertical space, we add show all / less toggler
|
|
if ( array_key_exists( 'field_options_moreless', $args ) && $args['field_options_moreless'] ) {
|
|
echo '<div class="asenha-field-with-options field-show-more">';
|
|
echo '<a id="' . esc_attr( $args['field_slug'] ) . '-show-moreless" class="show-more-less show-more" href="#">' . __( 'Expand', 'admin-site-enhancements' ) . ' ▼</a>';
|
|
echo '<div class="asenha-field-options-wrapper wrapper-show-more">';
|
|
} else {
|
|
echo '<div class="asenha-field-with-options">';
|
|
echo '<div class="asenha-field-options-wrapper">';
|
|
}
|
|
}
|
|
echo '<div class="asenha-field-description" data-search-filter data-module-info="' . esc_attr( strtolower( $field_title ) ) . '">' . wp_kses_post( $field_description ) . '</div>';
|
|
// For field with additional options / sub-fields, we add wrapper for them
|
|
if ( array_key_exists( 'field_options_wrapper', $args ) && $args['field_options_wrapper'] ) {
|
|
echo '<div class="asenha-subfields" style="display:none"></div>';
|
|
}
|
|
// For field with additional options / sub-fields, we add a wrapper to enclose field descriptions
|
|
if ( array_key_exists( 'field_options_wrapper', $args ) && $args['field_options_wrapper'] ) {
|
|
echo '</div>';
|
|
echo '</div>';
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Render checkbox field as sub-field of a toggle/switcher checkbox
|
|
*
|
|
* @since 1.9.0
|
|
*/
|
|
function render_checkbox_plain( $args ) {
|
|
$option_name = $args['option_name'];
|
|
if ( !empty( $option_name ) ) {
|
|
$options = get_option( $option_name, array() );
|
|
} else {
|
|
$options = get_option( ASENHA_SLUG_U, array() );
|
|
}
|
|
$field_name = $args['field_name'];
|
|
$field_label = $args['field_label'];
|
|
$default_value = false;
|
|
switch ( $args['field_id'] ) {
|
|
case 'login_page_disable_registration':
|
|
$default_value = ( 1 == get_option( 'users_can_register' ) ? false : true );
|
|
break;
|
|
}
|
|
$field_option_value = ( isset( $options[$args['field_id']] ) ? $options[$args['field_id']] : $default_value );
|
|
$display_none_on_load = ( isset( $args['display_none_on_load'] ) ? $args['display_none_on_load'] : false );
|
|
if ( $display_none_on_load ) {
|
|
$inline_style = 'display:none;';
|
|
} else {
|
|
$inline_style = '';
|
|
}
|
|
echo '<input type="checkbox" id="' . esc_attr( $field_name ) . '" class="asenha-subfield-checkbox" style="' . esc_attr( $inline_style ) . '" name="' . esc_attr( $field_name ) . '" ' . checked( $field_option_value, true, false ) . '>';
|
|
echo '<label for="' . esc_attr( $field_name ) . '" class="asenha-subfield-checkbox-label" style="' . esc_attr( $inline_style ) . '">' . wp_kses_post( $field_label ) . '</label>';
|
|
}
|
|
|
|
/**
|
|
* Render checkbox field as sub-field of a toggle/switcher checkbox
|
|
*
|
|
* @since 1.3.0
|
|
*/
|
|
function render_checkbox_subfield( $args ) {
|
|
$option_name = $args['option_name'];
|
|
if ( !empty( $option_name ) ) {
|
|
$options = get_option( $option_name, array() );
|
|
} else {
|
|
$options = get_option( ASENHA_SLUG_U, array() );
|
|
}
|
|
$field_name = $args['field_name'];
|
|
$field_label = $args['field_label'];
|
|
$parent_field_id = ( isset( $args['parent_field_id'] ) ? $args['parent_field_id'] : '' );
|
|
$sub_field_id = ( isset( $args['sub_field_id'] ) ? $args['sub_field_id'] : '' );
|
|
if ( in_array( $parent_field_id, array('enable_duplication_for', 'enable_rest_api_for') ) ) {
|
|
// Default is true/enabled. Usually for options introduced at a later date where the previous default is true/enabled.
|
|
$default_value = true;
|
|
} else {
|
|
// Default is false / checked
|
|
$default_value = false;
|
|
}
|
|
if ( !empty( $parent_field_id ) && !empty( $sub_field_id ) && isset( $options[$parent_field_id][$sub_field_id][$args['field_id']] ) ) {
|
|
$field_option_value = $options[$parent_field_id][$sub_field_id][$args['field_id']];
|
|
} elseif ( in_array( $parent_field_id, array('redirect_after_login_for_separate', 'redirect_after_logout_for_separate'), true ) && !empty( $sub_field_id ) ) {
|
|
$field_option_value = ( isset( $options[$sub_field_id][$args['field_id']] ) ? $options[$sub_field_id][$args['field_id']] : $default_value );
|
|
} elseif ( empty( $parent_field_id ) && !empty( $args['field_id'] ) ) {
|
|
$field_option_value = ( isset( $options[$args['field_id']] ) ? $options[$args['field_id']] : $default_value );
|
|
} else {
|
|
$field_option_value = ( isset( $options[$parent_field_id][$args['field_id']] ) ? $options[$parent_field_id][$args['field_id']] : $default_value );
|
|
}
|
|
echo '<input type="checkbox" id="' . esc_attr( $field_name ) . '" class="asenha-subfield-checkbox" name="' . esc_attr( $field_name ) . '" ' . checked( $field_option_value, true, false ) . '>';
|
|
echo '<label for="' . esc_attr( $field_name ) . '" class="asenha-subfield-checkbox-label">' . wp_kses_post( $field_label ) . '</label>';
|
|
if ( !empty( $args['field_description'] ) ) {
|
|
$desc_display = ( isset( $args['field_description_display'] ) ? $args['field_description_display'] : 'inline' );
|
|
if ( 'tooltip' === $desc_display ) {
|
|
echo '<span class="asenha-info-tooltip-wrap">';
|
|
echo '<button type="button" class="asenha-info-tooltip-toggle" aria-label="' . esc_attr__( 'More information', 'admin-site-enhancements' ) . '">';
|
|
echo '<span class="dashicons dashicons-info-outline" aria-hidden="true"></span>';
|
|
echo '</button>';
|
|
echo '<span class="asenha-info-tooltip" role="tooltip">' . esc_html( $args['field_description'] ) . '</span>';
|
|
echo '</span>';
|
|
} else {
|
|
echo '<div class="asenha-subfield-description">' . wp_kses_post( $args['field_description'] ) . '</div>';
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Render radio buttons field as sub-field of a toggle/switcher checkbox
|
|
*
|
|
* @since 1.3.0
|
|
*/
|
|
function render_radio_buttons_subfield( $args ) {
|
|
$option_name = $args['option_name'];
|
|
if ( !empty( $option_name ) ) {
|
|
$options = get_option( $option_name, array() );
|
|
} else {
|
|
$options = get_option( ASENHA_SLUG_U, array() );
|
|
}
|
|
$field_id = $args['field_id'];
|
|
$field_name = $args['field_name'];
|
|
$field_radios = $args['field_radios'];
|
|
if ( !empty( $args['field_default'] ) ) {
|
|
$default_value = $args['field_default'];
|
|
} else {
|
|
$default_value = false;
|
|
}
|
|
$field_description = ( isset( $args['field_description'] ) ? $args['field_description'] : '' );
|
|
$field_option_value = ( isset( $options[$field_id] ) ? $options[$field_id] : $default_value );
|
|
echo '<div class="asenha-subfield-radio-button-wrapper">';
|
|
foreach ( $field_radios as $radio_label => $radio_value ) {
|
|
echo '<input type="radio" id="' . esc_attr( $field_id . '_' . $radio_value ) . '" class="asenha-subfield-radio-button" name="' . esc_attr( $field_name ) . '" value="' . esc_attr( $radio_value ) . '" ' . checked( $radio_value, $field_option_value, false ) . '>';
|
|
echo '<label for="' . esc_attr( $field_id . '_' . $radio_value ) . '" class="asenha-subfield-radio-button-label">' . wp_kses_post( $radio_label ) . '</label>';
|
|
}
|
|
echo '</div>';
|
|
if ( !empty( $field_description ) ) {
|
|
echo '<div class="asenha-subfield-description">' . wp_kses_post( $field_description ) . '</div>';
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Render checkboxes field as sub-field of a toggle/switcher checkbox
|
|
*
|
|
* @since 6.9.2
|
|
*/
|
|
function render_checkboxes_subfield( $args ) {
|
|
$options = get_option( ASENHA_SLUG_U, array() );
|
|
$field_id = $args['field_id'];
|
|
$field_name = $args['field_name'];
|
|
$field_options = $args['field_options'];
|
|
$layout = ( !empty( $args['layout'] ) ? $args['layout'] : 'horizontal' );
|
|
$default_value = ( !empty( $args['field_default'] ) ? $args['field_default'] : array() );
|
|
$parent_field_id = ( isset( $args['parent_field_id'] ) ? $args['parent_field_id'] : '' );
|
|
$sub_field_id = ( isset( $args['sub_field_id'] ) ? $args['sub_field_id'] : '' );
|
|
if ( !empty( $parent_field_id ) && !empty( $sub_field_id ) && isset( $options[$parent_field_id][$sub_field_id][$field_id] ) ) {
|
|
$field_option_value = (array) $options[$parent_field_id][$sub_field_id][$field_id];
|
|
} else {
|
|
$field_option_value = ( isset( $options[$field_id] ) ? (array) $options[$field_id] : $default_value );
|
|
}
|
|
// Back-compat: legacy naming for Two-Factor Recovery Codes.
|
|
if ( in_array( $field_id, array('two_factor_available_providers', 'available_providers'), true ) && is_array( $field_option_value ) ) {
|
|
$field_option_value = array_map( static function ( $provider_key ) {
|
|
return ( 'backup_codes' === $provider_key ? 'recovery_codes' : $provider_key );
|
|
}, $field_option_value );
|
|
}
|
|
echo '<div class="wrapper-for-checkboxes ' . esc_attr( $layout ) . '">';
|
|
foreach ( $field_options as $option_label => $option_value ) {
|
|
$checkbox_id = ( !empty( $parent_field_id ) && !empty( $sub_field_id ) ? $parent_field_id . '_' . $sub_field_id . '_' . $field_id . '_' . $option_value : $field_id . '_' . $option_value );
|
|
echo '<div>';
|
|
echo '<input type="checkbox" id="' . esc_attr( $checkbox_id ) . '" class="asenha-subfield-radio-button" name="' . esc_attr( $field_name ) . '" value="' . esc_attr( $option_value ) . '" ' . checked( in_array( $option_value, $field_option_value ), 1, false ) . '>';
|
|
echo '<label for="' . esc_attr( $checkbox_id ) . '" class="asenha-subfield-radio-button-label">' . wp_kses_post( $option_label ) . '</label>';
|
|
echo '</div>';
|
|
}
|
|
echo '</div>';
|
|
}
|
|
|
|
/**
|
|
* Render text field as sub-field of a toggle/switcher checkbox
|
|
*
|
|
* @since 1.4.0
|
|
*/
|
|
function render_text_subfield( $args ) {
|
|
$option_name = $args['option_name'];
|
|
if ( !empty( $option_name ) ) {
|
|
$options = get_option( $option_name, array() );
|
|
} else {
|
|
$options = get_option( ASENHA_SLUG_U, array() );
|
|
}
|
|
$field_id = $args['field_id'];
|
|
$field_slug = str_replace( '_', '-', $field_id );
|
|
$field_name = $args['field_name'];
|
|
$field_width_classname = ( isset( $args['field_width_classname'] ) ? $args['field_width_classname'] : '' );
|
|
$field_type = $args['field_type'];
|
|
$field_prefix = $args['field_prefix'];
|
|
$field_suffix = $args['field_suffix'];
|
|
$field_is_read_only = ( isset( $args['read_only'] ) ? $args['read_only'] : false );
|
|
$field_is_read_only_output = ( $field_is_read_only ? ' readonly="readonly"' : '' );
|
|
$field_placeholder = ( isset( $args['field_placeholder'] ) ? $args['field_placeholder'] : '' );
|
|
$field_description = $args['field_description'];
|
|
if ( isset( $options[$field_id] ) ) {
|
|
if ( 'live_site_url' == $field_id ) {
|
|
if ( false !== strpos( $options[$field_id], 'http' ) ) {
|
|
$field_option_value = $options[$field_id];
|
|
} else {
|
|
// Legacy support for when base64 encoding was used prior to v7.3.1
|
|
$field_option_value = base64_decode( $options[$field_id] );
|
|
}
|
|
} elseif ( 'login_page_logo_image_width' == $field_id || 'login_page_logo_image_height' == $field_id ) {
|
|
if ( isset( $options[$field_id] ) ) {
|
|
if ( is_numeric( $options[$field_id] ) ) {
|
|
$field_option_value = $options[$field_id];
|
|
} else {
|
|
$field_option_value = str_replace( 'px', '', $options[$field_id] );
|
|
}
|
|
}
|
|
} else {
|
|
$field_option_value = $options[$field_id];
|
|
}
|
|
} else {
|
|
if ( 'altcha_secret_key' == $field_id ) {
|
|
$field_option_value = '';
|
|
} else {
|
|
$field_option_value = '';
|
|
}
|
|
}
|
|
if ( !empty( $field_prefix ) && !empty( $field_suffix ) ) {
|
|
$field_classname = ' with-prefix with-suffix';
|
|
} elseif ( !empty( $field_prefix ) && empty( $field_suffix ) ) {
|
|
$field_classname = ' with-prefix';
|
|
} elseif ( empty( $field_prefix ) && !empty( $field_suffix ) ) {
|
|
$field_classname = ' with-suffix';
|
|
} else {
|
|
$field_classname = '';
|
|
}
|
|
if ( !empty( $field_width_classname ) ) {
|
|
$field_classname .= ' ' . $field_width_classname;
|
|
}
|
|
echo wp_kses_post( $field_prefix ) . '<input type="text" id="' . esc_attr( $field_name ) . '" class="asenha-subfield-text' . esc_attr( $field_classname ) . '" name="' . esc_attr( $field_name ) . '" placeholder="' . esc_attr( $field_placeholder ) . '" value="' . esc_attr( $field_option_value ) . '"' . esc_html( $field_is_read_only_output ) . '>' . wp_kses_post( $field_suffix );
|
|
echo '<label for="' . esc_attr( $field_name ) . '" class="asenha-subfield-checkbox-label">' . esc_html( $field_description ) . '</label>';
|
|
}
|
|
|
|
/**
|
|
* Render text field as sub-field of a checkbox field. e.g. in Redirect After Login module
|
|
*
|
|
* @since 7.3.3
|
|
*/
|
|
function render_checkbox_field_text_subfield( $args ) {
|
|
$option_name = $args['option_name'];
|
|
if ( !empty( $option_name ) ) {
|
|
$options = get_option( $option_name, array() );
|
|
} else {
|
|
$options = get_option( ASENHA_SLUG_U, array() );
|
|
}
|
|
$field_id = $args['field_id'];
|
|
$field_name = $args['field_name'];
|
|
$field_width_classname = ( isset( $args['field_width_classname'] ) ? $args['field_width_classname'] : '' );
|
|
$field_type = $args['field_type'];
|
|
$field_prefix = $args['field_prefix'];
|
|
$field_suffix = $args['field_suffix'];
|
|
$field_placeholder = ( isset( $args['field_placeholder'] ) ? $args['field_placeholder'] : '' );
|
|
$field_description = $args['field_description'];
|
|
$parent_field_id = ( isset( $args['parent_field_id'] ) ? $args['parent_field_id'] : '' );
|
|
$sub_field_id = ( isset( $args['sub_field_id'] ) ? $args['sub_field_id'] : '' );
|
|
if ( 'redirect_after_login_for_separate' == $parent_field_id && !empty( $sub_field_id ) ) {
|
|
$field_option_value = ( isset( $options[$sub_field_id][$field_id] ) ? $options[$sub_field_id][$field_id] : '' );
|
|
} else {
|
|
$field_option_value = ( isset( $options[$parent_field_id][$field_id] ) ? $options[$parent_field_id][$field_id] : '' );
|
|
}
|
|
// $field_option_value = ( isset( $options[$field_id] ) ) ? $options[$field_id] : '';
|
|
$field_option_value = ( isset( $options[$parent_field_id . '_slug'][$args['field_id']] ) ? $options[$parent_field_id . '_slug'][$field_id] : '' );
|
|
if ( !empty( $field_prefix ) && !empty( $field_suffix ) ) {
|
|
$field_classname = ' with-prefix with-suffix';
|
|
} elseif ( !empty( $field_prefix ) && empty( $field_suffix ) ) {
|
|
$field_classname = ' with-prefix';
|
|
} elseif ( empty( $field_prefix ) && !empty( $field_suffix ) ) {
|
|
$field_classname = ' with-suffix';
|
|
} else {
|
|
$field_classname = '';
|
|
}
|
|
if ( !empty( $field_width_classname ) ) {
|
|
$field_classname .= ' ' . $field_width_classname;
|
|
}
|
|
echo wp_kses_post( $field_prefix ) . '<input type="text" id="' . esc_attr( $field_name ) . '" class="asenha-subfield-text' . esc_attr( $field_classname ) . '" name="' . esc_attr( $field_name ) . '" placeholder="' . esc_attr( $field_placeholder ) . '" value="' . esc_attr( $field_option_value ) . '">' . wp_kses_post( $field_suffix );
|
|
echo '<label for="' . esc_attr( $field_name ) . '" class="asenha-subfield-checkbox-label">' . esc_html( $field_description ) . '</label>';
|
|
}
|
|
|
|
/**
|
|
* Render description field as sub-field of a toggle/switcher checkbox
|
|
*
|
|
* @since 4.6.0
|
|
*/
|
|
function render_description_subfield( $args ) {
|
|
$field_description = $args['field_description'];
|
|
echo '<div class="asenha-subfield-description">' . wp_kses( $field_description, get_kses_with_style_src_svg_ruleset() ) . '</div>';
|
|
}
|
|
|
|
/**
|
|
* Render View Admin as Role recovery URL description at display time.
|
|
*
|
|
* @since 8.8.5
|
|
* @param array $args Settings field arguments.
|
|
* @return void
|
|
*/
|
|
function render_view_admin_as_role_recovery_description( $args ) {
|
|
$view_admin_as_role = new View_Admin_As_Role();
|
|
$recovery_url = $view_admin_as_role->get_recovery_url_for_settings( get_current_user_id() );
|
|
$field_description = '<div class="asenha-warning"><strong>' . sprintf(
|
|
/* translators: %s is the secret recovery URL or instructional text */
|
|
__( 'If something goes wrong</strong> and you need to regain access to your account as an administrator, please visit the following URL: <br /><strong>%s</strong><br /><br />If you use <strong>Ninja Firewall</strong>, please uncheck "Block attempts to gain administrative privileges" in the Firewall Policies settings before you try to view as a non-admin user role to <strong>prevent being locked out</strong> of your admin account.', 'admin-site-enhancements' ),
|
|
esc_html( $recovery_url )
|
|
) . '<br /><br />' . __( 'In any case, please also <strong>create at least one backup admin user</strong> as a last resort should your primary admin user fails to properly login as admin. With this second admin user, you can also restore the admin role for your primary admin user.', 'admin-site-enhancements' ) . '</div>';
|
|
echo '<div class="asenha-subfield-description">' . wp_kses( $field_description, get_kses_with_style_src_svg_ruleset() ) . '</div>';
|
|
}
|
|
|
|
/**
|
|
* Render heading for sub-fields of a toggle/switcher checkbox
|
|
*
|
|
* @since 5.0.0
|
|
*/
|
|
function render_subfields_heading( $args ) {
|
|
$subfields_heading = $args['subfields_heading'];
|
|
echo '<div class="asenha-subfields-heading">' . wp_kses_post( $subfields_heading ) . '</div>';
|
|
}
|
|
|
|
/**
|
|
* Render password field as sub-field of a toggle/switcher checkbox
|
|
*
|
|
* @since 4.1.0
|
|
*/
|
|
function render_password_subfield( $args ) {
|
|
$option_name = $args['option_name'];
|
|
if ( !empty( $option_name ) ) {
|
|
$options = get_option( $option_name, array() );
|
|
} else {
|
|
$options = get_option( ASENHA_SLUG_U, array() );
|
|
}
|
|
$field_id = $args['field_id'];
|
|
$field_name = $args['field_name'];
|
|
$field_type = $args['field_type'];
|
|
$field_prefix = $args['field_prefix'];
|
|
$field_suffix = $args['field_suffix'];
|
|
$field_description = $args['field_description'];
|
|
$field_option_value = ( isset( $options[$args['field_id']] ) ? $options[$args['field_id']] : '' );
|
|
$hide_stored_value = ( isset( $args['hide_stored_value'] ) ? (bool) $args['hide_stored_value'] : false );
|
|
if ( !empty( $field_prefix ) && !empty( $field_suffix ) ) {
|
|
$field_classname = ' with-prefix with-suffix';
|
|
} elseif ( !empty( $field_prefix ) && empty( $field_suffix ) ) {
|
|
$field_classname = ' with-prefix';
|
|
} elseif ( empty( $field_prefix ) && !empty( $field_suffix ) ) {
|
|
$field_classname = ' with-suffix';
|
|
} else {
|
|
$field_classname = '';
|
|
}
|
|
if ( $hide_stored_value ) {
|
|
$field_option_value = '';
|
|
}
|
|
$placeholder = ( isset( $args['field_placeholder'] ) ? $args['field_placeholder'] : '' );
|
|
echo wp_kses_post( $field_prefix ) . '<input type="password" id="' . esc_attr( $field_name ) . '" class="asenha-subfield-password' . esc_attr( $field_classname ) . '" name="' . esc_attr( $field_name ) . '" placeholder="' . esc_attr( $placeholder ) . '" size="24" autocomplete="off" value="' . esc_attr( $field_option_value ) . '">' . wp_kses_post( $field_suffix );
|
|
echo '<label for="' . esc_attr( $field_name ) . '" class="asenha-subfield-checkbox-label">' . esc_html( $field_description ) . '</label>';
|
|
}
|
|
|
|
/**
|
|
* Render number field as sub-field of a toggle/switcher checkbox
|
|
*
|
|
* @since 1.4.0
|
|
*/
|
|
function render_number_subfield( $args ) {
|
|
$option_name = $args['option_name'];
|
|
if ( !empty( $option_name ) ) {
|
|
$options = get_option( $option_name, array() );
|
|
} else {
|
|
$options = get_option( ASENHA_SLUG_U, array() );
|
|
}
|
|
$field_id = $args['field_id'];
|
|
$field_name = $args['field_name'];
|
|
$field_type = $args['field_type'];
|
|
$field_prefix = $args['field_prefix'];
|
|
$field_suffix = $args['field_suffix'];
|
|
$field_intro = $args['field_intro'];
|
|
$field_placeholder = ( isset( $args['field_placeholder'] ) ? $args['field_placeholder'] : '' );
|
|
$field_min = ( isset( $args['field_min'] ) ? $args['field_min'] : 1 );
|
|
$field_max = ( isset( $args['field_max'] ) ? $args['field_max'] : 10 );
|
|
$field_description = ( isset( $args['field_description'] ) ? $args['field_description'] : '' );
|
|
$field_option_value = ( isset( $options[$args['field_id']] ) ? $options[$args['field_id']] : '' );
|
|
if ( !empty( $field_prefix ) && !empty( $field_suffix ) ) {
|
|
$field_classname = ' with-prefix with-suffix';
|
|
} elseif ( !empty( $field_prefix ) && empty( $field_suffix ) ) {
|
|
$field_classname = ' with-prefix';
|
|
} elseif ( empty( $field_prefix ) && !empty( $field_suffix ) ) {
|
|
$field_classname = ' with-suffix';
|
|
} else {
|
|
$field_classname = '';
|
|
}
|
|
echo '<div class="asenha-subfield-number-wrapper">';
|
|
if ( !empty( $field_intro ) ) {
|
|
echo '<div class="asenha-subfield-number-intro">' . wp_kses_post( $field_intro ) . '</div>';
|
|
}
|
|
echo '<div>' . wp_kses_post( $field_prefix ) . '<input type="number" id="' . esc_attr( $field_name ) . '" class="asenha-subfield-number' . esc_attr( $field_classname ) . '" name="' . esc_attr( $field_name ) . '" placeholder="' . esc_attr( $field_placeholder ) . '" step="1" min="' . esc_attr( $field_min ) . '" max="' . esc_attr( $field_max ) . '" value="' . esc_attr( $field_option_value ) . '">' . wp_kses_post( $field_suffix ) . '</div>';
|
|
if ( !empty( $field_description ) ) {
|
|
echo '<div class="asenha-subfield-number-description">' . wp_kses_post( $field_description ) . '</div>';
|
|
}
|
|
echo '</div>';
|
|
}
|
|
|
|
/**
|
|
* Render select field as sub-field of a toggle/switcher checkbox
|
|
*
|
|
* @since 1.4.0
|
|
*/
|
|
function render_select_subfield( $args ) {
|
|
$option_name = $args['option_name'];
|
|
if ( !empty( $option_name ) ) {
|
|
$options = get_option( $option_name, array() );
|
|
} else {
|
|
$options = get_option( ASENHA_SLUG_U, array() );
|
|
}
|
|
$field_id = $args['field_id'];
|
|
$field_name = $args['field_name'];
|
|
$field_type = $args['field_type'];
|
|
$field_prefix = $args['field_prefix'];
|
|
$field_suffix = $args['field_suffix'];
|
|
$field_select_options = $args['field_select_options'];
|
|
$field_select_default = $args['field_select_default'];
|
|
$field_intro = $args['field_intro'];
|
|
$field_description = $args['field_description'];
|
|
$parent_field_id = ( isset( $args['parent_field_id'] ) ? $args['parent_field_id'] : '' );
|
|
$sub_field_id = ( isset( $args['sub_field_id'] ) ? $args['sub_field_id'] : '' );
|
|
if ( !empty( $field_select_default ) ) {
|
|
$default_value = $field_select_default;
|
|
} else {
|
|
$default_value = false;
|
|
}
|
|
if ( !empty( $parent_field_id ) && !empty( $sub_field_id ) && isset( $options[$parent_field_id][$sub_field_id][$field_id] ) ) {
|
|
$field_option_value = $options[$parent_field_id][$sub_field_id][$field_id];
|
|
} else {
|
|
$field_option_value = ( isset( $options[$field_id] ) ? $options[$field_id] : $default_value );
|
|
}
|
|
if ( !empty( $field_prefix ) && !empty( $field_suffix ) ) {
|
|
$field_classname = ' with-prefix with-suffix';
|
|
} elseif ( !empty( $field_prefix ) && empty( $field_suffix ) ) {
|
|
$field_classname = ' with-prefix';
|
|
} elseif ( empty( $field_prefix ) && !empty( $field_suffix ) ) {
|
|
$field_classname = ' with-suffix';
|
|
} else {
|
|
$field_classname = '';
|
|
}
|
|
$display_none_on_load = ( isset( $args['display_none_on_load'] ) ? $args['display_none_on_load'] : false );
|
|
if ( $display_none_on_load ) {
|
|
$inline_style = 'display:none;';
|
|
} else {
|
|
$inline_style = '';
|
|
}
|
|
echo '<div class="asenha-subfield-select-wrapper">';
|
|
if ( !empty( $field_intro ) ) {
|
|
echo '<div class="asenha-subfield-select-intro">' . wp_kses_post( $field_intro ) . '</div>';
|
|
}
|
|
echo '<div style="' . esc_attr( $inline_style ) . '" class="asenha-subfield-select-inner">' . wp_kses_post( $field_prefix );
|
|
echo '<select name="' . esc_attr( $field_name ) . '" class="asenha-subfield-select' . esc_attr( $field_classname ) . '">';
|
|
foreach ( $field_select_options as $label => $value ) {
|
|
echo '<option value="' . esc_attr( $value ) . '" ' . selected( $value, $field_option_value, false ) . '>' . esc_html( $label ) . '</option>';
|
|
}
|
|
echo '</select>';
|
|
echo wp_kses_post( $field_suffix ) . '</div>';
|
|
if ( !empty( $field_description ) ) {
|
|
echo '<div class="asenha-subfield-select-description">' . wp_kses_post( $field_description ) . '</div>';
|
|
}
|
|
echo '</div>';
|
|
}
|
|
|
|
/**
|
|
* Render textarea field as sub-field of a toggle/switcher checkbox
|
|
*
|
|
* @since 2.3.0
|
|
*/
|
|
function render_textarea_subfield( $args ) {
|
|
$option_name = $args['option_name'];
|
|
if ( !empty( $option_name ) ) {
|
|
$options = get_option( $option_name, array() );
|
|
} else {
|
|
$options = get_option( ASENHA_SLUG_U, array() );
|
|
}
|
|
$field_id = $args['field_id'];
|
|
$field_slug = $args['field_slug'];
|
|
$field_name = $args['field_name'];
|
|
$field_type = $args['field_type'];
|
|
$field_rows = $args['field_rows'];
|
|
$field_intro = $args['field_intro'];
|
|
$field_description = $args['field_description'];
|
|
$field_placeholder = ( isset( $args['field_placeholder'] ) ? $args['field_placeholder'] : '' );
|
|
// Always load textarea content from robots.txt URL, whether it's a real, custom-made robots.txt file or a virtual one generated by WordPress
|
|
if ( 'robots_txt_content' == $field_id ) {
|
|
if ( array_key_exists( 'manage_robots_txt', $options ) ) {
|
|
// Manage robots.txt feature has been enabled before
|
|
if ( !$options['manage_robots_txt'] ) {
|
|
// Manage robots.txt feature is NOT enabled
|
|
if ( array_key_exists( 'robots_txt_content', $options ) && $options['robots_txt_content'] ) {
|
|
$field_option_value = $options['robots_txt_content'];
|
|
} else {
|
|
$robots_txt_content = wp_remote_get( get_site_url() . '/robots.txt' );
|
|
$robots_txt_content = esc_textarea( trim( wp_remote_retrieve_body( $robots_txt_content ) ) );
|
|
$field_option_value = $robots_txt_content;
|
|
}
|
|
} else {
|
|
// Manage robots.txt feature is enabled
|
|
if ( array_key_exists( 'robots_txt_content', $options ) && $options['robots_txt_content'] ) {
|
|
$field_option_value = $options['robots_txt_content'];
|
|
} else {
|
|
$robots_txt_content = wp_remote_get( get_site_url() . '/robots.txt' );
|
|
$robots_txt_content = esc_textarea( trim( wp_remote_retrieve_body( $robots_txt_content ) ) );
|
|
$field_option_value = $robots_txt_content;
|
|
}
|
|
}
|
|
} else {
|
|
// Manage robots.txt feature has never been enabled yet
|
|
$robots_txt_content = wp_remote_get( get_site_url() . '/robots.txt' );
|
|
$robots_txt_content = esc_textarea( trim( wp_remote_retrieve_body( $robots_txt_content ) ) );
|
|
$field_option_value = $robots_txt_content;
|
|
}
|
|
} else {
|
|
$field_option_value = ( isset( $options[$args['field_id']] ) ? $options[$args['field_id']] : '' );
|
|
}
|
|
echo '<div class="asenha-subfield-textarea-wrapper">';
|
|
if ( !empty( $field_intro ) ) {
|
|
echo '<div class="asenha-subfield-textarea-intro">' . wp_kses_post( $field_intro ) . '</div>';
|
|
}
|
|
echo '<textarea rows="' . esc_attr( $field_rows ) . '" class="asenha-subfield-textarea" id="' . esc_attr( $field_name ) . '" name="' . esc_attr( $field_name ) . '" placeholder="' . esc_attr( $field_placeholder ) . '">' . esc_textarea( $field_option_value ) . '</textarea>';
|
|
if ( !empty( $field_description ) ) {
|
|
echo '<div class="asenha-subfield-textarea-description">' . wp_kses_post( $field_description ) . '</div>';
|
|
}
|
|
echo '</div>';
|
|
}
|
|
|
|
/**
|
|
* Render textarea field as sub-field of a toggle/switcher checkbox
|
|
*
|
|
* @since 2.3.0
|
|
*/
|
|
function render_wpeditor_subfield( $args ) {
|
|
$option_name = $args['option_name'];
|
|
if ( !empty( $option_name ) ) {
|
|
$options = get_option( $option_name, array() );
|
|
} else {
|
|
$options = get_option( ASENHA_SLUG_U, array() );
|
|
}
|
|
$field_id = $args['field_id'];
|
|
$field_slug = $args['field_slug'];
|
|
$field_name = $args['field_name'];
|
|
$field_type = $args['field_type'];
|
|
$field_intro = $args['field_intro'];
|
|
$field_description = $args['field_description'];
|
|
$field_placeholder = ( isset( $args['field_placeholder'] ) ? $args['field_placeholder'] : '' );
|
|
$field_option_value = ( isset( $options[$args['field_id']] ) ? $options[$args['field_id']] : '' );
|
|
$editor_settings = $args['editor_settings'];
|
|
// https://developer.wordpress.org/reference/classes/_wp_editors/parse_settings/
|
|
echo '<div class="asenha-subfield-wpeditor-wrapper">';
|
|
if ( !empty( $field_intro ) ) {
|
|
echo '<div class="asenha-subfield-wpeditor-intro">' . wp_kses_post( $field_intro ) . '</div>';
|
|
}
|
|
$content = $field_option_value;
|
|
$editor_id = str_replace( array('[', ']'), array('--', ''), $field_name );
|
|
// vi( $editor_id, '', 'for ' . $field_name );
|
|
// phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
|
|
echo wp_editor( $content, $editor_id, $editor_settings );
|
|
if ( !empty( $field_description ) ) {
|
|
echo '<div class="asenha-subfield-wpeditor-description">' . wp_kses_post( $field_description ) . '</div>';
|
|
}
|
|
echo '</div>';
|
|
}
|
|
|
|
/**
|
|
* Render custom HTML subfield
|
|
*
|
|
* @since 5.3.0
|
|
*/
|
|
function render_custom_html( $args ) {
|
|
echo wp_kses( $args['html'], get_kses_with_custom_html_ruleset() );
|
|
}
|
|
|
|
/**
|
|
* Render media subfield
|
|
*
|
|
* @since 6.2.2
|
|
*/
|
|
function render_media_subfield( $args ) {
|
|
$field_id = $args['field_id'];
|
|
$field_slug = $args['field_slug'];
|
|
$field_name = $args['field_name'];
|
|
$field_media_frame_title = $args['field_media_frame_title'];
|
|
$field_media_frame_multiple = $args['field_media_frame_multiple'];
|
|
$field_media_frame_library_type = $args['field_media_frame_library_type'];
|
|
$field_media_frame_button_text = $args['field_media_frame_button_text'];
|
|
$field_intro = $args['field_intro'];
|
|
$field_description = $args['field_description'];
|
|
$options = get_option( $args['option_name'], array() );
|
|
$field_option_value = ( isset( $options[$field_id] ) ? $options[$field_id] : '' );
|
|
?>
|
|
<div class="media-subfield-wrapper">
|
|
<input id="<?php
|
|
echo esc_attr( $field_slug );
|
|
?>" class="image-picker" type="text" size="40" name="<?php
|
|
echo esc_attr( $field_name );
|
|
?>" value="<?php
|
|
echo esc_url( $field_option_value );
|
|
?>" />
|
|
<button id="<?php
|
|
echo esc_attr( $field_slug );
|
|
?>-button" class="image-picker-button button-secondary"><?php
|
|
echo __( 'Select an Image', 'admin-site-enhancements' );
|
|
?></button>
|
|
<?php
|
|
if ( array_key_exists( 'field_hidden_inputs', $args ) && is_array( $args['field_hidden_inputs'] ) ) {
|
|
foreach ( $args['field_hidden_inputs'] as $hidden_input ) {
|
|
$hidden_option_key = ( isset( $hidden_input['option_key'] ) ? sanitize_key( $hidden_input['option_key'] ) : '' );
|
|
$hidden_id = ( isset( $hidden_input['field_id'] ) ? (string) $hidden_input['field_id'] : '' );
|
|
$hidden_name = ( isset( $hidden_input['field_name'] ) ? (string) $hidden_input['field_name'] : '' );
|
|
if ( empty( $hidden_option_key ) || empty( $hidden_id ) || empty( $hidden_name ) ) {
|
|
continue;
|
|
}
|
|
$hidden_value = ( isset( $options[$hidden_option_key] ) ? absint( $options[$hidden_option_key] ) : 0 );
|
|
echo '<input type="hidden" id="' . esc_attr( $hidden_id ) . '" class="asenha-hidden-media-dim" name="' . esc_attr( $hidden_name ) . '" value="' . esc_attr( $hidden_value ) . '" />';
|
|
}
|
|
}
|
|
?>
|
|
<?php
|
|
if ( !empty( $field_description ) ) {
|
|
echo '<div class="asenha-subfield-description media-subfield">' . wp_kses_post( $field_description ) . '</div>';
|
|
}
|
|
?>
|
|
</div>
|
|
<?php
|
|
}
|
|
|
|
/**
|
|
* Render media subfield
|
|
*
|
|
* @since 6.2.2
|
|
*/
|
|
function render_color_picker_subfield( $args ) {
|
|
$common_methods = new Common_Methods();
|
|
$field_id = $args['field_id'];
|
|
$field_slug = $args['field_slug'];
|
|
$field_name = $args['field_name'];
|
|
$field_intro = $args['field_intro'];
|
|
$field_description = $args['field_description'];
|
|
$field_default_value = $args['field_default_value'];
|
|
$options = get_option( $args['option_name'], array() );
|
|
$field_option_value = ( isset( $options[$field_id] ) ? $options[$field_id] : $field_default_value );
|
|
?>
|
|
<div class="color-subfield-wrapper">
|
|
<input type="text" id="<?php
|
|
echo esc_attr( $field_slug );
|
|
?>" name="<?php
|
|
echo esc_attr( $field_name );
|
|
?>" value="<?php
|
|
echo esc_attr( $common_methods->sanitize_hex_color( $field_option_value ) );
|
|
?>" data-default-color="<?php
|
|
echo esc_attr( $common_methods->sanitize_hex_color( $field_default_value ) );
|
|
?>" class="color-picker"/>
|
|
</div>
|
|
<?php
|
|
}
|
|
|
|
/**
|
|
* Render text field as sub-field of a toggle/switcher checkbox
|
|
*
|
|
* @since 1.4.0
|
|
*/
|
|
function render_content_toggler( $args ) {
|
|
$field_id = $args['field_id'];
|
|
$field_slug = $args['field_slug'];
|
|
$field_slug = str_replace( '_', '-', $field_id );
|
|
$show_text = ( isset( $args['show_text'] ) ? $args['show_text'] : '' );
|
|
$hide_text = ( isset( $args['hide_text'] ) ? $args['hide_text'] : '' );
|
|
$content_selector = ( isset( $args['content_selector'] ) ? $args['content_selector'] : '' );
|
|
?>
|
|
<div class="subfield-content-toggler <?php
|
|
echo esc_attr( $field_slug );
|
|
?>"><a href="#" data-show-text="<?php
|
|
echo esc_attr( $show_text );
|
|
?>" data-hide-text="<?php
|
|
echo esc_attr( $hide_text );
|
|
?>" data-target-selector="<?php
|
|
echo esc_attr( $content_selector );
|
|
?>" class="asenha-content-toggler" data-expanded="no"><?php
|
|
echo esc_html( $show_text );
|
|
?> <span>▼</span></a></div>
|
|
<?php
|
|
}
|
|
|
|
/**
|
|
* Human-readable label fragment for an admin menu separator slug (AMO sortable UI).
|
|
*
|
|
* WordPress core and plugins use slugs like separator1, separator-last, separator-woocommerce.
|
|
* Internal slugs stay unchanged; this output is display-only (Spacer-* wording).
|
|
*
|
|
* @since 8.5.3
|
|
*
|
|
* @param string $menu_slug Separator menu slug from global $menu item index 2.
|
|
* @return string Middle segment only (without surrounding ~~); safe for esc_html when wrapped.
|
|
*/
|
|
private function format_admin_menu_separator_slug_for_display( $menu_slug ) {
|
|
$name = str_replace( 'separator', 'Spacer-', $menu_slug );
|
|
$name = str_replace( '--last', '-Last', $name );
|
|
$name = str_replace( '--woocommerce', '--WooCommerce', $name );
|
|
return $name;
|
|
}
|
|
|
|
/**
|
|
* Render sortable menu field
|
|
*
|
|
* @since 2.0.0
|
|
*/
|
|
function render_sortable_menu() {
|
|
$triangle_right_icon = '<svg xmlns="http://www.w3.org/2000/svg" width="10" height="10" viewBox="0 0 16 16"><path fill="currentColor" d="M14.222 6.687a1.5 1.5 0 0 1 0 2.629l-10 5.499A1.5 1.5 0 0 1 2 13.5V2.502a1.5 1.5 0 0 1 2.223-1.314z"/></svg>';
|
|
?>
|
|
<ul id="custom-admin-menu" class="menu ui-sortable">
|
|
<?php
|
|
global $menu, $submenu;
|
|
$common_methods = new Common_Methods();
|
|
$options_extra = get_option( ASENHA_SLUG_U . '_extra', array() );
|
|
$options = ( isset( $options_extra['admin_menu'] ) ? $options_extra['admin_menu'] : array() );
|
|
// Parsed early so Pro merge of custom spacers and render loops can use the same list.
|
|
$deleted_separators = ( isset( $options['custom_menu_deleted_separators'] ) ? $options['custom_menu_deleted_separators'] : '' );
|
|
$deleted_separators_array = array();
|
|
if ( is_string( $deleted_separators ) && !empty( $deleted_separators ) ) {
|
|
$deleted_separators_array = json_decode( $deleted_separators, true );
|
|
if ( !is_array( $deleted_separators_array ) ) {
|
|
$deleted_separators_array = array();
|
|
}
|
|
}
|
|
// Set menu items to be excluded from title renaming. These are from WordPress core.
|
|
$renaming_not_allowed = array(
|
|
'menu-dashboard',
|
|
'menu-pages',
|
|
// 'menu-posts',
|
|
'menu-media',
|
|
'menu-comments',
|
|
'menu-appearance',
|
|
'menu-plugins',
|
|
'menu-users',
|
|
'menu-tools',
|
|
'menu-settings',
|
|
);
|
|
// Get custom menu item titles
|
|
if ( array_key_exists( 'custom_menu_titles', $options ) ) {
|
|
$custom_menu_titles = $options['custom_menu_titles'];
|
|
$custom_menu_titles = explode( ',', $custom_menu_titles );
|
|
} else {
|
|
$custom_menu_titles = array();
|
|
}
|
|
// Get menu items hidden by toggle
|
|
$menu_hidden_by_toggle = $common_methods->get_menu_hidden_by_toggle();
|
|
$i = 1;
|
|
// Check if there's an existing custom menu order data stored in options
|
|
if ( array_key_exists( 'custom_menu_order', $options ) ) {
|
|
$custom_menu = $options['custom_menu_order'];
|
|
$custom_menu = explode( ',', $custom_menu );
|
|
$menu_key_in_use = array();
|
|
// Render sortables with data in custom menu order
|
|
foreach ( $custom_menu as $custom_menu_item ) {
|
|
foreach ( $menu as $menu_key => $menu_info ) {
|
|
// Skip deleted built-in separators only for real separator rows; Pro distinguishes ASE additional-separator rows.
|
|
$skip_deleted_separator = false;
|
|
if ( isset( $menu_info[2], $menu_info[4] ) && false !== strpos( $menu_info[4], 'wp-menu-separator' ) ) {
|
|
$skip_deleted_separator = in_array( $menu_info[2], $deleted_separators_array, true );
|
|
}
|
|
if ( $skip_deleted_separator ) {
|
|
continue;
|
|
}
|
|
if ( false !== strpos( $menu_info[4], 'wp-menu-separator' ) ) {
|
|
$menu_item_title = $menu_info[2];
|
|
$menu_item_id = $menu_info[2];
|
|
} else {
|
|
$menu_item_title = $menu_info[0];
|
|
$menu_item_id = $menu_info[5];
|
|
}
|
|
$menu_url_fragment = '';
|
|
if ( $custom_menu_item == $menu_item_id ) {
|
|
$menu_item_id_transformed = $common_methods->transform_menu_item_id( $menu_item_id );
|
|
$is_custom_menu = 'no';
|
|
$menu_required_capability = ( isset( $menu_info[1] ) ? $menu_info[1] : '' );
|
|
?>
|
|
<li id="<?php
|
|
echo esc_attr( $menu_item_id );
|
|
?>" class="menu-item parent-menu-item menu-item-depth-0" data-custom-menu-item="<?php
|
|
echo esc_attr( $is_custom_menu );
|
|
?>" data-menu-slug="<?php
|
|
echo esc_attr( $menu_info[2] );
|
|
?>">
|
|
<div class="menu-item-bar">
|
|
<div class="menu-item-handle">
|
|
<span class="dashicons dashicons-menu"></span>
|
|
<div class="item-title">
|
|
<div class="title-wrapper">
|
|
<span class="menu-item-title">
|
|
<?php
|
|
if ( false !== strpos( $menu_info[4], 'wp-menu-separator' ) ) {
|
|
echo '~~ ' . esc_html( $this->format_admin_menu_separator_slug_for_display( $menu_info[2] ) ) . ' ~~';
|
|
} else {
|
|
if ( in_array( $menu_item_id, $renaming_not_allowed ) ) {
|
|
$menu_item_title = $menu_info[0];
|
|
echo wp_kses_post( $common_methods->strip_html_tags_and_content( $menu_item_title ) );
|
|
} else {
|
|
// Get defaul/custom menu item title
|
|
foreach ( $custom_menu_titles as $custom_menu_title ) {
|
|
// At this point, $custom_menu_title value looks like toplevel_page_snippets__Code Snippets
|
|
$custom_menu_title = explode( '__', $custom_menu_title );
|
|
if ( $custom_menu_title[0] == $menu_item_id ) {
|
|
$menu_item_title = $common_methods->strip_html_tags_and_content( $custom_menu_title[1] );
|
|
// e.g. Code Snippets
|
|
break;
|
|
// stop foreach loop so $menu_item_title is not overwritten in the next iteration
|
|
} else {
|
|
$menu_item_title = $common_methods->strip_html_tags_and_content( $menu_info[0] );
|
|
}
|
|
}
|
|
?>
|
|
<input type="text" value="<?php
|
|
echo wp_kses_post( wp_unslash( $menu_item_title ) );
|
|
?>" class="menu-item-custom-title" data-menu-item-id="<?php
|
|
echo esc_attr( $menu_item_id );
|
|
?>">
|
|
<?php
|
|
}
|
|
}
|
|
?>
|
|
</span><!-- end of .menu-item-title -->
|
|
<?php
|
|
?>
|
|
</div><!-- end of .title-wrapper -->
|
|
<div class="options-for-hiding">
|
|
<?php
|
|
$hide_text = __( 'Hide until toggled', 'admin-site-enhancements' );
|
|
$checkbox_class = 'parent-menu-hide-checkbox';
|
|
?>
|
|
<label class="menu-item-checkbox-label">
|
|
<?php
|
|
if ( in_array( $custom_menu_item, $menu_hidden_by_toggle ) ) {
|
|
?>
|
|
<input type="checkbox" id="hide-status-for-<?php
|
|
echo esc_attr( $menu_item_id_transformed );
|
|
?>" class="<?php
|
|
echo esc_attr( $checkbox_class );
|
|
?>" data-menu-item-title="<?php
|
|
echo esc_attr( $common_methods->strip_html_tags_and_content( $menu_item_title ) );
|
|
?>" data-menu-item-id="<?php
|
|
echo esc_attr( $menu_item_id_transformed );
|
|
?>" data-menu-item-id-ori="<?php
|
|
echo esc_attr( $menu_item_id );
|
|
?>" data-menu-url-fragment="<?php
|
|
echo esc_attr( $menu_url_fragment );
|
|
?>" data-required-capability="<?php
|
|
echo esc_attr( $menu_required_capability );
|
|
?>" checked>
|
|
<span><?php
|
|
echo esc_html( $hide_text );
|
|
?></span>
|
|
<?php
|
|
} else {
|
|
?>
|
|
<input type="checkbox" id="hide-status-for-<?php
|
|
echo esc_attr( $menu_item_id_transformed );
|
|
?>" class="<?php
|
|
echo esc_attr( $checkbox_class );
|
|
?>" data-menu-item-title="<?php
|
|
echo esc_attr( $common_methods->strip_html_tags_and_content( $menu_item_title ) );
|
|
?>" data-menu-item-id="<?php
|
|
echo esc_attr( $menu_item_id_transformed );
|
|
?>" data-menu-item-id-ori="<?php
|
|
echo esc_attr( $menu_item_id );
|
|
?>" data-menu-url-fragment="<?php
|
|
echo esc_attr( $menu_url_fragment );
|
|
?>" data-required-capability="<?php
|
|
echo esc_attr( $menu_required_capability );
|
|
?>">
|
|
<span><?php
|
|
echo esc_html( $hide_text );
|
|
?></span>
|
|
<?php
|
|
}
|
|
?>
|
|
</label>
|
|
<?php
|
|
?>
|
|
</div><!-- end of .options-for-hiding -->
|
|
</div><!-- end of .item-title -->
|
|
</div><!-- end of .menu-item-handle -->
|
|
</div><!-- end of .menu-item-bar -->
|
|
<?php
|
|
$i = 1;
|
|
?>
|
|
</li>
|
|
<?php
|
|
$menu_key_in_use[] = $menu_key;
|
|
}
|
|
}
|
|
}
|
|
// Render the rest of the current menu towards the end of the sortables
|
|
foreach ( $menu as $menu_key => $menu_info ) {
|
|
if ( !in_array( $menu_key, $menu_key_in_use ) ) {
|
|
// Skip deleted built-in separators only for real separator rows; Pro distinguishes ASE additional-separator rows.
|
|
$skip_deleted_separator = false;
|
|
if ( isset( $menu_info[2], $menu_info[4] ) && false !== strpos( $menu_info[4], 'wp-menu-separator' ) ) {
|
|
$skip_deleted_separator = in_array( $menu_info[2], $deleted_separators_array, true );
|
|
}
|
|
if ( $skip_deleted_separator ) {
|
|
continue;
|
|
}
|
|
if ( false !== strpos( $menu_info[4], 'wp-menu-separator' ) ) {
|
|
$menu_item_id = $menu_info[2];
|
|
} else {
|
|
$menu_item_id = $menu_info[5];
|
|
}
|
|
$menu_item_title = $menu_info[0];
|
|
$menu_url_fragment = '';
|
|
// Strip tags
|
|
$menu_item_title = $common_methods->strip_html_tags_and_content( $menu_item_title );
|
|
// Exclude Show All/Less toggles
|
|
if ( false === strpos( $menu_item_id, 'toplevel_page_asenha_' ) ) {
|
|
$menu_item_id_transformed = $common_methods->transform_menu_item_id( $menu_item_id );
|
|
$is_custom_menu = 'no';
|
|
$menu_required_capability = ( isset( $menu_info[1] ) ? $menu_info[1] : '' );
|
|
?>
|
|
<li id="<?php
|
|
echo esc_attr( $menu_item_id );
|
|
?>" class="menu-item parent-menu-item menu-item-depth-0" data-custom-menu-item="<?php
|
|
echo esc_attr( $is_custom_menu );
|
|
?>">
|
|
<div class="menu-item-bar">
|
|
<div class="menu-item-handle">
|
|
<span class="dashicons dashicons-menu"></span>
|
|
<div class="item-title">
|
|
<div class="title-wrapper">
|
|
<span class="menu-item-title">
|
|
<?php
|
|
if ( false !== strpos( $menu_info[4], 'wp-menu-separator' ) ) {
|
|
echo '~~ ' . esc_html( $this->format_admin_menu_separator_slug_for_display( $menu_info[2] ) ) . ' ~~';
|
|
} else {
|
|
?>
|
|
<input type="text" value="<?php
|
|
echo wp_kses_post( wp_unslash( $menu_item_title ) );
|
|
?>" class="menu-item-custom-title" data-menu-item-id="<?php
|
|
echo esc_attr( $menu_item_id );
|
|
?>">
|
|
<?php
|
|
}
|
|
?>
|
|
</span>
|
|
<?php
|
|
?>
|
|
</div>
|
|
<div class="options-for-hiding">
|
|
<?php
|
|
$hide_text = __( 'Hide until toggled', 'admin-site-enhancements' );
|
|
$checkbox_class = 'parent-menu-hide-checkbox';
|
|
?>
|
|
<label class="menu-item-checkbox-label">
|
|
<input type="checkbox" id="hide-status-for-<?php
|
|
echo esc_attr( $menu_item_id_transformed );
|
|
?>" class="<?php
|
|
echo esc_attr( $checkbox_class );
|
|
?>" data-menu-item-title="<?php
|
|
echo esc_attr( $common_methods->strip_html_tags_and_content( $menu_item_title ) );
|
|
?>" data-menu-item-id="<?php
|
|
echo esc_attr( $menu_item_id_transformed );
|
|
?>" data-menu-item-id-ori="<?php
|
|
echo esc_attr( $menu_item_id );
|
|
?>" data-menu-url-fragment="<?php
|
|
echo esc_attr( $menu_url_fragment );
|
|
?>" data-required-capability="<?php
|
|
echo esc_attr( $menu_required_capability );
|
|
?>">
|
|
<span><?php
|
|
echo esc_html( $hide_text );
|
|
?></span>
|
|
</label>
|
|
<?php
|
|
?>
|
|
</div><!-- end of .options-for-hiding -->
|
|
</div><!-- end of .item-title -->
|
|
</div><!-- end of .menu-item-handle -->
|
|
</div><!-- end of .menu-item-bar -->
|
|
<?php
|
|
$i = 1;
|
|
// Add delete icon for saved custom menu items (not separators)
|
|
if ( $is_custom_menu === 'yes' && strpos( $menu_info[2], 'separator' ) === false ) {
|
|
?>
|
|
<div class="remove-custom-menu-item-saved" data-menu-item-id="<?php
|
|
echo esc_attr( $menu_info[2] );
|
|
?>">
|
|
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24">
|
|
<path fill="#bbbbbb" 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>
|
|
</div>
|
|
<?php
|
|
}
|
|
?>
|
|
</li><!-- end of .menu-item -->
|
|
<?php
|
|
}
|
|
}
|
|
}
|
|
} else {
|
|
// No custom menu order has been saved yet
|
|
// Render sortables with existing items in the admin menu
|
|
foreach ( $menu as $menu_key => $menu_info ) {
|
|
// Skip deleted built-in separators only for real separator rows; Pro distinguishes ASE additional-separator rows.
|
|
$skip_deleted_separator = false;
|
|
if ( isset( $menu_info[2], $menu_info[4] ) && false !== strpos( $menu_info[4], 'wp-menu-separator' ) ) {
|
|
$skip_deleted_separator = in_array( $menu_info[2], $deleted_separators_array, true );
|
|
}
|
|
if ( $skip_deleted_separator ) {
|
|
continue;
|
|
}
|
|
if ( false !== strpos( $menu_info[4], 'wp-menu-separator' ) ) {
|
|
$menu_item_id = $menu_info[2];
|
|
} else {
|
|
$menu_item_id = $menu_info[5];
|
|
}
|
|
$menu_url_fragment = '';
|
|
$menu_item_title = $menu_info[0];
|
|
$menu_item_id_transformed = $common_methods->transform_menu_item_id( $menu_item_id );
|
|
// Strip tags
|
|
$menu_item_title = $common_methods->strip_html_tags_and_content( $menu_item_title );
|
|
$is_custom_menu = 'no';
|
|
$menu_required_capability = ( isset( $menu_info[1] ) ? $menu_info[1] : '' );
|
|
$custom_menu_data = null;
|
|
$menu_item_handle_classes = 'menu-item-handle';
|
|
?>
|
|
<li id="<?php
|
|
echo esc_attr( $menu_item_id );
|
|
?>" class="menu-item parent-menu-item menu-item-depth-0" data-custom-menu-item="<?php
|
|
echo esc_attr( $is_custom_menu );
|
|
?>" data-menu-slug="<?php
|
|
echo esc_attr( $menu_info[2] );
|
|
?>">
|
|
<div class="menu-item-bar">
|
|
<div class="<?php
|
|
echo esc_attr( $menu_item_handle_classes );
|
|
?>">
|
|
<span class="dashicons dashicons-menu"></span>
|
|
<div class="item-title">
|
|
<div class="title-wrapper">
|
|
<span class="menu-item-title">
|
|
<?php
|
|
if ( false !== strpos( $menu_info[4], 'wp-menu-separator' ) ) {
|
|
echo '~~ ' . esc_html( $this->format_admin_menu_separator_slug_for_display( $menu_info[2] ) ) . ' ~~';
|
|
} else {
|
|
if ( in_array( $menu_item_id, $renaming_not_allowed ) ) {
|
|
echo wp_kses_post( $menu_item_title );
|
|
} else {
|
|
?>
|
|
<input type="text" value="<?php
|
|
echo wp_kses_post( wp_unslash( $menu_item_title ) );
|
|
?>" class="menu-item-custom-title" data-menu-item-id="<?php
|
|
echo esc_attr( $menu_item_id );
|
|
?>">
|
|
<?php
|
|
}
|
|
}
|
|
?>
|
|
</span>
|
|
<?php
|
|
?>
|
|
</div><!-- end of .title-wrapper -->
|
|
<div class="options-for-hiding">
|
|
<?php
|
|
$hide_text = __( 'Hide until toggled', 'admin-site-enhancements' );
|
|
$checkbox_class = 'parent-menu-hide-checkbox';
|
|
?>
|
|
<label class="menu-item-checkbox-label">
|
|
<input type="checkbox" id="hide-status-for-<?php
|
|
echo esc_attr( $menu_item_id_transformed );
|
|
?>" class="<?php
|
|
echo esc_attr( $checkbox_class );
|
|
?>" data-menu-item-title="<?php
|
|
echo esc_attr( $common_methods->strip_html_tags_and_content( $menu_item_title ) );
|
|
?>" data-menu-item-id="<?php
|
|
echo esc_attr( $menu_item_id_transformed );
|
|
?>" data-menu-item-id-ori="<?php
|
|
echo esc_attr( $menu_item_id );
|
|
?>" data-menu-url-fragment="<?php
|
|
echo esc_attr( $menu_url_fragment );
|
|
?>" data-required-capability="<?php
|
|
echo esc_attr( $menu_required_capability );
|
|
?>">
|
|
<span><?php
|
|
echo esc_html( $hide_text );
|
|
?></span>
|
|
</label>
|
|
<?php
|
|
?>
|
|
</div><!-- end of .options-for-hiding -->
|
|
</div><!-- end of .item-title -->
|
|
</div><!-- end of .menu-item-handle -->
|
|
</div><!-- end of .menu-item-bar -->
|
|
<?php
|
|
$i = 1;
|
|
// Add delete icon for saved custom menu items (not separators)
|
|
if ( $is_custom_menu === 'yes' && strpos( $menu_info[2], 'separator' ) === false ) {
|
|
?>
|
|
<div class="remove-custom-menu-item-saved" data-menu-item-id="<?php
|
|
echo esc_attr( $menu_info[2] );
|
|
?>">
|
|
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24">
|
|
<path fill="#bbbbbb" 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>
|
|
</div>
|
|
<?php
|
|
}
|
|
?>
|
|
</li>
|
|
<?php
|
|
}
|
|
}
|
|
?>
|
|
</ul>
|
|
<?php
|
|
// Hidden input field to store custom menu order (from options as is, or sortupdate) upon clicking Save Changes.
|
|
$field_id = 'custom_menu_order';
|
|
$field_option_value = ( isset( $options[$field_id] ) ? $options[$field_id] : '' );
|
|
echo '<input type="hidden" id="' . esc_attr( $field_id ) . '" class="asenha-subfield-text" name="' . esc_attr( $field_id ) . '" value="' . esc_attr( $field_option_value ) . '">';
|
|
// Hidden input field to store hidden menu items (from options as is, or 'Hide' checkbox clicks) upon clicking Save Changes.
|
|
$this->output_admin_menu_organizer_hidden_field( 'custom_menu_hidden' );
|
|
// Hidden input field to store custom menu titles (from options as is, or custom values entered on each non-WP-default menu items.
|
|
$this->output_admin_menu_organizer_hidden_field( 'custom_menu_titles' );
|
|
}
|
|
|
|
/**
|
|
* Decode and re-encode JSON option values for AMO hidden fields so WordPress-slashed or legacy
|
|
* strings become valid for JavaScript JSON.parse(), without applying stripslashes() to raw strings
|
|
* (which would break JSON \\u Unicode escapes).
|
|
*
|
|
* @since 8.5.3
|
|
*
|
|
* @param string $value Raw option value.
|
|
* @return string
|
|
*/
|
|
private function normalize_admin_menu_json_option_for_output( $value ) {
|
|
if ( !is_string( $value ) || '' === $value ) {
|
|
return $value;
|
|
}
|
|
// Use objects (not associative arrays) so JSON objects stay objects and arrays stay arrays.
|
|
$decoded = json_decode( $value, false );
|
|
if ( JSON_ERROR_NONE === json_last_error() ) {
|
|
return wp_json_encode( $decoded );
|
|
}
|
|
$decoded = json_decode( wp_unslash( $value ), false );
|
|
if ( JSON_ERROR_NONE === json_last_error() ) {
|
|
return wp_json_encode( $decoded );
|
|
}
|
|
return $value;
|
|
}
|
|
|
|
/**
|
|
* Output hidden field
|
|
*
|
|
* @since 6.9.13
|
|
*/
|
|
public function output_admin_menu_organizer_hidden_field( $field_id ) {
|
|
$options_extra = get_option( ASENHA_SLUG_U . '_extra', array() );
|
|
$options = ( isset( $options_extra['admin_menu'] ) ? $options_extra['admin_menu'] : array() );
|
|
$field_name = $field_id;
|
|
$field_option_value = ( isset( $options[$field_id] ) ? $options[$field_id] : '' );
|
|
$json_option_field_ids = array(
|
|
'custom_menu_new_separators',
|
|
'custom_menu_deleted_separators',
|
|
'custom_submenus_order',
|
|
'custom_menu_always_hidden',
|
|
'custom_submenu_always_hidden',
|
|
'custom_menu_new_items'
|
|
);
|
|
if ( in_array( $field_id, $json_option_field_ids, true ) ) {
|
|
$field_option_value = $this->normalize_admin_menu_json_option_for_output( $field_option_value );
|
|
}
|
|
echo '<input type="hidden" id="' . esc_attr( $field_name ) . '" class="asenha-subfield-text" name="' . esc_attr( $field_name ) . '" value="' . esc_attr( $field_option_value ) . '">';
|
|
}
|
|
|
|
/**
|
|
* Render textarea field as sub-field of a toggle/switcher checkbox
|
|
*
|
|
* @since 2.3.0
|
|
*/
|
|
function render_datatable( $args ) {
|
|
global $wpdb;
|
|
$option_name = $args['option_name'];
|
|
if ( !empty( $option_name ) ) {
|
|
$options = get_option( $option_name, array() );
|
|
} else {
|
|
$options = get_option( ASENHA_SLUG_U, array() );
|
|
}
|
|
$field_id = $args['field_id'];
|
|
$field_slug = $args['field_slug'];
|
|
$field_name = $args['field_name'];
|
|
$field_type = $args['field_type'];
|
|
$field_description = $args['field_description'];
|
|
$table_title = $args['table_title'];
|
|
$table_name = $args['table_name'];
|
|
$field_option_value = ( isset( $options[$args['field_id']] ) ? $options[$args['field_id']] : '' );
|
|
$login_fails_allowed = ( isset( $options['login_fails_allowed'] ) ? (int) $options['login_fails_allowed'] : 3 );
|
|
$login_lockout_maxcount = ( isset( $options['login_lockout_maxcount'] ) ? (int) $options['login_lockout_maxcount'] : 3 );
|
|
$login_fails_allowed = ( $login_fails_allowed > 0 ? $login_fails_allowed : 3 );
|
|
$login_lockout_maxcount = ( $login_lockout_maxcount > 0 ? $login_lockout_maxcount : 3 );
|
|
$default_lockout_period = 60 * 15;
|
|
// 15 minutes in seconds.
|
|
$extended_lockout_period = 24 * 60 * 60;
|
|
// 24 hours in seconds.
|
|
$now = time();
|
|
$ip_address_whitelist = array();
|
|
?>
|
|
<table id="login-attempts-log" class="wp-list-table widefat striped datatable">
|
|
<thead>
|
|
<tr class="datatable-tr">
|
|
<th class="datatable-th"><?php
|
|
_e( 'IP Address<br />Last Username', 'admin-site-enhancements' );
|
|
?></th>
|
|
<th class="datatable-th"><?php
|
|
_e( 'Attempts<br />Lockouts', 'admin-site-enhancements' );
|
|
?></th>
|
|
<th class="datatable-th"><?php
|
|
_e( 'Last Attempt On', 'admin-site-enhancements' );
|
|
?></th>
|
|
<th class="datatable-th"><?php
|
|
_e( 'Actions', 'admin-site-enhancements' );
|
|
?></th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
<?php
|
|
$limit = 1000;
|
|
$sql = $wpdb->prepare( "SELECT * FROM {$table_name} ORDER BY unixtime DESC LIMIT %d", array($limit) );
|
|
$entries = $wpdb->get_results( $sql, ARRAY_A );
|
|
foreach ( $entries as $entry ) {
|
|
$unixtime = $entry['unixtime'];
|
|
$ip_address = ( isset( $entry['ip_address'] ) ? (string) $entry['ip_address'] : '' );
|
|
$fail_count = ( isset( $entry['fail_count'] ) ? (int) $entry['fail_count'] : 0 );
|
|
$lockout_count = ( isset( $entry['lockout_count'] ) ? (int) $entry['lockout_count'] : 0 );
|
|
$locked_condition = $fail_count > 0 && $fail_count % $login_fails_allowed === 0;
|
|
$is_extended_lockout = $lockout_count >= $login_lockout_maxcount;
|
|
$lockout_period = ( $is_extended_lockout ? $extended_lockout_period : $default_lockout_period );
|
|
$is_locked_out = $locked_condition && $now - (int) $unixtime <= $lockout_period;
|
|
$is_whitelisted = in_array( $ip_address, $ip_address_whitelist, true );
|
|
if ( function_exists( 'wp_date' ) ) {
|
|
$date = wp_date( 'F j, Y', $unixtime );
|
|
$time = wp_date( 'H:i:s', $unixtime );
|
|
} else {
|
|
$date = date_i18n( 'F j, Y', $unixtime );
|
|
$time = date_i18n( 'H:i:s', $unixtime );
|
|
}
|
|
?>
|
|
<tr class="datatable-tr">
|
|
<td class="datatable-td"><?php
|
|
echo esc_html( $ip_address );
|
|
?><br /><?php
|
|
echo esc_html( $entry['username'] );
|
|
?></td>
|
|
<td class="datatable-td"><?php
|
|
echo esc_html( $fail_count );
|
|
?><br /><?php
|
|
echo esc_html( $lockout_count );
|
|
?></td>
|
|
<td class="datatable-td"><span class="unixtime"><?php
|
|
echo esc_html( $entry['unixtime'] );
|
|
?></span><?php
|
|
echo esc_html( $date );
|
|
?><br /><?php
|
|
echo esc_html( $time );
|
|
?></td>
|
|
<td class="datatable-td">
|
|
<?php
|
|
if ( $is_locked_out && !$is_whitelisted ) {
|
|
?>
|
|
<a href="#" class="button button-secondary button-small asenha-release-login-lock" data-ip-address="<?php
|
|
echo esc_attr( $ip_address );
|
|
?>"><?php
|
|
_e( 'Release Lock', 'admin-site-enhancements' );
|
|
?></a>
|
|
<?php
|
|
}
|
|
?>
|
|
<?php
|
|
?>
|
|
</td>
|
|
</tr>
|
|
<?php
|
|
}
|
|
?>
|
|
</tbody>
|
|
</table>
|
|
<?php
|
|
echo '<div class="asenha-subfield-description">' . esc_html( $field_description ) . '</div>';
|
|
echo '<input type="hidden" id="' . esc_attr( $field_name ) . '" class="asenha-subfield-datatable" name="' . esc_attr( $field_name ) . '" value="' . esc_attr( $field_option_value ) . '">';
|
|
}
|
|
|
|
/**
|
|
* Render checks and status for AVIF support
|
|
*
|
|
* @link https://php.watch/versions/8.1/gd-avif
|
|
* @since 5.7.0
|
|
*/
|
|
public function render_avif_support_status() {
|
|
// Check status of GD extension and it's AVIF support
|
|
if ( extension_loaded( 'gd' ) && function_exists( 'gd_info' ) ) {
|
|
$is_gd_enabled = true;
|
|
$gd_info = gd_info();
|
|
$gd_version = $gd_info['GD Version'];
|
|
$gd_avif_support = ( isset( $gd_info['AVIF Support'] ) ? isset( $gd_info['AVIF Support'] ) : false );
|
|
if ( $gd_avif_support ) {
|
|
$gd_status = $gd_version . ' <span class="supported">' . __( 'with AVIF support', 'admin-site-enhancements' ) . '</span>';
|
|
} else {
|
|
$gd_status = $gd_version . ' <span class="unsupported">' . __( 'without AVIF support', 'admin-site-enhancements' ) . '</span>';
|
|
}
|
|
} else {
|
|
$is_gd_enabled = false;
|
|
$gd_avif_support = false;
|
|
$gd_status = __( 'Not available', 'admin-site-enhancements' );
|
|
}
|
|
// Check status of ImageMagick library and it's AVIF support
|
|
if ( extension_loaded( 'imagick' ) && class_exists( 'Imagick' ) ) {
|
|
$is_imagick_enabled = true;
|
|
$imagick_version = \Imagick::getVersion();
|
|
if ( preg_match( '/((?:[0-9]+\\.?)+)/', $imagick_version['versionString'], $matches ) ) {
|
|
$imagick_version = $matches[0];
|
|
} else {
|
|
$imagick_version = $imagick_version['versionString'];
|
|
}
|
|
if ( version_compare( $imagick_version, '7.0.25', '>=' ) ) {
|
|
$imagick_avif_support = true;
|
|
$imagick_status = $imagick_version . ' <span class="supported">with AVIF support</span>';
|
|
} else {
|
|
$imagick_avif_support = false;
|
|
$imagick_status = $imagick_version . ' <span class="unsupported">without AVIF support</span>';
|
|
}
|
|
} else {
|
|
$is_imagick_enabled = false;
|
|
$imagick_avif_support = false;
|
|
$imagick_status = __( 'Not available', 'admin-site-enhancements' );
|
|
}
|
|
echo '<div class="asenha-subfield-status">';
|
|
echo '<div class="status-title">' . __( 'AVIF Support Status', 'admin-site-enhancements' ) . '</div>';
|
|
echo '<div class="status-body">';
|
|
echo '<div class="status-item"><span class="status-item-title">PHP</span> : ' . wp_kses_post( phpversion() ) . '</div>';
|
|
echo '<div class="status-item"><span class="status-item-title">GD</span> : ' . wp_kses_post( $gd_status ) . '</div>';
|
|
echo '<div class="status-item"><span class="status-item-title">ImageMagick</span> : ' . wp_kses_post( $imagick_status ) . '</div>';
|
|
echo '</div>';
|
|
echo '<div class="status-footer">' . __( 'Full AVIF support requires that your server / hosting has <a href="https://php.watch/versions/8.1/gd-avif" target="_blank">GD extension</a> compiled with AVIF support in PHP 8.1 or greater, or, <a href="https://web.archive.org/web/20240104012918/https://avif.io/blog/tutorials/imagemagick/" target="_blank">ImageMagick 7.0.25 or greater</a> installed. Without either, you can still upload AVIF files but without auto-generation of the smaller thumbnail sizes. A majority of <a href="https://web.archive.org/web/20231207174740/https://avif.io/blog/articles/avif-browser-support/" target="_blank">modern desktop and mobile browsers</a> support the display of AVIF files.', 'admin-site-enhancements' ) . '</div>';
|
|
echo '</div>';
|
|
}
|
|
|
|
}
|