args['admin_bar_priority'] );
// Options page.
add_action( 'admin_menu', array( $this, 'options_page' ) );
// Add a network menu.
if ( 'network' === $redux->args['database'] && $redux->args['network_admin'] ) {
add_action( 'network_admin_menu', array( $this, 'options_page' ) );
}
}
/**
* Class Options Page Function, creates main options page.
*
* @since 1.0.0
* @access public
* @return void
*/
public function options_page() {
$core = $this->core();
// phpcs:ignore Generic.CodeAnalysis.EmptyStatement
if ( 'hidden' === $core->args['menu_type'] ) {
// No menu to add!
} elseif ( 'submenu' === $core->args['menu_type'] ) {
$this->submenu( $core );
} else {
// Theme-Check notice is displayed for WP.org theme devs, informing them to NOT use this.
$this->page = call_user_func(
'add_menu_page',
$core->args['page_title'],
$core->args['menu_title'],
$core->args['page_permissions'],
$core->args['page_slug'],
array(
$this,
'generate_panel',
),
$core->args['menu_icon'],
(int) $core->args['page_priority']
);
if ( true === $core->args['allow_sub_menu'] ) {
foreach ( $core->sections as $k => $section ) {
$can_be_subsection = $k > 0 && ( ! isset( $core->sections[ ( $k ) ]['type'] ) || 'divide' !== $core->sections[ ( $k ) ]['type'] );
if ( ! isset( $section['title'] ) || ( $can_be_subsection && ( isset( $section['subsection'] ) && true === $section['subsection'] ) ) ) {
continue;
}
if ( isset( $section['submenu'] ) && false === $section['submenu'] ) {
continue;
}
if ( isset( $section['customizer_only'] ) && true === $section['customizer_only'] ) {
continue;
}
if ( isset( $section['hidden'] ) && true === $section['hidden'] ) {
continue;
}
if ( isset( $section['permissions'] ) && ! Redux_Helpers::current_user_can( $section['permissions'] ) ) {
continue;
}
// ONLY for non-wp.org themes OR plugins. Theme-Check alert shown if used and IS theme.
call_user_func(
'add_submenu_page',
$core->args['page_slug'],
$section['title'],
$section['title'],
$core->args['page_permissions'],
$core->args['page_slug'] . '&tab=' . $k,
'__return_null'
);
}
// Remove parent submenu item instead of adding null item.
remove_submenu_page( $core->args['page_slug'], $core->args['page_slug'] );
}
}
add_action( "load-$this->page", array( $this, 'load_page' ) );
}
/**
* Show page help
*
* @since 1.0.0
* @access public
* @return void
*/
public function load_page() {
$core = $this->core();
// Do admin head action for this page.
add_action( 'admin_head', array( $this, 'admin_head' ) );
// Do admin footer text hook.
add_filter( 'admin_footer_text', array( $this, 'admin_footer_text' ) );
$screen = get_current_screen();
if ( is_array( $core->args['help_tabs'] ) ) {
foreach ( $core->args['help_tabs'] as $tab ) {
$screen->add_help_tab( $tab );
}
}
// If hint argument is set, display hint tab.
if ( true === $this->show_hints ) {
global $current_user;
$cur_page = '';
// Users enable/disable hint choice.
$hint_status = get_user_meta( $current_user->ID, 'ignore_hints' ) ? get_user_meta( $current_user->ID, 'ignore_hints', true ) : 'true';
// current page parameters.
if ( isset( $_GET['page'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification
$cur_page = sanitize_text_field( wp_unslash( $_GET['page'] ) ); // phpcs:ignore WordPress.Security.NonceVerification
}
$cur_tab = '0';
if ( isset( $_GET['tab'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification
$cur_tab = sanitize_text_field( wp_unslash( $_GET['tab'] ) ); // phpcs:ignore WordPress.Security.NonceVerification
}
// Default url values for enabling hints.
$dismiss = 'true';
$s = esc_html__( 'Enable', 'redux-framework' );
// Values for disabling hints.
if ( 'true' === $hint_status ) {
$dismiss = 'false';
$s = esc_html__( 'Disable', 'redux-framework' );
}
// Make URL.
$nonce = wp_create_nonce( 'redux_hint_toggle' );
$url = '' . $s . ' hints';
$event = esc_html__( 'moving the mouse over', 'redux-framework' );
if ( 'click' === $core->args['hints']['tip_effect']['show']['event'] ) {
$event = esc_html__( 'clicking', 'redux-framework' );
}
// Construct message.
// translators: %1$s: Mouse action. %2$s: Hint status.
$msg = sprintf( esc_html__( 'Hints are tooltips that popup when %1$s the hint icon, offering addition information about the field in which they appear. They can be %2$s by using the link below.', 'redux-framework' ), $event, Redux_Core::strtolower( $s ) ) . '
' . $url;
// Construct hint tab.
$tab = array(
'id' => 'redux-hint-tab',
'title' => esc_html__( 'Hints', 'redux-framework' ),
'content' => '
' . $msg . '
', ); $screen->add_help_tab( $tab ); } // Sidebar text. if ( '' !== $core->args['help_sidebar'] ) { // Specify user's text from arguments. $screen->set_help_sidebar( $core->args['help_sidebar'] ); } elseif ( true === $this->show_hints ) { // If a sidebar text is empty and hints are active, display text // about hints. $screen->set_help_sidebar( 'Redux Framework
' . esc_html__( 'Hint Tooltip Preferences', 'redux-framework' ) . '
' . esc_attr( $field['id'] ) . '', '' . esc_attr( $field['type'] ) . '' );
}
}
}
if ( class_exists( $field_class ) ) {
$value = $core->options[ $field['id'] ] ?? '';
if ( null !== $v ) {
$value = $v;
}
/**
* Action 'redux/field/{opt_name}/{field.type}/render/before'
*
* @param array $field field data
* @param string $value field id
*/
// phpcs:ignore WordPress.NamingConventions.ValidHookName
do_action_ref_array(
// phpcs:ignore WordPress.NamingConventions.ValidHookName
"redux/field/{$core->args['opt_name']}/{$field['type']}/render/before",
array(
&$field,
&$value,
)
);
/**
* Action 'redux/field/{$this->args['opt_name']}/render/before'
*
* @param array $field field data
* @param string $value field id
*/
// phpcs:ignore WordPress.NamingConventions.ValidHookName
do_action_ref_array(
// phpcs:ignore WordPress.NamingConventions.ValidHookName
"redux/field/{$core->args['opt_name']}/render/before",
array(
&$field,
&$value,
)
);
if ( ! isset( $field['name_suffix'] ) ) {
$field['name_suffix'] = '';
}
$render = new $field_class( $field, $value, $core );
ob_start();
try {
$render->render();
} catch ( Error $e ) {
echo 'Field failed to render: ', esc_html( $e->getMessage() ), "\n";
}
/**
* Filter 'redux/field/{opt_name}'
*
* @param string $content Rendered field markup.
* @param array $field field data
*/
// phpcs:ignore WordPress.NamingConventions.ValidHookName
$_render = apply_filters( "redux/field/{$core->args['opt_name']}", ob_get_contents(), $field );
/**
* Filter 'redux/field/{opt_name}/{field.type}/render/after'
*
* @param string $content Rendered field markup.
* @param array $field Field data
*/
// phpcs:ignore WordPress.NamingConventions.ValidHookName
$_render = apply_filters( "redux/field/{$core->args['opt_name']}/{$field['type']}/render/after", $_render, $field );
/**
* Filter 'redux/field/{opt_name}/render/after'
*
* @param string $content Rendered field markup.
* @param array $field Field data
*/
// phpcs:ignore WordPress.NamingConventions.ValidHookName
$_render = apply_filters( "redux/field/{$core->args['opt_name']}/render/after", $_render, $field );
ob_end_clean();
// create default data und class string and checks the dependencies of an object.
$class_string = '';
$core->required_class->check_dependencies( $field );
/**
* Action 'redux/field/{opt_name}/{field.type}/fieldset/before/{opt_name}'
*
* @param array $field field data
* @param string $value field id
*/
// phpcs:ignore WordPress.NamingConventions.ValidHookName
do_action_ref_array(
// phpcs:ignore WordPress.NamingConventions.ValidHookName
"redux/field/{$core->args['opt_name']}/{$field['type']}/fieldset/before/{$core->args['opt_name']}",
array(
&$field,
&$value,
)
);
/**
* Action 'redux/field/{opt_name}/fieldset/before/{opt_name}'
*
* @param array $field field data
* @param string $value field id
*/
// phpcs:ignore WordPress.NamingConventions.ValidHookName
do_action_ref_array(
// phpcs:ignore WordPress.NamingConventions.ValidHookName
"redux/field/{$core->args['opt_name']}/fieldset/before/{$core->args['opt_name']}",
array(
&$field,
&$value,
)
);
$hidden = '';
if ( isset( $field['hidden'] ) && $field['hidden'] ) {
$hidden = 'hidden ';
}
$disabled = '';
if ( isset( $field['disabled'] ) && $field['disabled'] ) {
$disabled = 'disabled ';
}
if ( isset( $field['full_width'] ) && true === $field['full_width'] ) {
$class_string .= 'redux_remove_th';
}
if ( isset( $field['fieldset_class'] ) && ! empty( $field['fieldset_class'] ) ) {
$class_string .= ' ' . $field['fieldset_class'];
}
echo '';
/**
* Action 'redux/field/{opt_name}/{field.type}/fieldset/after/{opt_name}'
*
* @param array $field field data
* @param string $value field id
*/
// phpcs:ignore WordPress.NamingConventions.ValidHookName
do_action_ref_array(
// phpcs:ignore WordPress.NamingConventions.ValidHookName
"redux/field/{$core->args['opt_name']}/{$field['type']}/fieldset/after/{$core->args['opt_name']}",
array(
&$field,
&$value,
)
);
/**
* Action 'redux/field/{opt_name}/fieldset/after/{opt_name}'
*
* @param array $field field data
* @param string $value field id
*/
// phpcs:ignore WordPress.NamingConventions.ValidHookName
do_action_ref_array(
// phpcs:ignore WordPress.NamingConventions.ValidHookName
"redux/field/{$core->args['opt_name']}/fieldset/after/{$core->args['opt_name']}",
array(
&$field,
&$value,
)
);
}
}
}
/**
* Add admin bar menu.
*
* @since 3.1.5.16
* @access public
* @global $menu , $submenu, $wp_admin_bar
* @return void
*/
public function add_menu() {
global $menu, $submenu, $wp_admin_bar;
$core = $this->core();
if ( ! is_super_admin() || ! is_admin_bar_showing() || ! $core->args['admin_bar'] || 'hidden' === $core->args['menu_type'] ) {
return;
}
if ( $menu ) {
foreach ( $menu as $menu_item ) {
if ( isset( $menu_item[2] ) && $menu_item[2] === $core->args['page_slug'] ) {
// Fetch the title.
$title = empty( $core->args['admin_bar_icon'] ) ? $menu_item[0] : '' . esc_html( $menu_item[0] );
$nodeargs = array(
'id' => $menu_item[2],
'title' => $title,
'href' => admin_url( 'admin.php?page=' . $menu_item[2] ),
'meta' => array(),
);
$wp_admin_bar->add_node( $nodeargs );
break;
}
}
if ( isset( $submenu[ $core->args['page_slug'] ] ) && is_array( $submenu[ $core->args['page_slug'] ] ) ) {
foreach ( $submenu[ $core->args['page_slug'] ] as $index => $redux_options_submenu ) {
$subnodeargs = array(
'id' => esc_html( $core->args['page_slug'] . '_' . $index ),
'title' => esc_html( $redux_options_submenu[0] ),
'parent' => esc_html( $core->args['page_slug'] ),
'href' => esc_url( admin_url( 'admin.php?page=' . $redux_options_submenu[2] ) ),
);
$wp_admin_bar->add_node( $subnodeargs );
}
}
// Let's deal with external links.
if ( isset( $core->args['admin_bar_links'] ) ) {
if ( ! $core->args['dev_mode'] && $core->args_class->omit_items ) {
return;
}
// Group for Main Root Menu (External Group).
$wp_admin_bar->add_node(
array(
'id' => esc_html( $core->args['page_slug'] . '-external' ),
'parent' => esc_html( $core->args['page_slug'] ),
'group' => true,
'meta' => array( 'class' => 'ab-sub-secondary' ),
)
);
// Add Child Menus to External Group Menu.
foreach ( $core->args['admin_bar_links'] as $link ) {
if ( ! isset( $link['id'] ) ) {
$link['id'] = $core->args['page_slug'] . '-sub-' . sanitize_html_class( $link['title'] );
}
$externalnodeargs = array(
'id' => esc_html( $link['id'] ),
'title' => esc_html( $link['title'] ),
'parent' => esc_html( $core->args['page_slug'] . '-external' ),
'href' => esc_url( $link['href'] ),
'meta' => array( 'target' => '_blank' ),
);
$wp_admin_bar->add_node( $externalnodeargs );
}
}
} else {
// Fetch the title.
$title = empty( $core->args['admin_bar_icon'] ) ? $core->args['menu_title'] : '' . esc_html( $core->args['menu_title'] );
$nodeargs = array(
'id' => esc_html( $core->args['page_slug'] ),
'title' => $title,
'href' => esc_url( admin_url( 'admin.php?page=' . $core->args['page_slug'] ) ),
'meta' => array(),
);
$wp_admin_bar->add_node( $nodeargs );
}
}
/**
* Do action redux-admin-head for option page
*
* @since 1.0.0
* @access public
* @return void
*/
public function admin_head() {
$core = $this->core();
/**
* Action 'redux/page/{opt_name}/header'
*
* @param object $this ReduxFramework
*/
// phpcs:ignore WordPress.NamingConventions.ValidHookName
do_action( "redux/page/{$core->args['opt_name']}/header", $core );
}
/**
* Return footer text
*
* @since 2.0.0
* @access public
* @return string $this->args['footer_credit']
*/
public function admin_footer_text(): string {
$core = $this->core();
return $core->args['footer_credit'];
}
/**
* Generate field header HTML
*
* @param array $field Field array.
*
* @return string
*/
public function get_header_html( array $field ): string {
global $current_user;
$core = $this->core();
// Set to empty string to avoid warnings.
$hint = '';
$th = '';
if ( isset( $field['title'] ) && isset( $field['type'] ) && 'info' !== $field['type'] && 'section' !== $field['type'] ) {
$default_mark = ( ! empty( $field['default'] ) && isset( $core->options[ $field['id'] ] ) && $field['default'] === $core->options[ $field['id'] ] && ! empty( $core->args['default_mark'] ) ) ? $core->args['default_mark'] : '';
// If a hint is specified in the field, process it.
if ( isset( $field['hint'] ) && ! empty( $field['hint'] ) ) {
// Set the show_hints flag to true, so the help tab will be displayed.
$this->show_hints = true;
// phpcs:ignore WordPress.NamingConventions.ValidHookName
$hint = apply_filters( 'redux/hints/html', $hint, $field, $core->args );
// Get user pref for displaying hints.
$meta_val = get_user_meta( $current_user->ID, 'ignore_hints', true );
if ( 'true' === $meta_val || empty( $meta_val ) && empty( $hint ) ) {
// Set hand cursor for clickable hints.
$pointer = '';
if ( isset( $core->args['hints']['tip_effect']['show']['event'] ) && 'click' === $core->args['hints']['tip_effect']['show']['event'] ) {
$pointer = 'pointer';
}
$size = '16px';
if ( 'large' === $core->args['hints']['icon_size'] ) {
$size = '18px';
}
// In case docs are ignored.
$title_param = $field['hint']['title'] ?? '';
$content_param = $field['hint']['content'] ?? '';
$hint_color = $core->args['hints']['icon_color'] ?? '#d3d3d3';
// Set hint html with appropriate position css.
$hint = '