2018-04-17 23:51:48 +00:00
< ? php
2018-10-23 15:52:18 +00:00
/**
* Admin functions
*
* @ package WC_Admin
*/
2018-05-11 17:07:53 +00:00
/**
* Returns true if we are on a JS powered admin page .
*/
2018-07-10 12:48:06 +00:00
function wc_admin_is_admin_page () {
2018-05-11 17:07:53 +00:00
global $hook_suffix ;
2018-07-10 12:48:06 +00:00
if ( in_array ( $hook_suffix , array ( 'woocommerce_page_wc-admin' ) ) ) {
2018-05-11 17:07:53 +00:00
return true ;
}
return false ;
}
2018-06-26 14:49:42 +00:00
/**
* Returns true if we are on a " classic " ( non JS app ) powered admin page .
* `wc_get_screen_ids` will also return IDs for extensions that have properly registered themselves .
*/
2018-07-10 12:48:06 +00:00
function wc_admin_is_embed_enabled_wc_page () {
2019-02-12 20:02:02 +00:00
if ( ! wc_admin_is_feature_enabled ( 'activity-panels' ) ) {
return false ;
}
2018-07-10 12:48:06 +00:00
$screen_id = wc_admin_get_current_screen_id ();
2018-06-26 14:49:42 +00:00
if ( ! $screen_id ) {
return false ;
}
2018-07-10 12:48:06 +00:00
$screens = wc_admin_get_embed_enabled_screen_ids ();
2018-06-26 14:49:42 +00:00
if ( in_array ( $screen_id , $screens ) ) {
return true ;
}
return false ;
}
2018-04-17 23:51:48 +00:00
/**
2018-08-20 21:24:17 +00:00
* Add a single page to a given parent top - level - item .
*
* @ param array $options {
* Array describing the menu item .
*
* @ type string $title Menu title
* @ type string $parent Parent path or menu ID
* @ type string $path Path for this page , full path in app context ; ex / analytics / report
* }
2018-04-17 23:51:48 +00:00
*/
2018-08-20 21:24:17 +00:00
function wc_admin_register_page ( $options ) {
$defaults = array (
'parent' => '/analytics' ,
);
$options = wp_parse_args ( $options , $defaults );
add_submenu_page (
'/' === $options [ 'parent' ][ 0 ] ? " wc-admin# { $options [ 'parent' ] } " : $options [ 'parent' ],
$options [ 'title' ],
$options [ 'title' ],
'manage_options' ,
" wc-admin# { $options [ 'path' ] } " ,
'wc_admin_page'
);
}
/**
* Register menu pages for the Dashboard and Analytics sections .
*/
function wc_admin_register_pages () {
2018-05-22 19:59:32 +00:00
global $menu , $submenu ;
2019-02-12 20:02:02 +00:00
if ( wc_admin_is_feature_enabled ( 'dashboard' ) ) {
add_submenu_page (
'woocommerce' ,
__ ( 'WooCommerce Dashboard' , 'wc-admin' ),
__ ( 'Dashboard' , 'wc-admin' ),
'manage_options' ,
'wc-admin' ,
'wc_admin_page'
);
}
2018-05-15 15:06:15 +00:00
2019-02-12 20:02:02 +00:00
if ( wc_admin_is_feature_enabled ( 'analytics' ) ) {
add_menu_page (
__ ( 'WooCommerce Analytics' , 'wc-admin' ),
__ ( 'Analytics' , 'wc-admin' ),
'manage_options' ,
'wc-admin#/analytics/revenue' ,
'wc_admin_page' ,
'dashicons-chart-bar' ,
56 // After WooCommerce & Product menu items.
);
2018-07-12 01:43:33 +00:00
2019-02-12 20:02:02 +00:00
wc_admin_register_page (
array (
'title' => __ ( 'Revenue' , 'wc-admin' ),
'parent' => '/analytics/revenue' ,
'path' => '/analytics/revenue' ,
)
);
2018-08-20 21:24:17 +00:00
2019-02-12 20:02:02 +00:00
wc_admin_register_page (
array (
'title' => __ ( 'Orders' , 'wc-admin' ),
'parent' => '/analytics/revenue' ,
'path' => '/analytics/orders' ,
)
);
2018-09-17 02:26:34 +00:00
2019-02-12 20:02:02 +00:00
wc_admin_register_page (
array (
'title' => __ ( 'Products' , 'wc-admin' ),
'parent' => '/analytics/revenue' ,
'path' => '/analytics/products' ,
)
);
2018-09-24 15:36:35 +00:00
2019-02-12 20:02:02 +00:00
wc_admin_register_page (
array (
'title' => __ ( 'Categories' , 'wc-admin' ),
'parent' => '/analytics/revenue' ,
'path' => '/analytics/categories' ,
)
);
2018-11-14 21:04:59 +00:00
2019-02-12 20:02:02 +00:00
wc_admin_register_page (
array (
'title' => __ ( 'Coupons' , 'wc-admin' ),
'parent' => '/analytics/revenue' ,
'path' => '/analytics/coupons' ,
)
);
2018-11-16 13:39:29 +00:00
2019-02-12 20:02:02 +00:00
wc_admin_register_page (
array (
'title' => __ ( 'Taxes' , 'wc-admin' ),
'parent' => '/analytics/revenue' ,
'path' => '/analytics/taxes' ,
)
);
2018-11-16 13:33:58 +00:00
2019-02-12 20:02:02 +00:00
wc_admin_register_page (
array (
'title' => __ ( 'Downloads' , 'wc-admin' ),
'parent' => '/analytics/revenue' ,
'path' => '/analytics/downloads' ,
)
);
2018-12-17 20:50:45 +00:00
2019-02-12 20:02:02 +00:00
wc_admin_register_page (
array (
'title' => __ ( 'Stock' , 'wc-admin' ),
'parent' => '/analytics/revenue' ,
'path' => '/analytics/stock' ,
)
);
2018-12-14 23:58:08 +00:00
2019-02-12 20:02:02 +00:00
wc_admin_register_page (
array (
'title' => __ ( 'Customers' , 'wc-admin' ),
'parent' => '/analytics/revenue' ,
'path' => '/analytics/customers' ,
)
);
2018-12-06 22:21:46 +00:00
2019-02-12 20:02:02 +00:00
wc_admin_register_page (
array (
'title' => __ ( 'Settings' , 'wc-admin' ),
'parent' => '/analytics/revenue' ,
'path' => '/analytics/settings' ,
)
);
}
2019-01-31 01:04:11 +00:00
2019-02-12 20:02:02 +00:00
if ( wc_admin_is_feature_enabled ( 'devdocs' ) && defined ( 'WP_DEBUG' ) && WP_DEBUG && defined ( 'SCRIPT_DEBUG' ) && SCRIPT_DEBUG ) {
2018-10-22 16:20:14 +00:00
wc_admin_register_page (
array (
'title' => 'DevDocs' ,
'parent' => 'woocommerce' , // Exposed on the main menu for now.
'path' => '/devdocs' ,
)
);
2018-09-24 15:36:35 +00:00
}
2018-04-17 23:51:48 +00:00
}
2018-07-10 12:48:06 +00:00
add_action ( 'admin_menu' , 'wc_admin_register_pages' );
2018-04-17 23:51:48 +00:00
2018-05-22 19:59:32 +00:00
/**
* This method is temporary while this is a feature plugin . As a part of core ,
* we can integrate this better with wc - admin - menus .
*
* It makes dashboard the top level link for 'WooCommerce' and renames the first Analytics menu item .
*/
2018-07-10 12:48:06 +00:00
function wc_admin_link_structure () {
2018-05-22 19:59:32 +00:00
global $submenu ;
2018-08-20 21:24:17 +00:00
// User does not have capabilites to see the submenu.
2018-06-08 17:11:24 +00:00
if ( ! current_user_can ( 'manage_woocommerce' ) ) {
return ;
}
2018-05-22 19:59:32 +00:00
2018-07-10 12:48:06 +00:00
$wc_admin_key = null ;
2018-05-22 19:59:32 +00:00
foreach ( $submenu [ 'woocommerce' ] as $submenu_key => $submenu_item ) {
2018-07-10 12:48:06 +00:00
if ( 'wc-admin' === $submenu_item [ 2 ] ) {
$wc_admin_key = $submenu_key ;
2018-05-22 19:59:32 +00:00
break ;
}
}
2018-07-10 12:48:06 +00:00
if ( ! $wc_admin_key ) {
2018-05-22 19:59:32 +00:00
return ;
}
2018-08-20 21:24:17 +00:00
$menu = $submenu [ 'woocommerce' ][ $wc_admin_key ];
2018-05-22 19:59:32 +00:00
2018-08-20 21:24:17 +00:00
// Move menu item to top of array.
unset ( $submenu [ 'woocommerce' ][ $wc_admin_key ] );
2018-07-10 12:48:06 +00:00
array_unshift ( $submenu [ 'woocommerce' ], $menu );
2018-05-22 19:59:32 +00:00
}
2018-08-20 21:24:17 +00:00
// priority is 20 to run after https://github.com/woocommerce/woocommerce/blob/a55ae325306fc2179149ba9b97e66f32f84fdd9c/includes/admin/class-wc-admin-menus.php#L165.
2018-07-10 12:48:06 +00:00
add_action ( 'admin_head' , 'wc_admin_link_structure' , 20 );
2018-05-22 19:59:32 +00:00
2018-04-17 23:51:48 +00:00
/**
2018-07-10 12:48:06 +00:00
* Load the assets on the admin pages
2018-04-17 23:51:48 +00:00
*/
2018-08-20 21:24:17 +00:00
function wc_admin_enqueue_script () {
2018-07-10 12:48:06 +00:00
if ( ! wc_admin_is_admin_page () && ! wc_admin_is_embed_enabled_wc_page () ) {
2018-04-17 23:51:48 +00:00
return ;
}
2018-07-10 12:48:06 +00:00
wp_enqueue_script ( WC_ADMIN_APP );
wp_enqueue_style ( WC_ADMIN_APP );
2018-12-28 17:58:03 +00:00
// Use server-side detection to prevent unneccessary stylesheet loading in other browsers.
$user_agent = isset ( $_SERVER [ 'HTTP_USER_AGENT' ] ) ? $_SERVER [ 'HTTP_USER_AGENT' ] : '' ; // WPCS: sanitization ok.
preg_match ( '/MSIE (.*?);/' , $user_agent , $matches );
if ( count ( $matches ) < 2 ) {
preg_match ( '/Trident\/\d{1,2}.\d{1,2}; rv:([0-9]*)/' , $user_agent , $matches );
}
if ( count ( $matches ) > 1 ) {
wp_enqueue_style ( 'wc-components-ie' );
}
2018-04-17 23:51:48 +00:00
}
2018-07-10 12:48:06 +00:00
add_action ( 'admin_enqueue_scripts' , 'wc_admin_enqueue_script' );
2018-04-17 23:51:48 +00:00
2018-10-23 15:52:18 +00:00
/**
2019-02-12 20:02:02 +00:00
* Adds body classes to the main wp - admin wrapper , allowing us to better target elements in specific scenarios .
2018-10-23 15:52:18 +00:00
*
* @ param string $admin_body_class Body class to add .
*/
2018-07-10 12:48:06 +00:00
function wc_admin_admin_body_class ( $admin_body_class = '' ) {
2018-05-10 18:35:55 +00:00
global $hook_suffix ;
2018-07-10 12:48:06 +00:00
if ( ! wc_admin_is_admin_page () && ! wc_admin_is_embed_enabled_wc_page () ) {
2018-05-10 18:35:55 +00:00
return $admin_body_class ;
}
2018-10-22 16:20:14 +00:00
$classes = explode ( ' ' , trim ( $admin_body_class ) );
2018-05-10 18:35:55 +00:00
$classes [] = 'woocommerce-page' ;
2018-07-10 12:48:06 +00:00
if ( wc_admin_is_embed_enabled_wc_page () ) {
2018-06-26 14:49:42 +00:00
$classes [] = 'woocommerce-embed-page' ;
}
2019-02-12 20:02:02 +00:00
if ( function_exists ( 'wc_admin_get_feature_config' ) ) {
$features = wc_admin_get_feature_config ();
foreach ( $features as $feature_key => $bool ) {
if ( true === $bool ) {
$classes [] = sanitize_html_class ( 'woocommerce-feature-enabled-' . $feature_key );
} else {
$classes [] = sanitize_html_class ( 'woocommerce-feature-disabled-' . $feature_key );
}
}
}
2018-05-10 18:35:55 +00:00
$admin_body_class = implode ( ' ' , array_unique ( $classes ) );
return " $admin_body_class " ;
}
2018-07-10 12:48:06 +00:00
add_filter ( 'admin_body_class' , 'wc_admin_admin_body_class' );
2018-05-10 18:35:55 +00:00
2019-02-21 18:37:45 +00:00
/**
* Removes notices that should not be displayed on WC Admin pages .
*/
function wc_admin_remove_notices () {
if ( ! wc_admin_is_admin_page () && ! wc_admin_is_embed_enabled_wc_page () ) {
return ;
}
// Hello Dolly.
if ( function_exists ( 'hello_dolly' ) ) {
remove_action ( 'admin_notices' , 'hello_dolly' );
}
}
add_action ( 'admin_head' , 'wc_admin_remove_notices' );
2018-10-23 15:52:18 +00:00
/**
* Runs before admin notices action and hides them .
*/
2018-07-10 12:48:06 +00:00
function wc_admin_admin_before_notices () {
2019-02-12 20:02:02 +00:00
if ( ( ! wc_admin_is_admin_page () && ! wc_admin_is_embed_enabled_wc_page () ) || ! wc_admin_is_feature_enabled ( 'activity-panels' ) ) {
2018-05-11 17:07:53 +00:00
return ;
}
2018-06-26 14:49:42 +00:00
echo '<div class="woocommerce-layout__notice-list-hide" id="wp__notice-list">' ;
2018-10-23 15:52:18 +00:00
echo '<div class="wp-header-end" id="woocommerce-layout__notice-catcher"></div>' ; // https://github.com/WordPress/WordPress/blob/f6a37e7d39e2534d05b9e542045174498edfe536/wp-admin/js/common.js#L737.
2018-05-11 17:07:53 +00:00
}
2018-07-10 12:48:06 +00:00
add_action ( 'admin_notices' , 'wc_admin_admin_before_notices' , 0 );
2018-05-11 17:07:53 +00:00
2018-10-23 15:52:18 +00:00
/**
* Runs after admin notices and closes div .
*/
2018-07-10 12:48:06 +00:00
function wc_admin_admin_after_notices () {
2019-02-12 20:02:02 +00:00
if ( ( ! wc_admin_is_admin_page () && ! wc_admin_is_embed_enabled_wc_page () ) || ! wc_admin_is_feature_enabled ( 'activity-panels' ) ) {
2018-05-11 17:07:53 +00:00
return ;
}
echo '</div>' ;
}
2018-07-10 12:48:06 +00:00
add_action ( 'admin_notices' , 'wc_admin_admin_after_notices' , PHP_INT_MAX );
2018-05-11 17:07:53 +00:00
2018-10-23 15:52:18 +00:00
/**
2018-10-23 17:54:20 +00:00
* Edits Admin title based on section of wc - admin .
*
2018-10-23 15:52:18 +00:00
* @ param string $admin_title Modifies admin title .
2019-02-06 06:41:53 +00:00
* @ todo Can we do some URL rewriting so we can figure out which page they are on server side ?
2018-10-23 15:52:18 +00:00
*/
2018-07-10 12:48:06 +00:00
function wc_admin_admin_title ( $admin_title ) {
if ( ! wc_admin_is_admin_page () && ! wc_admin_is_embed_enabled_wc_page () ) {
2018-05-24 16:03:03 +00:00
return $admin_title ;
}
2018-06-26 14:49:42 +00:00
2018-07-10 12:48:06 +00:00
if ( wc_admin_is_embed_enabled_wc_page () ) {
$sections = wc_admin_get_embed_breadcrumbs ();
2018-06-26 14:49:42 +00:00
$sections = is_array ( $sections ) ? $sections : array ( $sections );
$pieces = array ();
foreach ( $sections as $section ) {
2018-10-22 16:20:14 +00:00
$pieces [] = is_array ( $section ) ? $section [ 1 ] : $section ;
2018-06-26 14:49:42 +00:00
}
$pieces = array_reverse ( $pieces );
2018-10-22 16:20:14 +00:00
$title = implode ( ' ‹ ' , $pieces );
2018-06-26 14:49:42 +00:00
} else {
2018-07-10 12:48:06 +00:00
$title = __ ( 'Dashboard' , 'wc-admin' );
2018-06-26 14:49:42 +00:00
}
2018-10-23 15:52:18 +00:00
/* translators: %1$s: updated title, %2$s: blog info name */
2018-07-10 12:48:06 +00:00
return sprintf ( __ ( '%1$s ‹ %2$s — WooCommerce' , 'wc-admin' ), $title , get_bloginfo ( 'name' ) );
2018-05-24 16:03:03 +00:00
}
2018-10-22 16:20:14 +00:00
add_filter ( 'admin_title' , 'wc_admin_admin_title' );
2018-05-24 16:03:03 +00:00
2018-04-17 23:51:48 +00:00
/**
* Set up a div for the app to render into .
*/
2018-10-22 16:20:14 +00:00
function wc_admin_page () {
2018-04-17 23:51:48 +00:00
?>
< div class = " wrap " >
< div id = " root " ></ div >
</ div >
2018-10-22 16:20:14 +00:00
< ? php
2018-04-17 23:51:48 +00:00
}
2018-06-26 14:49:42 +00:00
2018-10-23 15:52:18 +00:00
/**
* Outputs a breadcrumb
*
* @ param array $section Section to create breadcrumb from .
*/
function wc_admin_output_breadcrumb ( $section ) {
?>
< span >
< ? php if ( is_array ( $section ) ) : ?>
< a href = " <?php echo esc_url( admin_url( $section[0] ) ); ?> " >
< ? php echo esc_html ( $section [ 1 ] ); ?>
</ a >
< ? php else : ?>
< ? php echo esc_html ( $section ); ?>
< ? php endif ; ?>
</ span >
< ? php
}
2018-06-26 14:49:42 +00:00
/**
* Set up a div for the header embed to render into .
* The initial contents here are meant as a place loader for when the PHP page initialy loads .
2019-02-06 06:41:53 +00:00
*
* @ todo Icon Placeholders for the ActivityPanel , when we implement the new designs .
2018-06-26 14:49:42 +00:00
*/
function woocommerce_embed_page_header () {
2018-07-10 12:48:06 +00:00
if ( ! wc_admin_is_embed_enabled_wc_page () ) {
2018-06-26 14:49:42 +00:00
return ;
}
2018-10-23 15:52:18 +00:00
$sections = wc_admin_get_embed_breadcrumbs ();
$sections = is_array ( $sections ) ? $sections : array ( $sections );
2018-06-26 14:49:42 +00:00
?>
< div id = " woocommerce-embedded-root " >
2018-06-28 13:52:45 +00:00
< div class = " woocommerce-layout " >
2018-06-29 15:20:08 +00:00
< div class = " woocommerce-layout__header is-embed-loading " >
2018-06-28 13:52:45 +00:00
< h1 class = " woocommerce-layout__header-breadcrumbs " >
2018-07-10 12:48:06 +00:00
< span >< a href = " <?php echo esc_url( admin_url( 'admin.php?page=wc-admin#/' ) ); ?> " > WooCommerce </ a ></ span >
2018-10-23 15:52:18 +00:00
< ? php foreach ( $sections as $section ) : ?>
< ? php wc_admin_output_breadcrumb ( $section ); ?>
< ? php endforeach ; ?>
2018-06-26 14:49:42 +00:00
</ h1 >
</ div >
</ div >
2018-06-29 15:20:08 +00:00
< div class = " woocommerce-layout__primary is-embed-loading " id = " woocommerce-layout__primary " >
2018-06-26 14:49:42 +00:00
< div id = " woocommerce-layout__notice-list " class = " woocommerce-layout__notice-list " ></ div >
</ div >
</ div >
< ? php
}
add_action ( 'in_admin_header' , 'woocommerce_embed_page_header' );
2018-12-13 19:24:54 +00:00
/**
* Registers WooCommerce specific user data to the WordPress user API .
*/
function wc_admin_register_user_data () {
register_rest_field (
'user' ,
'woocommerce_meta' ,
array (
'get_callback' => 'wc_admin_get_user_data_values' ,
'update_callback' => 'wc_admin_update_user_data_values' ,
'schema' => null ,
)
);
}
add_action ( 'rest_api_init' , 'wc_admin_register_user_data' );
/**
* We store some WooCommerce specific user meta attached to users endpoint ,
* so that we can track certain preferences or values such as the inbox activity panel last open time .
* Additional fields can be added in the function below , and then used via wc - admin ' s currentUser data .
*
* @ return array Fields to expose over the WP user endpoint .
*/
function wc_admin_get_user_data_fields () {
$user_data_fields = array (
2018-12-13 20:34:23 +00:00
'categories_report_columns' ,
'coupons_report_columns' ,
'customers_report_columns' ,
'orders_report_columns' ,
'products_report_columns' ,
2018-12-13 19:24:54 +00:00
'revenue_report_columns' ,
2018-12-13 20:34:23 +00:00
'taxes_report_columns' ,
'variations_report_columns' ,
2019-01-17 14:08:59 +00:00
'dashboard_performance_indicators' ,
2019-01-08 01:49:11 +00:00
'dashboard_charts' ,
'dashboard_chart_type' ,
2019-01-09 00:12:39 +00:00
'dashboard_chart_interval' ,
2019-01-08 07:20:01 +00:00
'dashboard_leaderboards' ,
'dashboard_leaderboard_rows' ,
2018-12-13 19:24:54 +00:00
);
return apply_filters ( 'wc_admin_get_user_data_fields' , $user_data_fields );
}
/**
* For all the registered user data fields ( wc_admin_get_user_data_fields ), fetch the data
* for returning via the REST API .
*
* @ param WP_User $user Current user .
*/
function wc_admin_get_user_data_values ( $user ) {
$values = array ();
foreach ( wc_admin_get_user_data_fields () as $field ) {
$values [ $field ] = get_user_meta ( $user [ 'id' ], 'wc_admin_' . $field , true );
}
return $values ;
}
/**
* For all the registered user data fields ( wc_admin_get_user_data_fields ), update the data
* for the REST API .
*
* @ param array $values The new values for the meta .
* @ param WP_User $user The current user .
* @ param string $field_id The field id for the user meta .
*/
function wc_admin_update_user_data_values ( $values , $user , $field_id ) {
if ( empty ( $values ) || ! is_array ( $values ) || 'woocommerce_meta' !== $field_id ) {
return ;
}
$fields = wc_admin_get_user_data_fields ();
$updates = array ();
foreach ( $values as $field => $value ) {
if ( in_array ( $field , $fields , true ) ) {
$updates [ $field ] = $value ;
update_user_meta ( $user -> ID , 'wc_admin_' . $field , $value );
}
}
return $updates ;
}
2019-01-31 01:04:11 +00:00
/**
* Register the admin settings for use in the WC REST API
*
* @ param array $groups Array of setting groups .
* @ return array
*/
function wc_admin_add_settings_group ( $groups ) {
$groups [] = array (
'id' => 'wc_admin' ,
'label' => __ ( 'WooCommerce Admin' , 'wc-admin' ),
'description' => __ ( 'Settings for WooCommerce admin reporting.' , 'wc-admin' ),
);
return $groups ;
}
add_filter ( 'woocommerce_settings_groups' , 'wc_admin_add_settings_group' );
/**
* Add WC Admin specific settings
*
* @ param array $settings Array of settings in wc admin group .
* @ return array
*/
function wc_admin_add_settings ( $settings ) {
$settings [] = array (
'id' => 'woocommerce_excluded_report_order_statuses' ,
'option_key' => 'woocommerce_excluded_report_order_statuses' ,
'label' => __ ( 'Excluded report order statuses' , 'wc-admin' ),
'description' => __ ( 'Statuses that should not be included when calculating report totals.' , 'wc-admin' ),
2019-03-06 05:14:38 +00:00
'default' => array ( 'pending' , 'cancelled' , 'failed' ),
'type' => 'multiselect' ,
'options' => format_order_statuses ( wc_get_order_statuses () ),
);
$settings [] = array (
'id' => 'woocommerce_actionable_order_statuses' ,
'option_key' => 'woocommerce_actionable_order_statuses' ,
'label' => __ ( 'Actionable order statuses' , 'wc-admin' ),
'description' => __ ( 'Statuses that require extra action on behalf of the store admin.' , 'wc-admin' ),
'default' => array ( 'processing' , 'on-hold' ),
2019-01-31 01:04:11 +00:00
'type' => 'multiselect' ,
'options' => format_order_statuses ( wc_get_order_statuses () ),
);
return $settings ;
};
add_filter ( 'woocommerce_settings-wc_admin' , 'wc_admin_add_settings' );