Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add block-based widget editor #603

Closed
wants to merge 7 commits into from
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
385 changes: 375 additions & 10 deletions package-lock.json

Large diffs are not rendered by default.

5 changes: 3 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -86,10 +86,10 @@
"@wordpress/blob": "2.10.0",
"@wordpress/block-directory": "1.16.1",
"@wordpress/block-editor": "5.0.1",
"@wordpress/block-library": "2.25.1",
"@wordpress/block-library": "2.25.3",
"@wordpress/block-serialization-default-parser": "3.8.0",
"@wordpress/blocks": "6.23.0",
"@wordpress/components": "11.0.0",
"@wordpress/components": "11.0.1",
"@wordpress/compose": "3.21.0",
"@wordpress/core-data": "2.23.0",
"@wordpress/data": "4.24.0",
Expand All @@ -99,6 +99,7 @@
"@wordpress/dom": "2.15.0",
"@wordpress/dom-ready": "2.11.0",
"@wordpress/edit-post": "3.24.1",
"@wordpress/edit-widgets": "1.0.2",
"@wordpress/editor": "9.23.1",
"@wordpress/element": "2.18.0",
"@wordpress/escape-html": "1.10.0",
Expand Down
16 changes: 16 additions & 0 deletions src/js/_enqueues/wp/customize/widgets.js
Original file line number Diff line number Diff line change
Expand Up @@ -566,6 +566,7 @@
control._setupHighlightEffects();
control._setupUpdateUI();
control._setupRemoveUI();
control._setupEditUI();
},

/**
Expand Down Expand Up @@ -1032,6 +1033,21 @@
}
},

/**
* Add a Edit button to block widgets.
*/
_setupEditUI: function() {
if ( 'block' === this.params.widget_id_base ) {
this.container.find( '.widget-control-remove' ).before(
$( '<a>' )
.attr( 'class', 'button-link' )
.attr( 'href', 'widgets.php' )
.text( l10n.editBtnLabel ),
' | '
);
}
},

/**
* Find all inputs in a widget container that should be considered when
* comparing the loaded form with the sanitized form, whose fields will
Expand Down
6 changes: 5 additions & 1 deletion src/wp-admin/admin-header.php
Original file line number Diff line number Diff line change
Expand Up @@ -190,8 +190,12 @@
$admin_body_class .= ' no-customize-support no-svg';

if ( $current_screen->is_block_editor() ) {
$admin_body_class .= ' block-editor-page wp-embed-responsive';

// Default to is-fullscreen-mode to avoid jumps in the UI.
$admin_body_class .= ' block-editor-page is-fullscreen-mode wp-embed-responsive';
if ( 'widgets' !== $current_screen->base ) {
$admin_body_class .= ' is-fullscreen-mode';
}

if ( current_theme_supports( 'editor-styles' ) && current_theme_supports( 'dark-editor-style' ) ) {
$admin_body_class .= ' is-dark-theme';
Expand Down
44 changes: 44 additions & 0 deletions src/wp-admin/includes/widgets.php
Original file line number Diff line number Diff line change
Expand Up @@ -325,3 +325,47 @@ function wp_widget_control( $sidebar_args ) {
function wp_widgets_access_body_class( $classes ) {
return "$classes widgets_access ";
}

/**
* Outputs a HTML page that previews a Legacy Widget block. Suitable for use in
* an iframe, which is exactly what the Legacy Widget block does when a user
* selects Preview.
*
* @since 5.6.0
* @access private
*
* @param array $widget_preview Legacy Widget block attributes to preview.
*/
function wp_legacy_widget_block_preview( $widget_preview ) {
?>
<!doctype html>
<html <?php language_attributes(); ?>>
<head>
<meta charset="<?php bloginfo( 'charset' ); ?>" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<link rel="profile" href="https://gmpg.org/xfn/11" />
<?php wp_head(); ?>
<style>
/* Reset theme styles */
html, body, #page, #content {
background: #FFF !important;
padding: 0 !important;
margin: 0 !important;
}
</style>
</head>
<body <?php body_class(); ?>>
<div id="page" class="site">
<div id="content" class="site-content">
<?php
$registry = WP_Block_Type_Registry::get_instance();
$block = $registry->get_registered( 'core/legacy-widget' );
echo $block->render( $widget_preview );
?>
</div><!-- #content -->
</div><!-- #page -->
<?php wp_footer(); ?>
</body>
</html>
<?php
}
193 changes: 193 additions & 0 deletions src/wp-admin/widgets-block-editor.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,193 @@
<?php
/**
* The block-based widgets editor, for use in widgets.php.
*
* @package WordPress
* @subpackage Administration
*/

// Don't load directly.
if ( ! defined( 'ABSPATH' ) ) {
die( '-1' );
}

/**
* @global array $wp_widget_factory
* @global array $wp_registered_widgets
*/
global $wp_widget_factory, $wp_registered_widgets;

// Handle requests made by the Legacy Block to widgets.php?widget-preview={}.
if ( isset( $_GET['widget-preview'] ) ) {
define( 'IFRAME_REQUEST', true );
wp_legacy_widget_block_preview( $_GET['widget-preview'] );
exit;
}

// Flag that we're loading the block editor.
$current_screen = get_current_screen();
$current_screen->is_block_editor( true );

$max_upload_size = wp_max_upload_size();
if ( ! $max_upload_size ) {
$max_upload_size = 0;
}

/** This filter is documented in wp-admin/includes/media.php */
$image_size_names = apply_filters(
'image_size_names_choose',
array(
'thumbnail' => __( 'Thumbnail' ),
'medium' => __( 'Medium' ),
'large' => __( 'Large' ),
'full' => __( 'Full Size' ),
)
);

$available_image_sizes = array();
foreach ( $image_size_names as $image_size_slug => $image_size_name ) {
$available_image_sizes[] = array(
'slug' => $image_size_slug,
'name' => $image_size_name,
);
}

/**
* Filters the list of widget classes that should **not** be offered by the legacy widget block.
*
* Returning an empty array will make all the widgets available.
*
* @param array $widgets An array of excluded widgets classnames.
*
* @since 5.6.0
*/
$widgets_to_exclude_from_legacy_widget_block = apply_filters(
'widgets_to_exclude_from_legacy_widget_block',
array(
'WP_Widget_Block',
'WP_Widget_Pages',
'WP_Widget_Calendar',
'WP_Widget_Archives',
'WP_Widget_Media_Audio',
'WP_Widget_Media_Image',
'WP_Widget_Media_Gallery',
'WP_Widget_Media_Video',
'WP_Widget_Meta',
'WP_Widget_Search',
'WP_Widget_Text',
'WP_Widget_Categories',
'WP_Widget_Recent_Posts',
'WP_Widget_Recent_Comments',
'WP_Widget_RSS',
'WP_Widget_Tag_Cloud',
'WP_Nav_Menu_Widget',
'WP_Widget_Custom_HTML',
)
);

$available_legacy_widgets = array();

if ( ! empty( $wp_widget_factory ) ) {
foreach ( $wp_widget_factory->widgets as $class => $widget_obj ) {
$available_legacy_widgets[ $class ] = array(
'name' => html_entity_decode( $widget_obj->name ),
'id_base' => $widget_obj->id_base,
// wp_widget_description is not being used because its input parameter is a Widget Id.
// Widgets id's reference to a specific widget instance.
// Here we are iterating on all the available widget classes even if no widget instance exists for them.
'description' => isset( $widget_obj->widget_options['description'] ) ?
html_entity_decode( $widget_obj->widget_options['description'] ) :
null,
'isReferenceWidget' => false,
'isHidden' => in_array( $class, $widgets_to_exclude_from_legacy_widget_block, true ),
);
}
}

if ( ! empty( $wp_registered_widgets ) ) {
foreach ( $wp_registered_widgets as $widget_id => $widget_obj ) {
$block_widget_start = 'blocks-widget-';
if (
( is_array( $widget_obj['callback'] ) &&
isset( $widget_obj['callback'][0] ) &&
( $widget_obj['callback'][0] instanceof WP_Widget ) ) ||
// $widget_id starts with $block_widget_start.
strncmp( $widget_id, $block_widget_start, strlen( $block_widget_start ) ) === 0
) {
continue;
}
$available_legacy_widgets[ $widget_id ] = array(
'name' => html_entity_decode( $widget_obj['name'] ),
'description' => html_entity_decode( wp_widget_description( $widget_id ) ),
'isReferenceWidget' => true,
);
}
}

$editor_settings = array(
'maxUploadFileSize' => $max_upload_size,
'imageSizes' => $available_image_sizes,
'availableLegacyWidgets' => $available_legacy_widgets,
'isRTL' => is_rtl(),
);

/**
* Filters the settings to pass to the widgets block editor.
*
* @since 5.6.0
*
* @param array $editor_settings Default editor settings.
*/
$editor_settings = apply_filters( 'widgets_block_editor_settings', $editor_settings );

wp_add_inline_script(
'wp-edit-widgets',
sprintf(
'wp.domReady( function() {
wp.editWidgets.initialize( "widgets-editor", %s );
} );',
wp_json_encode( $editor_settings )
)
);

$preload_paths = array(
array( '/wp/v2/media', 'OPTIONS' ),
'/__experimental/sidebars?context=edit&per_page=-1',
);
$preload_data = array_reduce(
$preload_paths,
'rest_preload_api_request',
array()
);
wp_add_inline_script(
'wp-api-fetch',
sprintf(
'wp.apiFetch.use( wp.apiFetch.createPreloadingMiddleware( %s ) );',
wp_json_encode( $preload_data )
),
'after'
);

wp_add_inline_script(
'wp-blocks',
'wp.blocks.unstable__bootstrapServerSideBlockDefinitions(' . wp_json_encode( get_block_editor_server_block_settings() ) . ');'
);

wp_enqueue_script( 'wp-edit-widgets' );
wp_enqueue_script( 'admin-widgets' );
wp_enqueue_script( 'wp-format-library' );
wp_enqueue_style( 'wp-edit-widgets' );
wp_enqueue_style( 'wp-format-library' );

require_once ABSPATH . 'wp-admin/admin-header.php';
?>

<div id="widgets-editor" class="blocks-widgets-container"></div>

<?php /* The Legacy Widget block requires this nonce */ ?>
<form method="post">
<?php wp_nonce_field( 'save-sidebar-widgets', '_wpnonce_widgets', false ); ?>
</form>

<?php
require_once ABSPATH . 'wp-admin/admin-footer.php';
Loading