Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 17 additions & 1 deletion includes/admin/beta-features.php
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,13 @@ class SCF_Admin_Beta_Features {
*/
private $beta_features = array();

/**
* Whether the beta feature classes have been included.
*
* @var bool
*/
private $included = false;

/**
* This function will setup the class functionality
*
Expand Down Expand Up @@ -64,6 +71,9 @@ public function register_beta_feature( $beta_feature ) {
* @return mixed (SCF_Admin_Beta_Feature|null)
*/
public function get_beta_feature( $name ) {
// Include beta features.
$this->include_beta_features();

return isset( $this->beta_features[ $name ] ) ? $this->beta_features[ $name ] : null;
}

Expand Down Expand Up @@ -137,8 +147,13 @@ public function admin_body_class( $classes ) {
* @return void
*/
private function include_beta_features() {
if ( $this->included ) {
return;
}
$this->included = true;

acf_include( 'includes/admin/beta-features/class-scf-beta-feature.php' );
acf_include( 'includes/admin/beta-features/class-scf-beta-feature-connect-fields.php' );
acf_include( 'includes/admin/beta-features/class-scf-beta-feature-editor-sidebar.php' );

add_action( 'scf/include_admin_beta_features', array( $this, 'register_beta_features' ) );

Expand All @@ -153,6 +168,7 @@ private function include_beta_features() {
* @return void
*/
public function register_beta_features() {
$this->register_beta_feature( 'SCF_Admin_Beta_Feature_Editor_Sidebar' );
}

/**
Expand Down
23 changes: 21 additions & 2 deletions includes/ajax/class-acf-ajax-check-screen.php
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,12 @@ public function get_response( $request ) {
return new WP_Error( 'acf_invalid_permissions', __( 'Sorry, you do not have permission to do that.', 'secure-custom-fields' ) );
}

$post_type = $this->get( 'post_type' );

if ( ! $post_type && 'post' === $args['screen'] ) {
$post_type = get_post_type( (int) $args['post_id'] );
}

$response = array(
'results' => array(),
'style' => '',
Expand All @@ -45,6 +51,9 @@ public function get_response( $request ) {
// get field groups
$field_groups = acf_get_field_groups( $args );

// Meta box IDs moved into the editor sidebar by a beta feature.
$relocated = array();

// loop through field groups
if ( $field_groups ) {
foreach ( $field_groups as $i => $field_group ) {
Expand All @@ -54,14 +63,18 @@ public function get_response( $request ) {
'id' => esc_attr( 'acf-' . $field_group['key'] ),
'key' => esc_attr( $field_group['key'] ),
'title' => acf_esc_html( acf_get_field_group_title( $field_group ) ),
'position' => esc_attr( $field_group['position'] ),
'position' => esc_attr( scf_get_field_group_meta_box_position( $post_type, $field_group['position'] ) ),
'classes' => postbox_classes( 'acf-' . $field_group['key'], $args['screen'] ),
'style' => esc_attr( $field_group['style'] ),
'label' => esc_attr( $field_group['label_placement'] ),
'edit' => esc_url( acf_get_field_group_edit_link( $field_group['ID'] ) ),
'html' => '',
);

if ( $item['position'] !== $field_group['position'] ) {
$relocated[] = $item['id'];
}

$hidden_metaboxes = get_hidden_meta_boxes( $args['screen'] );

if ( is_array( $hidden_metaboxes ) && in_array( $item['id'], $hidden_metaboxes ) ) {
Expand Down Expand Up @@ -95,7 +108,13 @@ public function get_response( $request ) {

// Custom metabox order.
if ( $this->get( 'screen' ) == 'post' ) {
$response['sorted'] = get_user_option( 'meta-box-order_' . $this->get( 'post_type' ) );
$sorted = get_user_option( 'meta-box-order_' . $post_type );

if ( $relocated && is_array( $sorted ) ) {
$sorted = scf_move_meta_box_ids_to_sidebar( $sorted, $relocated );
}

$response['sorted'] = $sorted;
}

/**
Expand Down
101 changes: 101 additions & 0 deletions includes/api/api-helpers.php
Original file line number Diff line number Diff line change
Expand Up @@ -4146,6 +4146,107 @@ function acf_is_block_editor() {
return false;
}

/**
* Returns true when the "Move Elements to Editor Sidebar" beta feature is
* enabled and the given post type is edited with the block editor.
*
* The beta feature registry only loads on admin screens, so this is always
* false outside of them, and post types using the classic editor are never
* affected.
*
* @param string $post_type The post type being edited.
* @return boolean
*/
function scf_field_groups_use_editor_sidebar( $post_type ) {
if ( ! is_string( $post_type ) || '' === $post_type ) {
return false;
}

if ( ! function_exists( 'use_block_editor_for_post_type' ) || ! use_block_editor_for_post_type( $post_type ) ) {
return false;
}

$acf = acf();

if ( ! isset( $acf->admin_beta_features ) ) {
return false;
}

$feature = $acf->admin_beta_features->get_beta_feature( 'editor_sidebar' );

return $feature && $feature->is_enabled();
}

/**
* Returns the meta box position a field group should render in.
*
* Field groups keep the position saved on them unless the editor sidebar beta
* feature moves them into the block editor sidebar.
*
* @param string $post_type The post type being edited.
* @param string $position The position saved on the field group.
* @return string
*/
function scf_get_field_group_meta_box_position( $post_type, $position ) {
if ( 'side' === $position || ! scf_field_groups_use_editor_sidebar( $post_type ) ) {
return $position;
}

return 'side';
}

/**
* Moves meta boxes into the sidebar within a saved meta box order.
*
* WordPress rebuilds the meta box registry from the order a user saved for the
* screen, and that order still lists field groups under the position saved on
* them. Without this the saved order would pull a field group back out of the
* editor sidebar.
*
* @param array $meta_box_order The saved order, a comma separated list of IDs per location.
* @param array $ids The meta box IDs to move.
* @return array
*/
function scf_move_meta_box_ids_to_sidebar( $meta_box_order, $ids ) {
if ( ! is_array( $meta_box_order ) || empty( $ids ) ) {
return $meta_box_order;
}

$sidebar = array();

foreach ( array( 'side', 'acf_after_title', 'normal', 'advanced' ) as $location ) {
if ( empty( $meta_box_order[ $location ] ) || ! is_string( $meta_box_order[ $location ] ) ) {
continue;
}

$remaining = array();

foreach ( explode( ',', $meta_box_order[ $location ] ) as $id ) {
$id = trim( $id );

if ( '' === $id ) {
continue;
}

if ( 'side' === $location ) {
$sidebar[] = $id;
} elseif ( in_array( $id, $ids, true ) ) {
$sidebar[] = $id;
} else {
$remaining[] = $id;
}
}

if ( 'side' !== $location ) {
$meta_box_order[ $location ] = implode( ',', $remaining );
}
}

$meta_box_order['side'] = implode( ',', array_values( array_unique( $sidebar ) ) );

return $meta_box_order;
}

/**
* Return an array of the WordPress reserved terms
*
Expand Down
39 changes: 38 additions & 1 deletion includes/forms/form-post.php
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,13 @@ class ACF_Form_Post {
*/
public $style = '';

/**
* Meta box IDs moved into the editor sidebar by a beta feature.
*
* @var array
*/
private $sidebar_meta_box_ids = array();

/**
* __construct
*
Expand Down Expand Up @@ -129,6 +136,12 @@ public function add_meta_boxes( $post_type, $post ) {
// Storage for localized postboxes.
$postboxes = array();

// Storage for postboxes moved to the editor sidebar by a beta feature.
$this->sidebar_meta_box_ids = array();

// Whether field groups are rendered in the editor sidebar rather than below the content.
$use_sidebar = scf_field_groups_use_editor_sidebar( $post_type );

// Get field groups for this screen.
$field_groups = acf_get_field_groups(
array(
Expand All @@ -146,7 +159,7 @@ public function add_meta_boxes( $post_type, $post ) {
}

$id = esc_attr( "acf-{$field_group['key']}" );
$context = esc_attr( $field_group['position'] );
$context = esc_attr( scf_get_field_group_meta_box_position( $post_type, $field_group['position'] ) );
$priority = 'high';

// Reduce priority for sidebar metaboxes for best position.
Expand Down Expand Up @@ -174,6 +187,10 @@ public function add_meta_boxes( $post_type, $post ) {
'edit' => esc_url( acf_get_field_group_edit_link( $field_group['ID'] ) ),
);

if ( $use_sidebar ) {
$this->sidebar_meta_box_ids[] = $id;
}

// Add the meta box.
add_meta_box(
$id,
Expand All @@ -186,6 +203,11 @@ public function add_meta_boxes( $post_type, $post ) {
);
}

// Keep the order saved for this screen from moving the boxes back out of the sidebar.
if ( $this->sidebar_meta_box_ids ) {
add_filter( 'get_user_option_meta-box-order_' . $post_type, array( $this, 'modify_user_option_meta_box_order' ) );
}

// Set style from first field group.
$this->style = acf_get_field_group_style( $field_groups[0] );

Expand Down Expand Up @@ -218,6 +240,21 @@ public function add_meta_boxes( $post_type, $post ) {
do_action( 'acf/add_meta_boxes', $post_type, $post, $field_groups );
}

/**
* Keeps field groups registered in the sidebar inside the sidebar.
*
* WordPress rebuilds the meta box registry from the order saved for the
* screen, and that order still lists field groups under the position saved
* on them. Without this the saved order would move them back below the
* content.
*
* @param array $locations The meta box order saved for this screen.
* @return array
*/
public function modify_user_option_meta_box_order( $locations ) {
return scf_move_meta_box_ids_to_sidebar( $locations, $this->sidebar_meta_box_ids );
}

/**
* Called after the title and before the content editor to render the after title metaboxes.
* Also renders the CSS required to hide the "hide-on-screen" elements on the page based on the field group settings.
Expand Down
25 changes: 14 additions & 11 deletions tests/e2e/fixtures.js
Original file line number Diff line number Diff line change
Expand Up @@ -144,22 +144,25 @@ const test = wpTest.extend( {
'role=button[name="View"i]'
);

if (
const hasViewButton =
( await viewButton.count() ) > 0 &&
( await viewButton.first().isVisible() )
) {
return editor.openPreviewPage();
}
( await viewButton.first().isVisible() );

await editorTopBar
.locator( 'role=button[name="Preview"i]' )
.click();
await ( hasViewButton
? viewButton.first()
: editorTopBar.locator( 'role=button[name="Preview"i]' )
).click();

// WordPress trunk renamed the menu item to
// "Preview (opens in a new tab)", so match on the shared
// "Preview ... new tab" text instead of the exact label.
const [ previewPage ] = await Promise.all( [
context.waitForEvent( 'page' ),
page.click(
'role=menuitem[name=/Preview in new tab/i]'
),
page
.getByRole( 'menuitem', {
name: /Preview.*new tab/i,
} )
.click(),
] );

return previewPage;
Expand Down
Loading
Loading