Menus, saved as item meta. */
final class MenuFields {
public function register(): void {
add_action( 'wp_nav_menu_item_custom_fields', array( $this, 'fields' ), 10, 2 );
add_action( 'wp_update_nav_menu_item', array( $this, 'save' ), 10, 2 );
add_action( 'admin_enqueue_scripts', array( self::class, 'assets' ) );
}
public function fields( int $item_id, $item ): void {
$icon = (string) get_post_meta( $item_id, '_dashbread_icon', true );
$roles = array_filter( (array) get_post_meta( $item_id, '_dashbread_roles', true ) );
echo '
' . esc_html__( 'Dashbread icon', 'dashbread' ) . '
' . wp_kses( Icons::picker( 'dashbread_icon[' . $item_id . ']', $icon ), \Dashbread\Core\Kses::ui() );
echo '' . esc_html__( 'Dashbread: visible to roles (none = everyone)', 'dashbread' ) . '
';
foreach ( wp_roles()->get_names() as $slug => $label ) {
echo '';
}
echo '
';
}
public static function assets( string $hook ): void {
if ( in_array( $hook, array( 'nav-menus.php', 'post.php', 'post-new.php' ), true ) ) {
Icons::enqueue_picker();
}
}
public function save( int $menu_id, int $item_id ): void {
if ( ! current_user_can( 'edit_theme_options' ) ) {
return;
}
// Only the Appearance > Menus form carries these fields: check its nonce here before reading
// them. Menu items saved any other way (Customizer, REST, code) keep their Dashbread settings.
if ( ! isset( $_POST['update-nav-menu-nonce'] ) || ! wp_verify_nonce( sanitize_text_field( wp_unslash( $_POST['update-nav-menu-nonce'] ) ), 'update-nav_menu' ) ) {
return;
}
$icon = isset( $_POST['dashbread_icon'][ $item_id ] ) ? sanitize_key( wp_unslash( $_POST['dashbread_icon'][ $item_id ] ) ) : '';
update_post_meta( $item_id, '_dashbread_icon', $icon );
$roles = isset( $_POST['dashbread_roles'][ $item_id ] ) ? array_map( 'sanitize_key', (array) wp_unslash( $_POST['dashbread_roles'][ $item_id ] ) ) : array();
update_post_meta( $item_id, '_dashbread_roles', $roles );
}
}