diff --git a/package-lock.json b/package-lock.json
index afeb2e7a90b73..741064afab089 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -3270,25 +3270,25 @@
}
},
"@wordpress/block-library": {
- "version": "2.25.1",
- "resolved": "https://registry.npmjs.org/@wordpress/block-library/-/block-library-2.25.1.tgz",
- "integrity": "sha512-v+LJdUXoZopna4Xs1jJphO9V9fr+YAX1GunAdmfp6L1KOFd08EN9g4JL2q/sCKQkKCn1fCaef6ZRh8kTvcWDhA==",
+ "version": "2.25.3",
+ "resolved": "https://registry.npmjs.org/@wordpress/block-library/-/block-library-2.25.3.tgz",
+ "integrity": "sha512-cU6LSiwXK6Fy/+w9DWXIfhd8T/2bQXe9f2Kbe6VT9ZxzGGcs5HX1EGAIcHSm+I/lWbL0QPm2frtDDXS9zvWgUA==",
"requires": {
"@babel/runtime": "^7.11.2",
"@wordpress/a11y": "^2.13.0",
"@wordpress/api-fetch": "^3.20.0",
"@wordpress/autop": "^2.10.0",
"@wordpress/blob": "^2.10.0",
- "@wordpress/block-editor": "^5.0.1",
+ "@wordpress/block-editor": "^5.0.2",
"@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",
"@wordpress/date": "^3.12.0",
"@wordpress/deprecated": "^2.10.0",
"@wordpress/dom": "^2.15.0",
- "@wordpress/editor": "^9.23.1",
+ "@wordpress/editor": "^9.23.2",
"@wordpress/element": "^2.18.0",
"@wordpress/escape-html": "^1.10.0",
"@wordpress/hooks": "^2.10.0",
@@ -3299,7 +3299,7 @@
"@wordpress/notices": "^2.10.0",
"@wordpress/primitives": "^1.9.0",
"@wordpress/rich-text": "^3.22.0",
- "@wordpress/server-side-render": "^1.18.0",
+ "@wordpress/server-side-render": "^1.18.1",
"@wordpress/url": "^2.19.0",
"@wordpress/viewport": "^2.23.0",
"classnames": "^2.2.5",
@@ -3309,6 +3309,119 @@
"moment": "^2.22.1",
"react-easy-crop": "^3.0.0",
"tinycolor2": "^1.4.1"
+ },
+ "dependencies": {
+ "@wordpress/block-editor": {
+ "version": "5.0.2",
+ "resolved": "https://registry.npmjs.org/@wordpress/block-editor/-/block-editor-5.0.2.tgz",
+ "integrity": "sha512-zKVF2iDQMuJnK85YDJlHC2eKBdqjREbOKkjNV3CYUnIuMl114eXIyIWxA2mZxVLa1u/xfguttoGN6bZ9JtbCCA==",
+ "requires": {
+ "@babel/runtime": "^7.11.2",
+ "@wordpress/a11y": "^2.13.0",
+ "@wordpress/blob": "^2.10.0",
+ "@wordpress/blocks": "^6.23.0",
+ "@wordpress/components": "^11.0.1",
+ "@wordpress/compose": "^3.21.0",
+ "@wordpress/data": "^4.24.0",
+ "@wordpress/deprecated": "^2.10.0",
+ "@wordpress/dom": "^2.15.0",
+ "@wordpress/element": "^2.18.0",
+ "@wordpress/hooks": "^2.10.0",
+ "@wordpress/html-entities": "^2.9.0",
+ "@wordpress/i18n": "^3.16.0",
+ "@wordpress/icons": "^2.7.0",
+ "@wordpress/is-shallow-equal": "^2.3.0",
+ "@wordpress/keyboard-shortcuts": "^1.11.0",
+ "@wordpress/keycodes": "^2.16.0",
+ "@wordpress/notices": "^2.10.0",
+ "@wordpress/rich-text": "^3.22.0",
+ "@wordpress/shortcode": "^2.11.0",
+ "@wordpress/token-list": "^1.13.0",
+ "@wordpress/url": "^2.19.0",
+ "@wordpress/viewport": "^2.23.0",
+ "@wordpress/warning": "^1.3.0",
+ "@wordpress/wordcount": "^2.12.0",
+ "classnames": "^2.2.5",
+ "css-mediaquery": "^0.1.2",
+ "diff": "^4.0.2",
+ "dom-scroll-into-view": "^1.2.1",
+ "inherits": "^2.0.3",
+ "lodash": "^4.17.19",
+ "memize": "^1.1.0",
+ "react-autosize-textarea": "^3.0.2",
+ "react-spring": "^8.0.19",
+ "react-transition-group": "^2.9.0",
+ "reakit": "1.1.0",
+ "redux-multi": "^0.1.12",
+ "refx": "^3.0.0",
+ "rememo": "^3.0.0",
+ "tinycolor2": "^1.4.1",
+ "traverse": "^0.6.6"
+ }
+ },
+ "@wordpress/editor": {
+ "version": "9.23.2",
+ "resolved": "https://registry.npmjs.org/@wordpress/editor/-/editor-9.23.2.tgz",
+ "integrity": "sha512-b+RqUvriWOm93fRKUmzYUQH5PMAkmk4hZ8uJffbkXSal69KHZoD+0Z8Yk6mMPdYpwp2oaGQDJ7P50WVplcXA8w==",
+ "requires": {
+ "@babel/runtime": "^7.11.2",
+ "@wordpress/api-fetch": "^3.20.0",
+ "@wordpress/autop": "^2.10.0",
+ "@wordpress/blob": "^2.10.0",
+ "@wordpress/block-editor": "^5.0.2",
+ "@wordpress/blocks": "^6.23.0",
+ "@wordpress/components": "^11.0.1",
+ "@wordpress/compose": "^3.21.0",
+ "@wordpress/core-data": "^2.23.0",
+ "@wordpress/data": "^4.24.0",
+ "@wordpress/data-controls": "^1.18.0",
+ "@wordpress/date": "^3.12.0",
+ "@wordpress/deprecated": "^2.10.0",
+ "@wordpress/element": "^2.18.0",
+ "@wordpress/hooks": "^2.10.0",
+ "@wordpress/html-entities": "^2.9.0",
+ "@wordpress/i18n": "^3.16.0",
+ "@wordpress/icons": "^2.7.0",
+ "@wordpress/is-shallow-equal": "^2.3.0",
+ "@wordpress/keyboard-shortcuts": "^1.11.0",
+ "@wordpress/keycodes": "^2.16.0",
+ "@wordpress/media-utils": "^1.17.0",
+ "@wordpress/notices": "^2.10.0",
+ "@wordpress/rich-text": "^3.22.0",
+ "@wordpress/server-side-render": "^1.18.1",
+ "@wordpress/url": "^2.19.0",
+ "@wordpress/viewport": "^2.23.0",
+ "@wordpress/wordcount": "^2.12.0",
+ "classnames": "^2.2.5",
+ "lodash": "^4.17.19",
+ "memize": "^1.1.0",
+ "react-autosize-textarea": "^3.0.2",
+ "redux-optimist": "^1.0.0",
+ "refx": "^3.0.0",
+ "rememo": "^3.0.0"
+ }
+ },
+ "@wordpress/server-side-render": {
+ "version": "1.18.1",
+ "resolved": "https://registry.npmjs.org/@wordpress/server-side-render/-/server-side-render-1.18.1.tgz",
+ "integrity": "sha512-Q4kFdXtylMRIeyry0KYpSkH086MtJL8KRol92qC5T7YBK2tIKgmaMxPcy30sGR9RLBjGXZwuR82nORe5MCwZPA==",
+ "requires": {
+ "@babel/runtime": "^7.11.2",
+ "@wordpress/api-fetch": "^3.20.0",
+ "@wordpress/components": "^11.0.1",
+ "@wordpress/data": "^4.24.0",
+ "@wordpress/deprecated": "^2.10.0",
+ "@wordpress/element": "^2.18.0",
+ "@wordpress/i18n": "^3.16.0",
+ "@wordpress/url": "^2.19.0",
+ "lodash": "^4.17.19"
+ }
+ },
+ "diff": {
+ "version": "4.0.2",
+ "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz",
+ "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A=="
+ }
}
},
"@wordpress/block-serialization-default-parser": {
@@ -3362,9 +3475,9 @@
"dev": true
},
"@wordpress/components": {
- "version": "11.0.0",
- "resolved": "https://registry.npmjs.org/@wordpress/components/-/components-11.0.0.tgz",
- "integrity": "sha512-DAtGJoV0FcfdbO/POmbtbBpMpnvt4j8ffxPmaKD/XiO0A9FfyVKy3h2lrJ/g6/P2kyzaaS+LJbCyy186+PNQoA==",
+ "version": "11.0.1",
+ "resolved": "https://registry.npmjs.org/@wordpress/components/-/components-11.0.1.tgz",
+ "integrity": "sha512-pK4osLZUq+nAoBAOhelDtjPqouFKw/hIoqHdoHvWBLSAyJxGc0rYwU9xg5nFzpiy6FSWExNY/Ay227KVZs4aZQ==",
"requires": {
"@babel/runtime": "^7.11.2",
"@emotion/core": "^10.0.22",
@@ -3591,6 +3704,258 @@
"rememo": "^3.0.0"
}
},
+ "@wordpress/edit-widgets": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/@wordpress/edit-widgets/-/edit-widgets-1.0.2.tgz",
+ "integrity": "sha512-r1qH9rTAgwOhGTaxgUlyQiAAH/dqlEBn3nNZ9SjgP0u0oUs5G4wrs4wC8/0OY0A9O0JFd+ctC1C2K3NzWVWQ4A==",
+ "requires": {
+ "@babel/runtime": "^7.11.2",
+ "@wordpress/api-fetch": "^3.20.0",
+ "@wordpress/block-editor": "^5.0.2",
+ "@wordpress/block-library": "^2.25.3",
+ "@wordpress/blocks": "^6.23.0",
+ "@wordpress/components": "^11.0.1",
+ "@wordpress/compose": "^3.21.0",
+ "@wordpress/core-data": "^2.23.0",
+ "@wordpress/data": "^4.24.0",
+ "@wordpress/data-controls": "^1.18.0",
+ "@wordpress/element": "^2.18.0",
+ "@wordpress/hooks": "^2.10.0",
+ "@wordpress/i18n": "^3.16.0",
+ "@wordpress/icons": "^2.7.0",
+ "@wordpress/interface": "^0.9.1",
+ "@wordpress/keyboard-shortcuts": "^1.11.0",
+ "@wordpress/keycodes": "^2.16.0",
+ "@wordpress/media-utils": "^1.17.0",
+ "@wordpress/notices": "^2.10.0",
+ "@wordpress/plugins": "^2.22.0",
+ "@wordpress/server-side-render": "^1.18.1",
+ "@wordpress/url": "^2.19.0",
+ "classnames": "^2.2.5",
+ "lodash": "^4.17.19",
+ "reakit": "^1.1.0",
+ "rememo": "^3.0.0"
+ },
+ "dependencies": {
+ "@wordpress/block-editor": {
+ "version": "5.0.2",
+ "resolved": "https://registry.npmjs.org/@wordpress/block-editor/-/block-editor-5.0.2.tgz",
+ "integrity": "sha512-zKVF2iDQMuJnK85YDJlHC2eKBdqjREbOKkjNV3CYUnIuMl114eXIyIWxA2mZxVLa1u/xfguttoGN6bZ9JtbCCA==",
+ "requires": {
+ "@babel/runtime": "^7.11.2",
+ "@wordpress/a11y": "^2.13.0",
+ "@wordpress/blob": "^2.10.0",
+ "@wordpress/blocks": "^6.23.0",
+ "@wordpress/components": "^11.0.1",
+ "@wordpress/compose": "^3.21.0",
+ "@wordpress/data": "^4.24.0",
+ "@wordpress/deprecated": "^2.10.0",
+ "@wordpress/dom": "^2.15.0",
+ "@wordpress/element": "^2.18.0",
+ "@wordpress/hooks": "^2.10.0",
+ "@wordpress/html-entities": "^2.9.0",
+ "@wordpress/i18n": "^3.16.0",
+ "@wordpress/icons": "^2.7.0",
+ "@wordpress/is-shallow-equal": "^2.3.0",
+ "@wordpress/keyboard-shortcuts": "^1.11.0",
+ "@wordpress/keycodes": "^2.16.0",
+ "@wordpress/notices": "^2.10.0",
+ "@wordpress/rich-text": "^3.22.0",
+ "@wordpress/shortcode": "^2.11.0",
+ "@wordpress/token-list": "^1.13.0",
+ "@wordpress/url": "^2.19.0",
+ "@wordpress/viewport": "^2.23.0",
+ "@wordpress/warning": "^1.3.0",
+ "@wordpress/wordcount": "^2.12.0",
+ "classnames": "^2.2.5",
+ "css-mediaquery": "^0.1.2",
+ "diff": "^4.0.2",
+ "dom-scroll-into-view": "^1.2.1",
+ "inherits": "^2.0.3",
+ "lodash": "^4.17.19",
+ "memize": "^1.1.0",
+ "react-autosize-textarea": "^3.0.2",
+ "react-spring": "^8.0.19",
+ "react-transition-group": "^2.9.0",
+ "reakit": "1.1.0",
+ "redux-multi": "^0.1.12",
+ "refx": "^3.0.0",
+ "rememo": "^3.0.0",
+ "tinycolor2": "^1.4.1",
+ "traverse": "^0.6.6"
+ }
+ },
+ "@wordpress/block-library": {
+ "version": "2.25.3",
+ "resolved": "https://registry.npmjs.org/@wordpress/block-library/-/block-library-2.25.3.tgz",
+ "integrity": "sha512-cU6LSiwXK6Fy/+w9DWXIfhd8T/2bQXe9f2Kbe6VT9ZxzGGcs5HX1EGAIcHSm+I/lWbL0QPm2frtDDXS9zvWgUA==",
+ "requires": {
+ "@babel/runtime": "^7.11.2",
+ "@wordpress/a11y": "^2.13.0",
+ "@wordpress/api-fetch": "^3.20.0",
+ "@wordpress/autop": "^2.10.0",
+ "@wordpress/blob": "^2.10.0",
+ "@wordpress/block-editor": "^5.0.2",
+ "@wordpress/blocks": "^6.23.0",
+ "@wordpress/components": "^11.0.1",
+ "@wordpress/compose": "^3.21.0",
+ "@wordpress/core-data": "^2.23.0",
+ "@wordpress/data": "^4.24.0",
+ "@wordpress/date": "^3.12.0",
+ "@wordpress/deprecated": "^2.10.0",
+ "@wordpress/dom": "^2.15.0",
+ "@wordpress/editor": "^9.23.2",
+ "@wordpress/element": "^2.18.0",
+ "@wordpress/escape-html": "^1.10.0",
+ "@wordpress/hooks": "^2.10.0",
+ "@wordpress/i18n": "^3.16.0",
+ "@wordpress/icons": "^2.7.0",
+ "@wordpress/is-shallow-equal": "^2.3.0",
+ "@wordpress/keycodes": "^2.16.0",
+ "@wordpress/notices": "^2.10.0",
+ "@wordpress/primitives": "^1.9.0",
+ "@wordpress/rich-text": "^3.22.0",
+ "@wordpress/server-side-render": "^1.18.1",
+ "@wordpress/url": "^2.19.0",
+ "@wordpress/viewport": "^2.23.0",
+ "classnames": "^2.2.5",
+ "fast-average-color": "4.3.0",
+ "lodash": "^4.17.19",
+ "memize": "^1.1.0",
+ "moment": "^2.22.1",
+ "react-easy-crop": "^3.0.0",
+ "tinycolor2": "^1.4.1"
+ }
+ },
+ "@wordpress/components": {
+ "version": "11.0.1",
+ "resolved": "https://registry.npmjs.org/@wordpress/components/-/components-11.0.1.tgz",
+ "integrity": "sha512-pK4osLZUq+nAoBAOhelDtjPqouFKw/hIoqHdoHvWBLSAyJxGc0rYwU9xg5nFzpiy6FSWExNY/Ay227KVZs4aZQ==",
+ "requires": {
+ "@babel/runtime": "^7.11.2",
+ "@emotion/core": "^10.0.22",
+ "@emotion/css": "^10.0.22",
+ "@emotion/native": "^10.0.22",
+ "@emotion/styled": "^10.0.23",
+ "@wordpress/a11y": "^2.13.0",
+ "@wordpress/compose": "^3.21.0",
+ "@wordpress/date": "^3.12.0",
+ "@wordpress/deprecated": "^2.10.0",
+ "@wordpress/dom": "^2.15.0",
+ "@wordpress/element": "^2.18.0",
+ "@wordpress/hooks": "^2.10.0",
+ "@wordpress/i18n": "^3.16.0",
+ "@wordpress/icons": "^2.7.0",
+ "@wordpress/is-shallow-equal": "^2.3.0",
+ "@wordpress/keycodes": "^2.16.0",
+ "@wordpress/primitives": "^1.9.0",
+ "@wordpress/rich-text": "^3.22.0",
+ "@wordpress/warning": "^1.3.0",
+ "classnames": "^2.2.5",
+ "dom-scroll-into-view": "^1.2.1",
+ "downshift": "^5.4.0",
+ "gradient-parser": "^0.1.5",
+ "lodash": "^4.17.19",
+ "memize": "^1.1.0",
+ "moment": "^2.22.1",
+ "re-resizable": "^6.4.0",
+ "react-dates": "^17.1.1",
+ "react-merge-refs": "^1.0.0",
+ "react-resize-aware": "^3.0.1",
+ "react-spring": "^8.0.20",
+ "react-use-gesture": "^7.0.15",
+ "reakit": "^1.1.0",
+ "rememo": "^3.0.0",
+ "tinycolor2": "^1.4.1",
+ "uuid": "^7.0.2"
+ }
+ },
+ "@wordpress/editor": {
+ "version": "9.23.2",
+ "resolved": "https://registry.npmjs.org/@wordpress/editor/-/editor-9.23.2.tgz",
+ "integrity": "sha512-b+RqUvriWOm93fRKUmzYUQH5PMAkmk4hZ8uJffbkXSal69KHZoD+0Z8Yk6mMPdYpwp2oaGQDJ7P50WVplcXA8w==",
+ "requires": {
+ "@babel/runtime": "^7.11.2",
+ "@wordpress/api-fetch": "^3.20.0",
+ "@wordpress/autop": "^2.10.0",
+ "@wordpress/blob": "^2.10.0",
+ "@wordpress/block-editor": "^5.0.2",
+ "@wordpress/blocks": "^6.23.0",
+ "@wordpress/components": "^11.0.1",
+ "@wordpress/compose": "^3.21.0",
+ "@wordpress/core-data": "^2.23.0",
+ "@wordpress/data": "^4.24.0",
+ "@wordpress/data-controls": "^1.18.0",
+ "@wordpress/date": "^3.12.0",
+ "@wordpress/deprecated": "^2.10.0",
+ "@wordpress/element": "^2.18.0",
+ "@wordpress/hooks": "^2.10.0",
+ "@wordpress/html-entities": "^2.9.0",
+ "@wordpress/i18n": "^3.16.0",
+ "@wordpress/icons": "^2.7.0",
+ "@wordpress/is-shallow-equal": "^2.3.0",
+ "@wordpress/keyboard-shortcuts": "^1.11.0",
+ "@wordpress/keycodes": "^2.16.0",
+ "@wordpress/media-utils": "^1.17.0",
+ "@wordpress/notices": "^2.10.0",
+ "@wordpress/rich-text": "^3.22.0",
+ "@wordpress/server-side-render": "^1.18.1",
+ "@wordpress/url": "^2.19.0",
+ "@wordpress/viewport": "^2.23.0",
+ "@wordpress/wordcount": "^2.12.0",
+ "classnames": "^2.2.5",
+ "lodash": "^4.17.19",
+ "memize": "^1.1.0",
+ "react-autosize-textarea": "^3.0.2",
+ "redux-optimist": "^1.0.0",
+ "refx": "^3.0.0",
+ "rememo": "^3.0.0"
+ }
+ },
+ "@wordpress/interface": {
+ "version": "0.9.1",
+ "resolved": "https://registry.npmjs.org/@wordpress/interface/-/interface-0.9.1.tgz",
+ "integrity": "sha512-+wjnX7lN92o5054f1qDLMkscGhhiVB5cT/Oq09Srbg0+hwrjQEzeq1UGmTXEO+w/k1VV11EyEcA31J9h1f90sQ==",
+ "requires": {
+ "@babel/runtime": "^7.11.2",
+ "@wordpress/components": "^11.0.1",
+ "@wordpress/data": "^4.24.0",
+ "@wordpress/element": "^2.18.0",
+ "@wordpress/i18n": "^3.16.0",
+ "@wordpress/icons": "^2.7.0",
+ "@wordpress/plugins": "^2.22.0",
+ "classnames": "^2.2.5",
+ "lodash": "^4.17.19"
+ }
+ },
+ "@wordpress/server-side-render": {
+ "version": "1.18.1",
+ "resolved": "https://registry.npmjs.org/@wordpress/server-side-render/-/server-side-render-1.18.1.tgz",
+ "integrity": "sha512-Q4kFdXtylMRIeyry0KYpSkH086MtJL8KRol92qC5T7YBK2tIKgmaMxPcy30sGR9RLBjGXZwuR82nORe5MCwZPA==",
+ "requires": {
+ "@babel/runtime": "^7.11.2",
+ "@wordpress/api-fetch": "^3.20.0",
+ "@wordpress/components": "^11.0.1",
+ "@wordpress/data": "^4.24.0",
+ "@wordpress/deprecated": "^2.10.0",
+ "@wordpress/element": "^2.18.0",
+ "@wordpress/i18n": "^3.16.0",
+ "@wordpress/url": "^2.19.0",
+ "lodash": "^4.17.19"
+ }
+ },
+ "diff": {
+ "version": "4.0.2",
+ "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz",
+ "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A=="
+ },
+ "uuid": {
+ "version": "7.0.3",
+ "resolved": "https://registry.npmjs.org/uuid/-/uuid-7.0.3.tgz",
+ "integrity": "sha512-DPSke0pXhTZgoF/d+WSt2QaKMCFSfx7QegxEWT+JOuHF5aWrKEn0G+ztjuJg/gG8/ItK+rbPCD/yNv8yyih6Cg=="
+ }
+ }
+ },
"@wordpress/editor": {
"version": "9.23.1",
"resolved": "https://registry.npmjs.org/@wordpress/editor/-/editor-9.23.1.tgz",
diff --git a/package.json b/package.json
index ab775e77cf1f7..dc9e7e65e2801 100644
--- a/package.json
+++ b/package.json
@@ -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",
@@ -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",
diff --git a/src/js/_enqueues/wp/customize/widgets.js b/src/js/_enqueues/wp/customize/widgets.js
index 990a3e19b525a..0e8c1108e7c17 100644
--- a/src/js/_enqueues/wp/customize/widgets.js
+++ b/src/js/_enqueues/wp/customize/widgets.js
@@ -566,6 +566,7 @@
control._setupHighlightEffects();
control._setupUpdateUI();
control._setupRemoveUI();
+ control._setupEditUI();
},
/**
@@ -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(
+ $( '' )
+ .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
diff --git a/src/wp-admin/admin-header.php b/src/wp-admin/admin-header.php
index 8eddb2b892143..6fd15dd209de3 100644
--- a/src/wp-admin/admin-header.php
+++ b/src/wp-admin/admin-header.php
@@ -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';
diff --git a/src/wp-admin/includes/widgets.php b/src/wp-admin/includes/widgets.php
index ac98cdb5274ee..e80d55f7a5196 100644
--- a/src/wp-admin/includes/widgets.php
+++ b/src/wp-admin/includes/widgets.php
@@ -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 ) {
+ ?>
+
+>
+
+
+
+
+
+
+
+>
+
+
+ get_registered( 'core/legacy-widget' );
+ echo $block->render( $widget_preview );
+ ?>
+
+
+
+
+
+ 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';
+?>
+
+
+
+
+
+
+add_help_tab(
+ array(
+ 'id' => 'overview',
+ 'title' => __( 'Overview' ),
+ 'content' =>
+ '' . __( 'Widgets are independent sections of content that can be placed into any widgetized area provided by your theme (commonly called sidebars). To populate your sidebars/widget areas with individual widgets, drag and drop the title bars into the desired area. By default, only the first widget area is expanded. To populate additional widget areas, click on their title bars to expand them.' ) . '
+ ' . __( 'The Available Widgets section contains all the widgets you can choose from. Once you drag a widget into a sidebar, it will open to allow you to configure its settings. When you are happy with the widget settings, click the Save button and the widget will go live on your site. If you click Delete, it will remove the widget.' ) . '
',
+ )
+);
+get_current_screen()->add_help_tab(
+ array(
+ 'id' => 'removing-reusing',
+ 'title' => __( 'Removing and Reusing' ),
+ 'content' =>
+ '' . __( 'If you want to remove the widget but save its setting for possible future use, just drag it into the Inactive Widgets area. You can add them back anytime from there. This is especially helpful when you switch to a theme with fewer or different widget areas.' ) . '
+ ' . __( 'Widgets may be used multiple times. You can give each widget a title, to display on your site, but it’s not required.' ) . '
+ ' . __( 'Enabling Accessibility Mode, via Screen Options, allows you to use Add and Edit buttons instead of using drag and drop.' ) . '
',
+ )
+);
+get_current_screen()->add_help_tab(
+ array(
+ 'id' => 'missing-widgets',
+ 'title' => __( 'Missing Widgets' ),
+ 'content' =>
+ '' . __( 'Many themes show some sidebar widgets by default until you edit your sidebars, but they are not automatically displayed in your sidebar management tool. After you make your first widget change, you can re-add the default widgets by adding them from the Available Widgets area.' ) . '
' .
+ '' . __( 'When changing themes, there is often some variation in the number and setup of widget areas/sidebars and sometimes these conflicts make the transition a bit less smooth. If you changed themes and seem to be missing widgets, scroll down on this screen to the Inactive Widgets area, where all of your widgets and their settings will have been saved.' ) . '
',
+ )
+);
+
+get_current_screen()->set_help_sidebar(
+ '' . __( 'For more information:' ) . '
' .
+ '' . __( 'Documentation on Widgets ' ) . '
' .
+ '' . __( 'Support ' ) . '
'
+);
+
+if ( ! current_theme_supports( 'widgets' ) ) {
+ wp_die( __( 'The theme you are currently using isn’t widget-aware, meaning that it has no sidebars that you are able to change. For information on making your theme widget-aware, please follow these instructions .' ) );
+}
+
+// These are the widgets grouped by sidebar.
+$sidebars_widgets = wp_get_sidebars_widgets();
+
+if ( empty( $sidebars_widgets ) ) {
+ $sidebars_widgets = wp_get_widget_defaults();
+}
+
+foreach ( $sidebars_widgets as $sidebar_id => $widgets ) {
+ if ( 'wp_inactive_widgets' === $sidebar_id ) {
+ continue;
+ }
+
+ if ( ! is_registered_sidebar( $sidebar_id ) ) {
+ if ( ! empty( $widgets ) ) { // Register the inactive_widgets area as sidebar.
+ register_sidebar(
+ array(
+ 'name' => __( 'Inactive Sidebar (not used)' ),
+ 'id' => $sidebar_id,
+ 'class' => 'inactive-sidebar orphan-sidebar',
+ 'description' => __( 'This sidebar is no longer available and does not show anywhere on your site. Remove each of the widgets below to fully remove this inactive sidebar.' ),
+ 'before_widget' => '',
+ 'after_widget' => '',
+ 'before_title' => '',
+ 'after_title' => '',
+ )
+ );
+ } else {
+ unset( $sidebars_widgets[ $sidebar_id ] );
+ }
+ }
+}
+
+// Register the inactive_widgets area as sidebar.
+register_sidebar(
+ array(
+ 'name' => __( 'Inactive Widgets' ),
+ 'id' => 'wp_inactive_widgets',
+ 'class' => 'inactive-sidebar',
+ 'description' => __( 'Drag widgets here to remove them from the sidebar but keep their settings.' ),
+ 'before_widget' => '',
+ 'after_widget' => '',
+ 'before_title' => '',
+ 'after_title' => '',
+ )
+);
+
+retrieve_widgets();
+
+// We're saving a widget without JS.
+if ( isset( $_POST['savewidget'] ) || isset( $_POST['removewidget'] ) ) {
+ $widget_id = $_POST['widget-id'];
+ check_admin_referer( "save-delete-widget-$widget_id" );
+
+ $number = isset( $_POST['multi_number'] ) ? (int) $_POST['multi_number'] : '';
+ if ( $number ) {
+ foreach ( $_POST as $key => $val ) {
+ if ( is_array( $val ) && preg_match( '/__i__|%i%/', key( $val ) ) ) {
+ $_POST[ $key ] = array( $number => array_shift( $val ) );
+ break;
+ }
+ }
+ }
+
+ $sidebar_id = $_POST['sidebar'];
+ $position = isset( $_POST[ $sidebar_id . '_position' ] ) ? (int) $_POST[ $sidebar_id . '_position' ] - 1 : 0;
+
+ $id_base = $_POST['id_base'];
+ $sidebar = isset( $sidebars_widgets[ $sidebar_id ] ) ? $sidebars_widgets[ $sidebar_id ] : array();
+
+ // Delete.
+ if ( isset( $_POST['removewidget'] ) && $_POST['removewidget'] ) {
+
+ if ( ! in_array( $widget_id, $sidebar, true ) ) {
+ wp_redirect( admin_url( 'widgets.php?error=0' ) );
+ exit;
+ }
+
+ $sidebar = array_diff( $sidebar, array( $widget_id ) );
+ $_POST = array(
+ 'sidebar' => $sidebar_id,
+ 'widget-' . $id_base => array(),
+ 'the-widget-id' => $widget_id,
+ 'delete_widget' => '1',
+ );
+
+ /**
+ * Fires immediately after a widget has been marked for deletion.
+ *
+ * @since 4.4.0
+ *
+ * @param string $widget_id ID of the widget marked for deletion.
+ * @param string $sidebar_id ID of the sidebar the widget was deleted from.
+ * @param string $id_base ID base for the widget.
+ */
+ do_action( 'delete_widget', $widget_id, $sidebar_id, $id_base );
+ }
+
+ $_POST['widget-id'] = $sidebar;
+
+ foreach ( (array) $wp_registered_widget_updates as $name => $control ) {
+ if ( $name !== $id_base || ! is_callable( $control['callback'] ) ) {
+ continue;
+ }
+
+ ob_start();
+ call_user_func_array( $control['callback'], $control['params'] );
+ ob_end_clean();
+
+ break;
+ }
+
+ $sidebars_widgets[ $sidebar_id ] = $sidebar;
+
+ // Remove old position.
+ if ( ! isset( $_POST['delete_widget'] ) ) {
+ foreach ( $sidebars_widgets as $key => $sb ) {
+ if ( is_array( $sb ) ) {
+ $sidebars_widgets[ $key ] = array_diff( $sb, array( $widget_id ) );
+ }
+ }
+ array_splice( $sidebars_widgets[ $sidebar_id ], $position, 0, $widget_id );
+ }
+
+ wp_set_sidebars_widgets( $sidebars_widgets );
+ wp_redirect( admin_url( 'widgets.php?message=0' ) );
+ exit;
+}
+
+// Remove inactive widgets without JS.
+if ( isset( $_POST['removeinactivewidgets'] ) ) {
+ check_admin_referer( 'remove-inactive-widgets', '_wpnonce_remove_inactive_widgets' );
+
+ if ( $_POST['removeinactivewidgets'] ) {
+ foreach ( $sidebars_widgets['wp_inactive_widgets'] as $key => $widget_id ) {
+ $pieces = explode( '-', $widget_id );
+ $multi_number = array_pop( $pieces );
+ $id_base = implode( '-', $pieces );
+ $widget = get_option( 'widget_' . $id_base );
+ unset( $widget[ $multi_number ] );
+ update_option( 'widget_' . $id_base, $widget );
+ unset( $sidebars_widgets['wp_inactive_widgets'][ $key ] );
+ }
+
+ wp_set_sidebars_widgets( $sidebars_widgets );
+ }
+
+ wp_redirect( admin_url( 'widgets.php?message=0' ) );
+ exit;
+}
+
+// Output the widget form without JS.
+if ( isset( $_GET['editwidget'] ) && $_GET['editwidget'] ) {
+ $widget_id = $_GET['editwidget'];
+
+ if ( isset( $_GET['addnew'] ) ) {
+ // Default to the first sidebar.
+ $keys = array_keys( $wp_registered_sidebars );
+ $sidebar = reset( $keys );
+
+ if ( isset( $_GET['base'] ) && isset( $_GET['num'] ) ) { // Multi-widget.
+ // Copy minimal info from an existing instance of this widget to a new instance.
+ foreach ( $wp_registered_widget_controls as $control ) {
+ if ( $_GET['base'] === $control['id_base'] ) {
+ $control_callback = $control['callback'];
+ $multi_number = (int) $_GET['num'];
+ $control['params'][0]['number'] = -1;
+ $control['id'] = $control['id_base'] . '-' . $multi_number;
+ $widget_id = $control['id'];
+ $wp_registered_widget_controls[ $control['id'] ] = $control;
+ break;
+ }
+ }
+ }
+ }
+
+ if ( isset( $wp_registered_widget_controls[ $widget_id ] ) && ! isset( $control ) ) {
+ $control = $wp_registered_widget_controls[ $widget_id ];
+ $control_callback = $control['callback'];
+ } elseif ( ! isset( $wp_registered_widget_controls[ $widget_id ] ) && isset( $wp_registered_widgets[ $widget_id ] ) ) {
+ $name = esc_html( strip_tags( $wp_registered_widgets[ $widget_id ]['name'] ) );
+ }
+
+ if ( ! isset( $name ) ) {
+ $name = esc_html( strip_tags( $control['name'] ) );
+ }
+
+ if ( ! isset( $sidebar ) ) {
+ $sidebar = isset( $_GET['sidebar'] ) ? $_GET['sidebar'] : 'wp_inactive_widgets';
+ }
+
+ if ( ! isset( $multi_number ) ) {
+ $multi_number = isset( $control['params'][0]['number'] ) ? $control['params'][0]['number'] : '';
+ }
+
+ $id_base = isset( $control['id_base'] ) ? $control['id_base'] : $control['id'];
+
+ // Show the widget form.
+ $width = ' style="width:' . max( $control['width'], 350 ) . 'px"';
+ $key = isset( $_GET['key'] ) ? (int) $_GET['key'] : 0;
+
+ require_once ABSPATH . 'wp-admin/admin-header.php'; ?>
+
+
+
+
+
+
+
+
+%2$s',
+ esc_url(
+ add_query_arg(
+ array(
+ array( 'autofocus' => array( 'panel' => 'widgets' ) ),
+ 'return' => urlencode( remove_query_arg( wp_removable_query_args(), wp_unslash( $_SERVER['REQUEST_URI'] ) ) ),
+ ),
+ admin_url( 'customize.php' )
+ )
+ ),
+ __( 'Manage with Live Preview' )
+ );
+}
+
+$nonce = wp_create_nonce( 'widgets-access' );
+?>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 1 ) {
+ $split = (int) ceil( $sidebars_count / 2 );
+} else {
+ $single_sidebar_class = ' single-sidebar';
+}
+
+?>
+
+
+
+
+
+
+
+
+
+add_help_tab(
- array(
- 'id' => 'overview',
- 'title' => __( 'Overview' ),
- 'content' =>
- '' . __( 'Widgets are independent sections of content that can be placed into any widgetized area provided by your theme (commonly called sidebars). To populate your sidebars/widget areas with individual widgets, drag and drop the title bars into the desired area. By default, only the first widget area is expanded. To populate additional widget areas, click on their title bars to expand them.' ) . '
- ' . __( 'The Available Widgets section contains all the widgets you can choose from. Once you drag a widget into a sidebar, it will open to allow you to configure its settings. When you are happy with the widget settings, click the Save button and the widget will go live on your site. If you click Delete, it will remove the widget.' ) . '
',
- )
-);
-get_current_screen()->add_help_tab(
- array(
- 'id' => 'removing-reusing',
- 'title' => __( 'Removing and Reusing' ),
- 'content' =>
- '' . __( 'If you want to remove the widget but save its setting for possible future use, just drag it into the Inactive Widgets area. You can add them back anytime from there. This is especially helpful when you switch to a theme with fewer or different widget areas.' ) . '
- ' . __( 'Widgets may be used multiple times. You can give each widget a title, to display on your site, but it’s not required.' ) . '
- ' . __( 'Enabling Accessibility Mode, via Screen Options, allows you to use Add and Edit buttons instead of using drag and drop.' ) . '
',
- )
-);
-get_current_screen()->add_help_tab(
- array(
- 'id' => 'missing-widgets',
- 'title' => __( 'Missing Widgets' ),
- 'content' =>
- '' . __( 'Many themes show some sidebar widgets by default until you edit your sidebars, but they are not automatically displayed in your sidebar management tool. After you make your first widget change, you can re-add the default widgets by adding them from the Available Widgets area.' ) . '
' .
- '' . __( 'When changing themes, there is often some variation in the number and setup of widget areas/sidebars and sometimes these conflicts make the transition a bit less smooth. If you changed themes and seem to be missing widgets, scroll down on this screen to the Inactive Widgets area, where all of your widgets and their settings will have been saved.' ) . '
',
- )
-);
-
-get_current_screen()->set_help_sidebar(
- '' . __( 'For more information:' ) . '
' .
- '' . __( 'Documentation on Widgets ' ) . '
' .
- '' . __( 'Support ' ) . '
'
-);
-
-if ( ! current_theme_supports( 'widgets' ) ) {
- wp_die( __( 'The theme you are currently using isn’t widget-aware, meaning that it has no sidebars that you are able to change. For information on making your theme widget-aware, please follow these instructions .' ) );
-}
-
-// These are the widgets grouped by sidebar.
-$sidebars_widgets = wp_get_sidebars_widgets();
-
-if ( empty( $sidebars_widgets ) ) {
- $sidebars_widgets = wp_get_widget_defaults();
-}
-
-foreach ( $sidebars_widgets as $sidebar_id => $widgets ) {
- if ( 'wp_inactive_widgets' === $sidebar_id ) {
- continue;
- }
-
- if ( ! is_registered_sidebar( $sidebar_id ) ) {
- if ( ! empty( $widgets ) ) { // Register the inactive_widgets area as sidebar.
- register_sidebar(
- array(
- 'name' => __( 'Inactive Sidebar (not used)' ),
- 'id' => $sidebar_id,
- 'class' => 'inactive-sidebar orphan-sidebar',
- 'description' => __( 'This sidebar is no longer available and does not show anywhere on your site. Remove each of the widgets below to fully remove this inactive sidebar.' ),
- 'before_widget' => '',
- 'after_widget' => '',
- 'before_title' => '',
- 'after_title' => '',
- )
- );
- } else {
- unset( $sidebars_widgets[ $sidebar_id ] );
- }
- }
-}
-
-// Register the inactive_widgets area as sidebar.
-register_sidebar(
- array(
- 'name' => __( 'Inactive Widgets' ),
- 'id' => 'wp_inactive_widgets',
- 'class' => 'inactive-sidebar',
- 'description' => __( 'Drag widgets here to remove them from the sidebar but keep their settings.' ),
- 'before_widget' => '',
- 'after_widget' => '',
- 'before_title' => '',
- 'after_title' => '',
- )
-);
-
-retrieve_widgets();
-
-// We're saving a widget without JS.
-if ( isset( $_POST['savewidget'] ) || isset( $_POST['removewidget'] ) ) {
- $widget_id = $_POST['widget-id'];
- check_admin_referer( "save-delete-widget-$widget_id" );
-
- $number = isset( $_POST['multi_number'] ) ? (int) $_POST['multi_number'] : '';
- if ( $number ) {
- foreach ( $_POST as $key => $val ) {
- if ( is_array( $val ) && preg_match( '/__i__|%i%/', key( $val ) ) ) {
- $_POST[ $key ] = array( $number => array_shift( $val ) );
- break;
- }
- }
- }
-
- $sidebar_id = $_POST['sidebar'];
- $position = isset( $_POST[ $sidebar_id . '_position' ] ) ? (int) $_POST[ $sidebar_id . '_position' ] - 1 : 0;
-
- $id_base = $_POST['id_base'];
- $sidebar = isset( $sidebars_widgets[ $sidebar_id ] ) ? $sidebars_widgets[ $sidebar_id ] : array();
-
- // Delete.
- if ( isset( $_POST['removewidget'] ) && $_POST['removewidget'] ) {
-
- if ( ! in_array( $widget_id, $sidebar, true ) ) {
- wp_redirect( admin_url( 'widgets.php?error=0' ) );
- exit;
- }
-
- $sidebar = array_diff( $sidebar, array( $widget_id ) );
- $_POST = array(
- 'sidebar' => $sidebar_id,
- 'widget-' . $id_base => array(),
- 'the-widget-id' => $widget_id,
- 'delete_widget' => '1',
- );
-
- /**
- * Fires immediately after a widget has been marked for deletion.
- *
- * @since 4.4.0
- *
- * @param string $widget_id ID of the widget marked for deletion.
- * @param string $sidebar_id ID of the sidebar the widget was deleted from.
- * @param string $id_base ID base for the widget.
- */
- do_action( 'delete_widget', $widget_id, $sidebar_id, $id_base );
- }
-
- $_POST['widget-id'] = $sidebar;
-
- foreach ( (array) $wp_registered_widget_updates as $name => $control ) {
- if ( $name !== $id_base || ! is_callable( $control['callback'] ) ) {
- continue;
- }
-
- ob_start();
- call_user_func_array( $control['callback'], $control['params'] );
- ob_end_clean();
-
- break;
- }
-
- $sidebars_widgets[ $sidebar_id ] = $sidebar;
-
- // Remove old position.
- if ( ! isset( $_POST['delete_widget'] ) ) {
- foreach ( $sidebars_widgets as $key => $sb ) {
- if ( is_array( $sb ) ) {
- $sidebars_widgets[ $key ] = array_diff( $sb, array( $widget_id ) );
- }
- }
- array_splice( $sidebars_widgets[ $sidebar_id ], $position, 0, $widget_id );
- }
-
- wp_set_sidebars_widgets( $sidebars_widgets );
- wp_redirect( admin_url( 'widgets.php?message=0' ) );
- exit;
-}
-
-// Remove inactive widgets without JS.
-if ( isset( $_POST['removeinactivewidgets'] ) ) {
- check_admin_referer( 'remove-inactive-widgets', '_wpnonce_remove_inactive_widgets' );
-
- if ( $_POST['removeinactivewidgets'] ) {
- foreach ( $sidebars_widgets['wp_inactive_widgets'] as $key => $widget_id ) {
- $pieces = explode( '-', $widget_id );
- $multi_number = array_pop( $pieces );
- $id_base = implode( '-', $pieces );
- $widget = get_option( 'widget_' . $id_base );
- unset( $widget[ $multi_number ] );
- update_option( 'widget_' . $id_base, $widget );
- unset( $sidebars_widgets['wp_inactive_widgets'][ $key ] );
- }
-
- wp_set_sidebars_widgets( $sidebars_widgets );
- }
-
- wp_redirect( admin_url( 'widgets.php?message=0' ) );
- exit;
-}
-
-// Output the widget form without JS.
-if ( isset( $_GET['editwidget'] ) && $_GET['editwidget'] ) {
- $widget_id = $_GET['editwidget'];
-
- if ( isset( $_GET['addnew'] ) ) {
- // Default to the first sidebar.
- $keys = array_keys( $wp_registered_sidebars );
- $sidebar = reset( $keys );
-
- if ( isset( $_GET['base'] ) && isset( $_GET['num'] ) ) { // Multi-widget.
- // Copy minimal info from an existing instance of this widget to a new instance.
- foreach ( $wp_registered_widget_controls as $control ) {
- if ( $_GET['base'] === $control['id_base'] ) {
- $control_callback = $control['callback'];
- $multi_number = (int) $_GET['num'];
- $control['params'][0]['number'] = -1;
- $control['id'] = $control['id_base'] . '-' . $multi_number;
- $widget_id = $control['id'];
- $wp_registered_widget_controls[ $control['id'] ] = $control;
- break;
- }
- }
- }
- }
-
- if ( isset( $wp_registered_widget_controls[ $widget_id ] ) && ! isset( $control ) ) {
- $control = $wp_registered_widget_controls[ $widget_id ];
- $control_callback = $control['callback'];
- } elseif ( ! isset( $wp_registered_widget_controls[ $widget_id ] ) && isset( $wp_registered_widgets[ $widget_id ] ) ) {
- $name = esc_html( strip_tags( $wp_registered_widgets[ $widget_id ]['name'] ) );
- }
-
- if ( ! isset( $name ) ) {
- $name = esc_html( strip_tags( $control['name'] ) );
- }
-
- if ( ! isset( $sidebar ) ) {
- $sidebar = isset( $_GET['sidebar'] ) ? $_GET['sidebar'] : 'wp_inactive_widgets';
- }
-
- if ( ! isset( $multi_number ) ) {
- $multi_number = isset( $control['params'][0]['number'] ) ? $control['params'][0]['number'] : '';
- }
-
- $id_base = isset( $control['id_base'] ) ? $control['id_base'] : $control['id'];
-
- // Show the widget form.
- $width = ' style="width:' . max( $control['width'], 350 ) . 'px"';
- $key = isset( $_GET['key'] ) ? (int) $_GET['key'] : 0;
-
- require_once ABSPATH . 'wp-admin/admin-header.php'; ?>
-
-
-
-
-
-
-
-
-%2$s',
- esc_url(
- add_query_arg(
- array(
- array( 'autofocus' => array( 'panel' => 'widgets' ) ),
- 'return' => urlencode( remove_query_arg( wp_removable_query_args(), wp_unslash( $_SERVER['REQUEST_URI'] ) ) ),
- ),
- admin_url( 'customize.php' )
- )
- ),
- __( 'Manage with Live Preview' )
- );
-}
-
-$nonce = wp_create_nonce( 'widgets-access' );
-?>
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- 1 ) {
- $split = (int) ceil( $sidebars_count / 2 );
+if ( $use_widgets_block_editor ) {
+ require ABSPATH . 'wp-admin/widgets-block-editor.php';
} else {
- $single_sidebar_class = ' single-sidebar';
+ require ABSPATH . 'wp-admin/widgets-form.php';
}
-
-?>
-
-
-
-
-
-
-
-
-
- array('dependencies' => array('wp-dom-ready', 'wp-i18n', 'wp-polyfill'), 'version' => '6d98587879c8c19080b1e3a855e946be'), 'annotations.js' => array('dependencies' => array('lodash', 'wp-data', 'wp-hooks', 'wp-i18n', 'wp-polyfill', 'wp-rich-text'), 'version' => '6f5dba93cfcc859a12384d6500bbdb6a'), 'api-fetch.js' => array('dependencies' => array('wp-i18n', 'wp-polyfill', 'wp-url'), 'version' => 'd38d8020fb8b03594fb705059bd02d08'), 'autop.js' => array('dependencies' => array('wp-polyfill'), 'version' => 'e3a7061e1087f5cf077a68aeaf0ea714'), 'blob.js' => array('dependencies' => array('wp-polyfill'), 'version' => '27195f29e36179999f6e1fa7d1f079b3'), 'block-directory.js' => array('dependencies' => array('lodash', 'wp-api-fetch', 'wp-block-editor', 'wp-blocks', 'wp-components', 'wp-compose', 'wp-data', 'wp-data-controls', 'wp-edit-post', 'wp-element', 'wp-hooks', 'wp-html-entities', 'wp-i18n', 'wp-notices', 'wp-plugins', 'wp-polyfill', 'wp-primitives'), 'version' => '48cdfe01e7d468f66bf1f31667b83ac6'), 'block-editor.js' => array('dependencies' => array('lodash', 'react', 'react-dom', 'wp-a11y', 'wp-blob', 'wp-blocks', 'wp-components', 'wp-compose', 'wp-data', 'wp-deprecated', 'wp-dom', 'wp-element', 'wp-hooks', 'wp-html-entities', 'wp-i18n', 'wp-is-shallow-equal', 'wp-keyboard-shortcuts', 'wp-keycodes', 'wp-notices', 'wp-polyfill', 'wp-primitives', 'wp-rich-text', 'wp-shortcode', 'wp-token-list', 'wp-url', 'wp-viewport', 'wp-warning', 'wp-wordcount'), 'version' => '503c5ca4a090284e4d04aa16b31dfdec'), 'block-library.js' => array('dependencies' => array('lodash', 'moment', 'react', 'wp-api-fetch', 'wp-autop', 'wp-blob', 'wp-block-editor', 'wp-blocks', 'wp-components', 'wp-compose', 'wp-core-data', 'wp-data', 'wp-date', 'wp-deprecated', 'wp-dom', 'wp-element', 'wp-i18n', 'wp-keycodes', 'wp-notices', 'wp-polyfill', 'wp-primitives', 'wp-rich-text', 'wp-server-side-render', 'wp-url', 'wp-viewport'), 'version' => '21b8a23eb77869fdc13df5b86d7b922f'), 'block-serialization-default-parser.js' => array('dependencies' => array('wp-polyfill'), 'version' => '27585bbfe083d705c915c21bf47047df'), 'blocks.js' => array('dependencies' => array('lodash', 'wp-autop', 'wp-blob', 'wp-block-serialization-default-parser', 'wp-compose', 'wp-data', 'wp-deprecated', 'wp-dom', 'wp-element', 'wp-hooks', 'wp-html-entities', 'wp-i18n', 'wp-is-shallow-equal', 'wp-polyfill', 'wp-primitives', 'wp-shortcode'), 'version' => '7ba861a0b2e8f76fc7a1f4c7a3a59de1'), 'components.js' => array('dependencies' => array('lodash', 'moment', 'react', 'react-dom', 'wp-a11y', 'wp-compose', 'wp-date', 'wp-deprecated', 'wp-dom', 'wp-element', 'wp-hooks', 'wp-i18n', 'wp-is-shallow-equal', 'wp-keycodes', 'wp-polyfill', 'wp-primitives', 'wp-rich-text', 'wp-warning'), 'version' => '57a23fbc83c860f0547e814cff74072a'), 'compose.js' => array('dependencies' => array('lodash', 'react', 'wp-element', 'wp-is-shallow-equal', 'wp-polyfill', 'wp-priority-queue'), 'version' => '980168910efaf01ea313952dd1af8fbd'), 'core-data.js' => array('dependencies' => array('lodash', 'wp-blocks', 'wp-data', 'wp-data-controls', 'wp-deprecated', 'wp-element', 'wp-i18n', 'wp-is-shallow-equal', 'wp-polyfill', 'wp-url'), 'version' => '7159cab2b2ec3870267c3549595864a6'), 'data.js' => array('dependencies' => array('lodash', 'react', 'wp-compose', 'wp-deprecated', 'wp-element', 'wp-is-shallow-equal', 'wp-polyfill', 'wp-priority-queue', 'wp-redux-routine'), 'version' => '18c22155dc4bce9be5fb2d823c738095'), 'data-controls.js' => array('dependencies' => array('wp-api-fetch', 'wp-data', 'wp-polyfill'), 'version' => '6cb5c91c1427296ea7f52a6349c6f179'), 'date.js' => array('dependencies' => array('moment', 'wp-polyfill'), 'version' => 'c9122f4b8a25a58b47487ad81ddf4742'), 'deprecated.js' => array('dependencies' => array('wp-hooks', 'wp-polyfill'), 'version' => '26aefabb46263ab5dac6d7f6c63b664c'), 'dom.js' => array('dependencies' => array('lodash', 'wp-polyfill'), 'version' => 'eedd920647fd959208dfb7bbf9caeadb'), 'dom-ready.js' => array('dependencies' => array('wp-polyfill'), 'version' => 'a6586b64552c9c6924b8093e9ef4f74e'), 'edit-post.js' => array('dependencies' => array('lodash', 'wp-a11y', 'wp-api-fetch', 'wp-block-editor', 'wp-block-library', 'wp-blocks', 'wp-components', 'wp-compose', 'wp-core-data', 'wp-data', 'wp-data-controls', 'wp-editor', 'wp-element', 'wp-hooks', 'wp-i18n', 'wp-keyboard-shortcuts', 'wp-keycodes', 'wp-media-utils', 'wp-notices', 'wp-plugins', 'wp-polyfill', 'wp-primitives', 'wp-url', 'wp-viewport', 'wp-warning'), 'version' => '4b53e762718f21b20f2b2c6875f540cc'), 'editor.js' => array('dependencies' => array('lodash', 'react', 'wp-api-fetch', 'wp-autop', 'wp-block-editor', 'wp-blocks', 'wp-components', 'wp-compose', 'wp-core-data', 'wp-data', 'wp-data-controls', 'wp-date', 'wp-deprecated', 'wp-element', 'wp-hooks', 'wp-html-entities', 'wp-i18n', 'wp-keyboard-shortcuts', 'wp-keycodes', 'wp-media-utils', 'wp-notices', 'wp-polyfill', 'wp-primitives', 'wp-rich-text', 'wp-server-side-render', 'wp-url', 'wp-viewport', 'wp-wordcount'), 'version' => 'a4ddebb6f88e9e6d0426288f757fc839'), 'element.js' => array('dependencies' => array('lodash', 'react', 'react-dom', 'wp-escape-html', 'wp-polyfill'), 'version' => '00b4616d8d8e497fed5efc56819a4f99'), 'escape-html.js' => array('dependencies' => array('wp-polyfill'), 'version' => '11a9ed20aa0e5b49a24e416455d2311e'), 'format-library.js' => array('dependencies' => array('lodash', 'wp-block-editor', 'wp-components', 'wp-data', 'wp-dom', 'wp-element', 'wp-html-entities', 'wp-i18n', 'wp-keycodes', 'wp-polyfill', 'wp-primitives', 'wp-rich-text', 'wp-url'), 'version' => 'c72d237e7ca6aae466e7be3d79adfdd0'), 'hooks.js' => array('dependencies' => array('wp-polyfill'), 'version' => 'd3b8b40265078ab4bf9a60e4be8c928e'), 'html-entities.js' => array('dependencies' => array('wp-polyfill'), 'version' => '5f0f2fc8f6cde41ab343549aa0b50183'), 'i18n.js' => array('dependencies' => array('wp-polyfill'), 'version' => 'd3a3d3210bfb2ca7ef6bdba31c413250'), 'is-shallow-equal.js' => array('dependencies' => array('wp-polyfill'), 'version' => 'b2327d0572e72da49f9e26cc3a53de34'), 'keyboard-shortcuts.js' => array('dependencies' => array('lodash', 'wp-compose', 'wp-data', 'wp-keycodes', 'wp-polyfill'), 'version' => '7439dba3888f064b1174470f8c90d789'), 'keycodes.js' => array('dependencies' => array('lodash', 'wp-i18n', 'wp-polyfill'), 'version' => '576dca936dbe58003338160c3c5c3ca0'), 'list-reusable-blocks.js' => array('dependencies' => array('lodash', 'wp-api-fetch', 'wp-components', 'wp-compose', 'wp-element', 'wp-i18n', 'wp-polyfill'), 'version' => '8306352fbf4b1a62d2f99b32e4bcf9db'), 'media-utils.js' => array('dependencies' => array('lodash', 'wp-api-fetch', 'wp-blob', 'wp-element', 'wp-i18n', 'wp-polyfill'), 'version' => '6ef5a273eb0a450c2545eaaedb952c9c'), 'notices.js' => array('dependencies' => array('lodash', 'wp-data', 'wp-polyfill'), 'version' => '59e33e2f12d7375fbb59033060e3755c'), 'nux.js' => array('dependencies' => array('lodash', 'wp-components', 'wp-compose', 'wp-data', 'wp-deprecated', 'wp-element', 'wp-i18n', 'wp-polyfill', 'wp-primitives'), 'version' => 'c6425ef5696f295c5bebd738baf59fdf'), 'plugins.js' => array('dependencies' => array('lodash', 'wp-compose', 'wp-element', 'wp-hooks', 'wp-polyfill', 'wp-primitives'), 'version' => 'bf7037b87ab1db074706fa8565c2ba5f'), 'primitives.js' => array('dependencies' => array('wp-element', 'wp-polyfill'), 'version' => '47f496b20b6a5895b5ca5f40e85b0e62'), 'priority-queue.js' => array('dependencies' => array('wp-polyfill'), 'version' => '61fc9b8c45afe763799612e733d04e5d'), 'redux-routine.js' => array('dependencies' => array('lodash', 'wp-polyfill'), 'version' => 'caae3879a1870fe55d4d6c91882b4aec'), 'rich-text.js' => array('dependencies' => array('lodash', 'wp-data', 'wp-deprecated', 'wp-element', 'wp-escape-html', 'wp-keycodes', 'wp-polyfill'), 'version' => '895e31f6df6a5ec8a679b93d71bd2175'), 'server-side-render.js' => array('dependencies' => array('lodash', 'wp-api-fetch', 'wp-components', 'wp-data', 'wp-deprecated', 'wp-element', 'wp-i18n', 'wp-polyfill', 'wp-url'), 'version' => '356e2911f80386235087cbc8a30b0b79'), 'shortcode.js' => array('dependencies' => array('lodash', 'wp-polyfill'), 'version' => '0f4a8551daa990e80114889793034ff6'), 'token-list.js' => array('dependencies' => array('lodash', 'wp-polyfill'), 'version' => '8c1de0af2850ea512bf7ee4ea8a6af09'), 'url.js' => array('dependencies' => array('lodash', 'wp-polyfill'), 'version' => '5cfad922551470f0d04552a83d5e7eb4'), 'viewport.js' => array('dependencies' => array('lodash', 'wp-compose', 'wp-data', 'wp-element', 'wp-polyfill'), 'version' => 'de07809632bb717b3bef9fb526a17f20'), 'warning.js' => array('dependencies' => array('wp-polyfill'), 'version' => '202ac16e99afe7c33c257b248625a947'), 'wordcount.js' => array('dependencies' => array('lodash', 'wp-polyfill'), 'version' => 'ababa914c8610cc872482756daceab10'));
\ No newline at end of file
+ array('dependencies' => array('wp-dom-ready', 'wp-i18n', 'wp-polyfill'), 'version' => '6d98587879c8c19080b1e3a855e946be'), 'annotations.js' => array('dependencies' => array('lodash', 'wp-data', 'wp-hooks', 'wp-i18n', 'wp-polyfill', 'wp-rich-text'), 'version' => '6f5dba93cfcc859a12384d6500bbdb6a'), 'api-fetch.js' => array('dependencies' => array('wp-i18n', 'wp-polyfill', 'wp-url'), 'version' => 'd38d8020fb8b03594fb705059bd02d08'), 'autop.js' => array('dependencies' => array('wp-polyfill'), 'version' => 'e3a7061e1087f5cf077a68aeaf0ea714'), 'blob.js' => array('dependencies' => array('wp-polyfill'), 'version' => '27195f29e36179999f6e1fa7d1f079b3'), 'block-directory.js' => array('dependencies' => array('lodash', 'wp-api-fetch', 'wp-block-editor', 'wp-blocks', 'wp-components', 'wp-compose', 'wp-data', 'wp-data-controls', 'wp-edit-post', 'wp-element', 'wp-hooks', 'wp-html-entities', 'wp-i18n', 'wp-notices', 'wp-plugins', 'wp-polyfill', 'wp-primitives'), 'version' => '48cdfe01e7d468f66bf1f31667b83ac6'), 'block-editor.js' => array('dependencies' => array('lodash', 'react', 'react-dom', 'wp-a11y', 'wp-blob', 'wp-blocks', 'wp-components', 'wp-compose', 'wp-data', 'wp-deprecated', 'wp-dom', 'wp-element', 'wp-hooks', 'wp-html-entities', 'wp-i18n', 'wp-is-shallow-equal', 'wp-keyboard-shortcuts', 'wp-keycodes', 'wp-notices', 'wp-polyfill', 'wp-primitives', 'wp-rich-text', 'wp-shortcode', 'wp-token-list', 'wp-url', 'wp-viewport', 'wp-warning', 'wp-wordcount'), 'version' => '503c5ca4a090284e4d04aa16b31dfdec'), 'block-library.js' => array('dependencies' => array('lodash', 'moment', 'react', 'wp-api-fetch', 'wp-autop', 'wp-blob', 'wp-block-editor', 'wp-blocks', 'wp-components', 'wp-compose', 'wp-core-data', 'wp-data', 'wp-date', 'wp-deprecated', 'wp-dom', 'wp-element', 'wp-i18n', 'wp-keycodes', 'wp-notices', 'wp-polyfill', 'wp-primitives', 'wp-rich-text', 'wp-server-side-render', 'wp-url', 'wp-viewport'), 'version' => '133abb15521407efb634785f4714d68f'), 'block-serialization-default-parser.js' => array('dependencies' => array('wp-polyfill'), 'version' => '27585bbfe083d705c915c21bf47047df'), 'blocks.js' => array('dependencies' => array('lodash', 'wp-autop', 'wp-blob', 'wp-block-serialization-default-parser', 'wp-compose', 'wp-data', 'wp-deprecated', 'wp-dom', 'wp-element', 'wp-hooks', 'wp-html-entities', 'wp-i18n', 'wp-is-shallow-equal', 'wp-polyfill', 'wp-primitives', 'wp-shortcode'), 'version' => '7ba861a0b2e8f76fc7a1f4c7a3a59de1'), 'components.js' => array('dependencies' => array('lodash', 'moment', 'react', 'react-dom', 'wp-a11y', 'wp-compose', 'wp-date', 'wp-deprecated', 'wp-dom', 'wp-element', 'wp-hooks', 'wp-i18n', 'wp-is-shallow-equal', 'wp-keycodes', 'wp-polyfill', 'wp-primitives', 'wp-rich-text', 'wp-warning'), 'version' => 'ba2a54427259bb4eacacaa1d1d22e922'), 'compose.js' => array('dependencies' => array('lodash', 'react', 'wp-element', 'wp-is-shallow-equal', 'wp-polyfill', 'wp-priority-queue'), 'version' => '980168910efaf01ea313952dd1af8fbd'), 'core-data.js' => array('dependencies' => array('lodash', 'wp-blocks', 'wp-data', 'wp-data-controls', 'wp-deprecated', 'wp-element', 'wp-i18n', 'wp-is-shallow-equal', 'wp-polyfill', 'wp-url'), 'version' => '7159cab2b2ec3870267c3549595864a6'), 'data.js' => array('dependencies' => array('lodash', 'react', 'wp-compose', 'wp-deprecated', 'wp-element', 'wp-is-shallow-equal', 'wp-polyfill', 'wp-priority-queue', 'wp-redux-routine'), 'version' => '18c22155dc4bce9be5fb2d823c738095'), 'data-controls.js' => array('dependencies' => array('wp-api-fetch', 'wp-data', 'wp-polyfill'), 'version' => '6cb5c91c1427296ea7f52a6349c6f179'), 'date.js' => array('dependencies' => array('moment', 'wp-polyfill'), 'version' => 'c9122f4b8a25a58b47487ad81ddf4742'), 'deprecated.js' => array('dependencies' => array('wp-hooks', 'wp-polyfill'), 'version' => '26aefabb46263ab5dac6d7f6c63b664c'), 'dom.js' => array('dependencies' => array('lodash', 'wp-polyfill'), 'version' => 'eedd920647fd959208dfb7bbf9caeadb'), 'dom-ready.js' => array('dependencies' => array('wp-polyfill'), 'version' => 'a6586b64552c9c6924b8093e9ef4f74e'), 'edit-post.js' => array('dependencies' => array('lodash', 'wp-a11y', 'wp-api-fetch', 'wp-block-editor', 'wp-block-library', 'wp-blocks', 'wp-components', 'wp-compose', 'wp-core-data', 'wp-data', 'wp-data-controls', 'wp-editor', 'wp-element', 'wp-hooks', 'wp-i18n', 'wp-keyboard-shortcuts', 'wp-keycodes', 'wp-media-utils', 'wp-notices', 'wp-plugins', 'wp-polyfill', 'wp-primitives', 'wp-url', 'wp-viewport', 'wp-warning'), 'version' => '4b53e762718f21b20f2b2c6875f540cc'), 'edit-widgets.js' => array('dependencies' => array('lodash', 'react', 'wp-api-fetch', 'wp-block-editor', 'wp-block-library', 'wp-blocks', 'wp-components', 'wp-compose', 'wp-core-data', 'wp-data', 'wp-element', 'wp-hooks', 'wp-i18n', 'wp-keyboard-shortcuts', 'wp-keycodes', 'wp-media-utils', 'wp-notices', 'wp-plugins', 'wp-polyfill', 'wp-primitives', 'wp-url'), 'version' => '32d56e34f79bc97aec1c441672e5d7f6'), 'editor.js' => array('dependencies' => array('lodash', 'react', 'wp-api-fetch', 'wp-autop', 'wp-block-editor', 'wp-blocks', 'wp-components', 'wp-compose', 'wp-core-data', 'wp-data', 'wp-data-controls', 'wp-date', 'wp-deprecated', 'wp-element', 'wp-hooks', 'wp-html-entities', 'wp-i18n', 'wp-keyboard-shortcuts', 'wp-keycodes', 'wp-media-utils', 'wp-notices', 'wp-polyfill', 'wp-primitives', 'wp-rich-text', 'wp-server-side-render', 'wp-url', 'wp-viewport', 'wp-wordcount'), 'version' => 'a4ddebb6f88e9e6d0426288f757fc839'), 'element.js' => array('dependencies' => array('lodash', 'react', 'react-dom', 'wp-escape-html', 'wp-polyfill'), 'version' => '00b4616d8d8e497fed5efc56819a4f99'), 'escape-html.js' => array('dependencies' => array('wp-polyfill'), 'version' => '11a9ed20aa0e5b49a24e416455d2311e'), 'format-library.js' => array('dependencies' => array('lodash', 'wp-block-editor', 'wp-components', 'wp-data', 'wp-dom', 'wp-element', 'wp-html-entities', 'wp-i18n', 'wp-keycodes', 'wp-polyfill', 'wp-primitives', 'wp-rich-text', 'wp-url'), 'version' => 'c72d237e7ca6aae466e7be3d79adfdd0'), 'hooks.js' => array('dependencies' => array('wp-polyfill'), 'version' => 'd3b8b40265078ab4bf9a60e4be8c928e'), 'html-entities.js' => array('dependencies' => array('wp-polyfill'), 'version' => '5f0f2fc8f6cde41ab343549aa0b50183'), 'i18n.js' => array('dependencies' => array('wp-polyfill'), 'version' => 'd3a3d3210bfb2ca7ef6bdba31c413250'), 'is-shallow-equal.js' => array('dependencies' => array('wp-polyfill'), 'version' => 'b2327d0572e72da49f9e26cc3a53de34'), 'keyboard-shortcuts.js' => array('dependencies' => array('lodash', 'wp-compose', 'wp-data', 'wp-keycodes', 'wp-polyfill'), 'version' => '7439dba3888f064b1174470f8c90d789'), 'keycodes.js' => array('dependencies' => array('lodash', 'wp-i18n', 'wp-polyfill'), 'version' => '576dca936dbe58003338160c3c5c3ca0'), 'list-reusable-blocks.js' => array('dependencies' => array('lodash', 'wp-api-fetch', 'wp-components', 'wp-compose', 'wp-element', 'wp-i18n', 'wp-polyfill'), 'version' => '8306352fbf4b1a62d2f99b32e4bcf9db'), 'media-utils.js' => array('dependencies' => array('lodash', 'wp-api-fetch', 'wp-blob', 'wp-element', 'wp-i18n', 'wp-polyfill'), 'version' => '6ef5a273eb0a450c2545eaaedb952c9c'), 'notices.js' => array('dependencies' => array('lodash', 'wp-data', 'wp-polyfill'), 'version' => '59e33e2f12d7375fbb59033060e3755c'), 'nux.js' => array('dependencies' => array('lodash', 'wp-components', 'wp-compose', 'wp-data', 'wp-deprecated', 'wp-element', 'wp-i18n', 'wp-polyfill', 'wp-primitives'), 'version' => 'c6425ef5696f295c5bebd738baf59fdf'), 'plugins.js' => array('dependencies' => array('lodash', 'wp-compose', 'wp-element', 'wp-hooks', 'wp-polyfill', 'wp-primitives'), 'version' => 'bf7037b87ab1db074706fa8565c2ba5f'), 'primitives.js' => array('dependencies' => array('wp-element', 'wp-polyfill'), 'version' => '47f496b20b6a5895b5ca5f40e85b0e62'), 'priority-queue.js' => array('dependencies' => array('wp-polyfill'), 'version' => '61fc9b8c45afe763799612e733d04e5d'), 'redux-routine.js' => array('dependencies' => array('lodash', 'wp-polyfill'), 'version' => 'caae3879a1870fe55d4d6c91882b4aec'), 'rich-text.js' => array('dependencies' => array('lodash', 'wp-data', 'wp-deprecated', 'wp-element', 'wp-escape-html', 'wp-keycodes', 'wp-polyfill'), 'version' => '895e31f6df6a5ec8a679b93d71bd2175'), 'server-side-render.js' => array('dependencies' => array('lodash', 'wp-api-fetch', 'wp-components', 'wp-data', 'wp-deprecated', 'wp-element', 'wp-i18n', 'wp-polyfill', 'wp-url'), 'version' => '356e2911f80386235087cbc8a30b0b79'), 'shortcode.js' => array('dependencies' => array('lodash', 'wp-polyfill'), 'version' => '0f4a8551daa990e80114889793034ff6'), 'token-list.js' => array('dependencies' => array('lodash', 'wp-polyfill'), 'version' => '8c1de0af2850ea512bf7ee4ea8a6af09'), 'url.js' => array('dependencies' => array('lodash', 'wp-polyfill'), 'version' => '5cfad922551470f0d04552a83d5e7eb4'), 'viewport.js' => array('dependencies' => array('lodash', 'wp-compose', 'wp-data', 'wp-element', 'wp-polyfill'), 'version' => 'de07809632bb717b3bef9fb526a17f20'), 'warning.js' => array('dependencies' => array('wp-polyfill'), 'version' => '202ac16e99afe7c33c257b248625a947'), 'wordcount.js' => array('dependencies' => array('lodash', 'wp-polyfill'), 'version' => 'ababa914c8610cc872482756daceab10'));
\ No newline at end of file
diff --git a/src/wp-includes/blocks/index.php b/src/wp-includes/blocks/index.php
index d4482718c1cbc..d4b603a300f23 100644
--- a/src/wp-includes/blocks/index.php
+++ b/src/wp-includes/blocks/index.php
@@ -12,6 +12,7 @@
require ABSPATH . WPINC . '/blocks/categories.php';
require ABSPATH . WPINC . '/blocks/latest-comments.php';
require ABSPATH . WPINC . '/blocks/latest-posts.php';
+require ABSPATH . WPINC . '/blocks/legacy-widget.php';
require ABSPATH . WPINC . '/blocks/rss.php';
require ABSPATH . WPINC . '/blocks/search.php';
require ABSPATH . WPINC . '/blocks/shortcode.php';
@@ -56,6 +57,7 @@ function register_core_block_types_from_metadata() {
'text-columns',
'verse',
'video',
+ 'widget-area',
);
foreach ( $block_folders as $block_folder ) {
diff --git a/src/wp-includes/blocks/legacy-widget.php b/src/wp-includes/blocks/legacy-widget.php
new file mode 100644
index 0000000000000..7f209f3f4fd4b
--- /dev/null
+++ b/src/wp-includes/blocks/legacy-widget.php
@@ -0,0 +1,100 @@
+ 'render_block_core_legacy_widget',
+ )
+ );
+}
+
+/**
+ * Renders the `core/legacy-widget` block on server.
+ *
+ * @param array $attributes The block attributes.
+ *
+ * @return string Returns the post content with the legacy widget added.
+ * @see WP_Widget
+ */
+function render_block_core_legacy_widget( $attributes ) {
+ global $wp_widget_factory, $wp_registered_sidebars;
+
+ if ( isset( $attributes['widgetId'] ) ) {
+ return __( 'Rendering legacy widget block using widgetId is unsupported.', 'gutenberg' );
+ }
+ $widget_id = - 1;
+
+ if ( ! isset( $attributes['sidebarId'] ) || ! isset( $wp_registered_sidebars[ $attributes['sidebarId'] ] ) ) {
+ return '';
+ }
+ $sidebar_id = $attributes['sidebarId'];
+
+ if ( ! isset( $attributes['widgetClass'] ) || ! isset( $wp_widget_factory->widgets[ $attributes['widgetClass'] ] ) ) {
+ return '';
+ }
+ $widget_class = $attributes['widgetClass'];
+ $widget_obj = $wp_widget_factory->widgets[ $widget_class ];
+
+ $instance = isset( $attributes['instance'] ) ? $attributes['instance'] : null;
+
+ $widget_params = array_merge(
+ array(
+ 'classname' => array(),
+ ),
+ $widget_obj->widget_options
+ );
+
+ /** This filter is documented in wp-includes/widgets/widgets.php */
+ do_action( 'dynamic_sidebar_before', $sidebar_id, true );
+ $sidebar = $wp_registered_sidebars[ $sidebar_id ];
+
+ $params = array_merge(
+ array(
+ array_merge(
+ $sidebar,
+ array(
+ 'widget_id' => $widget_id,
+ 'widget_name' => $widget_obj->name,
+ )
+ ),
+ ),
+ array(
+ $instance,
+ )
+ );
+
+ // Substitute HTML `id` and `class` attributes into `before_widget`.
+ $classname_ = '';
+ foreach ( (array) $widget_params['classname'] as $cn ) {
+ if ( is_string( $cn ) ) {
+ $classname_ .= '_' . $cn;
+ } elseif ( is_object( $cn ) ) {
+ $classname_ .= '_' . get_class( $cn );
+ }
+ }
+ $classname_ = ltrim( $classname_, '_' );
+ $params[0]['before_widget'] = sprintf( $params[0]['before_widget'], $widget_id, $classname_ );
+
+ /** This filter is documented in wp-includes/widgets/widgets.php */
+ $params = apply_filters( 'dynamic_sidebar_params', $params );
+
+ /** This filter is documented in wp-includes/widgets/widgets.php */
+ do_action( 'dynamic_sidebar', $widget_params );
+
+ ob_start();
+ $widget_obj->_set( - 1 );
+ call_user_func_array( array( $widget_obj, 'widget' ), $params );
+
+ return ob_get_clean();
+}
+
+add_action( 'init', 'register_block_core_legacy_widget' );
diff --git a/src/wp-includes/blocks/legacy-widget/block.json b/src/wp-includes/blocks/legacy-widget/block.json
new file mode 100644
index 0000000000000..b54a64b4090d3
--- /dev/null
+++ b/src/wp-includes/blocks/legacy-widget/block.json
@@ -0,0 +1,25 @@
+{
+ "name": "core/legacy-widget",
+ "category": "widgets",
+ "attributes": {
+ "widgetClass": {
+ "type": "string"
+ },
+ "referenceWidgetName": {
+ "type": "string"
+ },
+ "idBase": {
+ "type": "string"
+ },
+ "number": {
+ "type": "number"
+ },
+ "instance": {
+ "type": "object"
+ }
+ },
+ "supports": {
+ "html": false,
+ "customClassName": false
+ }
+}
diff --git a/src/wp-includes/blocks/widget-area/block.json b/src/wp-includes/blocks/widget-area/block.json
new file mode 100644
index 0000000000000..fd3c912908bbe
--- /dev/null
+++ b/src/wp-includes/blocks/widget-area/block.json
@@ -0,0 +1,18 @@
+{
+ "name": "core/widget-area",
+ "category": "widgets",
+ "attributes": {
+ "id": {
+ "type": "string"
+ },
+ "name": {
+ "type": "string"
+ }
+ },
+ "supports": {
+ "html": false,
+ "inserter": false,
+ "customClassName": false,
+ "__experimentalToolbar": false
+ }
+}
diff --git a/src/wp-includes/class-wp-customize-widgets.php b/src/wp-includes/class-wp-customize-widgets.php
index ed9bbe3dfd5e7..0842aec2564d1 100644
--- a/src/wp-includes/class-wp-customize-widgets.php
+++ b/src/wp-includes/class-wp-customize-widgets.php
@@ -788,6 +788,7 @@ public function enqueue_scripts() {
/* translators: %d: The number of widgets found. */
'widgetsFound' => __( 'Number of widgets found: %d' ),
'noWidgetsFound' => __( 'No widgets found.' ),
+ 'editBtnLabel' => __( 'Edit' ),
),
'tpl' => array(
'widgetReorderNav' => $widget_reorder_nav_tpl,
diff --git a/src/wp-includes/default-widgets.php b/src/wp-includes/default-widgets.php
index 173573a3dd588..f8f3c4d141535 100644
--- a/src/wp-includes/default-widgets.php
+++ b/src/wp-includes/default-widgets.php
@@ -63,3 +63,6 @@
/** WP_Widget_Custom_HTML class */
require_once ABSPATH . WPINC . '/widgets/class-wp-widget-custom-html.php';
+
+/** WP_Widget_Block class */
+require_once ABSPATH . WPINC . '/widgets/class-wp-widget-block.php';
diff --git a/src/wp-includes/rest-api.php b/src/wp-includes/rest-api.php
index ed62943309383..264cc2a98a04a 100644
--- a/src/wp-includes/rest-api.php
+++ b/src/wp-includes/rest-api.php
@@ -321,6 +321,14 @@ function create_initial_rest_routes() {
$site_health = WP_Site_Health::get_instance();
$controller = new WP_REST_Site_Health_Controller( $site_health );
$controller->register_routes();
+
+ // Sidebars.
+ $controller = new WP_REST_Sidebars_Controller();
+ $controller->register_routes();
+
+ // Widget Utils.
+ $controller = new WP_REST_Widget_Utils_Controller();
+ $controller->register_routes();
}
/**
diff --git a/src/wp-includes/rest-api/endpoints/class-wp-rest-sidebars-controller.php b/src/wp-includes/rest-api/endpoints/class-wp-rest-sidebars-controller.php
new file mode 100644
index 0000000000000..16b827e70ad17
--- /dev/null
+++ b/src/wp-includes/rest-api/endpoints/class-wp-rest-sidebars-controller.php
@@ -0,0 +1,635 @@
+.
+ *
+ * @author Martin Pettersson
+ * @copyright 2015 Martin Pettersson
+ * @license GPLv2
+ * @link https://github.com/martin-pettersson/wp-rest-api-sidebars
+ * @package gutenberg
+ */
+
+/**
+ * Class Sidebars_Controller
+ *
+ * @package WP_API_Sidebars\Controllers
+ */
+class WP_REST_Sidebars_Controller extends WP_REST_Controller {
+
+ /**
+ * Plugins controller constructor.
+ *
+ * @since 5.5.0
+ */
+ public function __construct() {
+ $this->namespace = '__experimental';
+ $this->rest_base = 'sidebars';
+ }
+
+ /**
+ * Registers the controllers routes.
+ *
+ * @return void
+ */
+ public function register_routes() {
+ // Lists all sidebars.
+ register_rest_route(
+ $this->namespace,
+ '/' . $this->rest_base,
+ array(
+ array(
+ 'methods' => WP_REST_Server::READABLE,
+ 'callback' => array( $this, 'get_items' ),
+ 'permission_callback' => array( $this, 'permissions_check' ),
+ ),
+ 'schema' => array( $this, 'get_public_item_schema' ),
+ )
+ );
+
+ // Lists/updates a single sidebar based on the given id.
+ register_rest_route(
+ $this->namespace,
+ '/' . $this->rest_base . '/(?P[\w-]+)',
+ array(
+ array(
+ 'methods' => WP_REST_Server::READABLE,
+ 'callback' => array( $this, 'get_item' ),
+ 'permission_callback' => array( $this, 'permissions_check' ),
+ 'args' => array(
+ 'id' => array(
+ 'description' => __( 'The id of a registered sidebar', 'gutenberg' ),
+ 'type' => 'string',
+ 'validate_callback' => function ( $id ) {
+ return self::get_sidebar( $id )[0];
+ },
+ ),
+ ),
+ ),
+ array(
+ 'methods' => WP_REST_Server::EDITABLE,
+ 'callback' => array( $this, 'update_item' ),
+ 'permission_callback' => array( $this, 'permissions_check' ),
+ 'args' => $this->get_endpoint_args_for_item_schema( WP_REST_Server::EDITABLE ),
+ ),
+ 'schema' => array( $this, 'get_public_item_schema' ),
+ )
+ );
+ }
+
+ /**
+ * Checks if the user has permissions to make the request.
+ *
+ * @return true|WP_Error True if the request has read access, WP_Error object otherwise.
+ * @since 5.6.0
+ * @access public
+ */
+ public function permissions_check() {
+ // Verify if the current user has edit_theme_options capability.
+ // This capability is required to access the widgets screen.
+ if ( ! current_user_can( 'edit_theme_options' ) ) {
+ return new WP_Error(
+ 'widgets_cannot_access',
+ __( 'Sorry, you are not allowed to access widgets on this site.', 'gutenberg' ),
+ array(
+ 'status' => rest_authorization_required_code(),
+ )
+ );
+ }
+
+ return true;
+ }
+
+
+ /**
+ * Updates the sidebar.
+ *
+ * @param WP_REST_Request $request The request instance.
+ *
+ * @return WP_REST_Response
+ * @global array $wp_registered_widget_updates
+ */
+ public function update_item( $request ) {
+ global $wp_registered_widget_updates, $wp_registered_widgets;
+ $sidebar_id = $request['id'];
+ $input_widgets = $request['widgets'];
+
+ // Initialize $numbers.
+ $numbers = array();
+ foreach ( $wp_registered_widget_updates as $id_base => $control ) {
+ if ( is_array( $control['callback'] ) ) {
+ $numbers[ $id_base ] = $control['callback'][0]->number + 1;
+ }
+ }
+
+ // Create and update widgets.
+ $sidebar_widgets_ids = array();
+ foreach ( $input_widgets as $input_widget ) {
+ ob_start();
+ if ( isset( $input_widget['id_base'] ) && isset( $wp_registered_widget_updates[ $input_widget['id_base'] ] ) ) {
+ // Class-based widget.
+ $update_control = $wp_registered_widget_updates[ $input_widget['id_base'] ];
+ if ( ! isset( $input_widget['id'] ) ) {
+ $number = $numbers[ $input_widget['id_base'] ] ++;
+ $id = $input_widget['id_base'] . '-' . $number;
+
+ $input_widget['id'] = $id;
+ $input_widget['number'] = $number;
+ }
+ $field = 'widget-' . $input_widget['id_base'];
+ $number = $input_widget['number'];
+ $_POST = $input_widget;
+ $_POST[ $field ][ $number ] = wp_slash( $input_widget['settings'] );
+ call_user_func( $update_control['callback'] );
+ $update_control['callback'][0]->updated = false;
+
+ // Just because we saved new widget doesn't mean it was added to $wp_registered_widgets.
+ // Let's make sure it's there so that it's included in the response.
+ if ( ! isset( $wp_registered_widgets[ $input_widget['id'] ] ) ) {
+ $first_widget_id = substr( $input_widget['id'], 0, strrpos( $input_widget['id'], '-' ) ) . '-1';
+
+ if ( isset( $wp_registered_widgets[ $first_widget_id ] ) ) {
+ $wp_registered_widgets[ $input_widget['id'] ] = $wp_registered_widgets[ $first_widget_id ];
+ $widget_class = get_class( $update_control['callback'][0] );
+ $new_object = new $widget_class(
+ $input_widget['id_base'],
+ $input_widget['name'],
+ $input_widget['settings']
+ );
+ $new_object->_register();
+ $wp_registered_widgets[ $input_widget['id'] ]['callback'][0] = $new_object;
+ }
+ }
+ } else {
+ $registered_widget_id = null;
+ if ( isset( $wp_registered_widget_updates[ $input_widget['id'] ] ) ) {
+ $registered_widget_id = $input_widget['id'];
+ } else {
+ $numberless_id = substr( $input_widget['id'], 0, strrpos( $input_widget['id'], '-' ) );
+ if ( isset( $wp_registered_widget_updates[ $numberless_id ] ) ) {
+ $registered_widget_id = $numberless_id;
+ }
+ }
+
+ if ( $registered_widget_id ) {
+ // Old-style widget.
+ $update_control = $wp_registered_widget_updates[ $registered_widget_id ];
+ $_POST = wp_slash( $input_widget['settings'] );
+ call_user_func( $update_control['callback'] );
+ }
+ }
+ ob_end_clean();
+
+ $sidebar_widgets_ids[] = $input_widget['id'];
+ }
+
+ // Update sidebar to only consist of the widgets we just processed.
+ $sidebars = wp_get_sidebars_widgets();
+ $sidebars[ $sidebar_id ] = $sidebar_widgets_ids;
+ wp_set_sidebars_widgets( $sidebars );
+
+ $request = new WP_REST_Request( 'GET' );
+ $request->set_param( 'id', $sidebar_id );
+
+ return $this->get_item( $request );
+ }
+
+ /**
+ * Returns a list of sidebars (active or inactive)
+ *
+ * @param WP_REST_Request $request The request instance.
+ *
+ * @return WP_REST_Response
+ * @global array $wp_registered_sidebars
+ */
+ public function get_items( $request ) {
+ $data = array();
+ foreach ( (array) wp_get_sidebars_widgets() as $id => $widgets ) {
+ $sidebar = self::get_sidebar( $id )[1];
+
+ $data[] = $this->prepare_item_for_response( $sidebar, $request )->get_data();
+ }
+
+ return rest_ensure_response( $data );
+ }
+
+ /**
+ * Returns the given sidebar
+ *
+ * @param WP_REST_Request $request The request instance.
+ *
+ * @return WP_REST_Response
+ */
+ public function get_item( $request ) {
+ $sidebar = self::get_sidebar( $request['id'] )[1];
+
+ return $this->prepare_item_for_response( $sidebar, $request );
+ }
+
+ /**
+ * Returns a sidebar for the given id or null if not found
+ *
+ * Note: The id can be either an index, the id or the name of a sidebar
+ *
+ * @param string|int $id ID of the sidebar.
+ *
+ * @return array|null
+ * @global array $wp_registered_sidebars
+ */
+ public static function get_sidebar( $id ) {
+ global $wp_registered_sidebars;
+
+ if ( is_int( $id ) ) {
+ $id = 'sidebar-' . $id;
+ } else {
+ $id = sanitize_title( $id );
+
+ foreach ( (array) $wp_registered_sidebars as $key => $sidebar ) {
+ if ( sanitize_title( $sidebar['name'] ) === $id ) {
+ return array( true, $sidebar );
+ }
+ }
+ }
+
+ foreach ( (array) $wp_registered_sidebars as $key => $sidebar ) {
+ if ( $key === $id ) {
+ return array( true, $sidebar );
+ }
+ }
+
+ return array( false, array( 'id' => $id ) );
+ }
+
+ /**
+ * Returns a list of widgets for the given sidebar id
+ *
+ * @param string $sidebar_id ID of the sidebar.
+ * @param WP_REST_Request $request Request object.
+ *
+ * @return array
+ * @global array $wp_registered_widgets
+ * @global array $wp_registered_sidebars
+ */
+ public static function get_widgets( $sidebar_id, $request ) {
+ global $wp_registered_widgets, $wp_registered_sidebars, $wp_registered_widget_controls;
+
+ $widgets = array();
+ $sidebars_widgets = (array) wp_get_sidebars_widgets();
+ $registered_sidebar = isset( $wp_registered_sidebars[ $sidebar_id ] )
+ ? $wp_registered_sidebars[ $sidebar_id ]
+ : (
+ 'wp_inactive_widgets' === $sidebar_id ? array() : null
+ );
+
+ if ( null !== $registered_sidebar && isset( $sidebars_widgets[ $sidebar_id ] ) ) {
+ foreach ( $sidebars_widgets[ $sidebar_id ] as $widget_id ) {
+ // Just to be sure.
+ if ( isset( $wp_registered_widgets[ $widget_id ] ) ) {
+ $widget = $wp_registered_widgets[ $widget_id ];
+
+ // Get the widget output.
+ if ( is_callable( $widget['callback'] ) ) {
+ // @note: everything up to ob_start is taken from the dynamic_sidebar function.
+ $widget_parameters = array_merge(
+ array(
+ array_merge(
+ $registered_sidebar,
+ array(
+ 'widget_id' => $widget_id,
+ 'widget_name' => $widget['name'],
+ )
+ ),
+ ),
+ (array) $widget['params']
+ );
+
+ $classname = '';
+ foreach ( (array) $widget['classname'] as $cn ) {
+ if ( is_string( $cn ) ) {
+ $classname .= '_' . $cn;
+ } elseif ( is_object( $cn ) ) {
+ $classname .= '_' . get_class( $cn );
+ }
+ }
+ $classname = ltrim( $classname, '_' );
+ if ( isset( $widget_parameters[0]['before_widget'] ) ) {
+ $widget_parameters[0]['before_widget'] = sprintf(
+ $widget_parameters[0]['before_widget'],
+ $widget_id,
+ $classname
+ );
+ }
+
+ ob_start();
+ call_user_func_array( $widget['callback'], $widget_parameters );
+ $widget['rendered'] = trim( ob_get_clean() );
+ }
+
+ if ( is_array( $widget['callback'] ) && isset( $widget['callback'][0] ) ) {
+ $instance = $widget['callback'][0];
+ $widget['widget_class'] = get_class( $instance );
+ $widget['settings'] = static::get_sidebar_widget_instance(
+ $registered_sidebar,
+ $widget_id
+ );
+ $widget['number'] = (int) $widget['params'][0]['number'];
+ $widget['id_base'] = $instance->id_base;
+ }
+
+ if ( 'edit' === $request['context'] && isset( $wp_registered_widget_controls[ $widget_id ]['callback'] ) ) {
+ $control = $wp_registered_widget_controls[ $widget_id ];
+ $arguments = array();
+ if ( ! empty( $widget['number'] ) ) {
+ $arguments[0] = array( 'number' => $widget['number'] );
+ }
+ ob_start();
+ call_user_func_array( $control['callback'], $arguments );
+ $widget['rendered_form'] = trim( ob_get_clean() );
+ }
+
+ unset( $widget['params'] );
+ unset( $widget['callback'] );
+
+ $widgets[] = $widget;
+ }
+ }
+ }
+
+ return $widgets;
+ }
+
+ /**
+ * Prepare a single sidebar output for response
+ *
+ * @param array $raw_sidebar Sidebar instance.
+ * @param WP_REST_Request $request Request object.
+ *
+ * @return WP_REST_Response $data
+ */
+ public function prepare_item_for_response( $raw_sidebar, $request ) {
+ global $wp_registered_sidebars;
+
+ $id = $raw_sidebar['id'];
+ $sidebar = array( 'id' => $id );
+
+ if ( isset( $wp_registered_sidebars[ $id ] ) ) {
+ $registered_sidebar = $wp_registered_sidebars[ $id ];
+
+ $sidebar['status'] = 'active';
+ $sidebar['name'] = isset( $registered_sidebar['name'] ) ? $registered_sidebar['name'] : '';
+ $sidebar['description'] = isset( $registered_sidebar['description'] ) ? $registered_sidebar['description'] : '';
+ } else {
+ $sidebar['status'] = 'inactive';
+ }
+
+ if ( 'wp_inactive_widgets' === $sidebar['id'] && empty( $sidebar['name'] ) ) {
+ $sidebar['name'] = __( 'Inactive widgets', 'gutenberg' );
+ }
+
+ $fields = $this->get_fields_for_response( $request );
+ if ( rest_is_field_included( 'widgets', $fields ) ) {
+ $sidebar['widgets'] = self::get_widgets( $sidebar['id'], $request );
+ }
+
+ $schema = $this->get_item_schema();
+ $data = array();
+ foreach ( $schema['properties'] as $property_id => $property ) {
+ if ( isset( $sidebar[ $property_id ] ) && gettype( $sidebar[ $property_id ] ) === $property['type'] ) {
+ $data[ $property_id ] = $sidebar[ $property_id ];
+ } elseif ( isset( $property['default'] ) ) {
+ $data[ $property_id ] = $property['default'];
+ }
+ }
+
+ foreach ( $sidebar['widgets'] as $widget_id => $widget ) {
+ $widget_data = array();
+ foreach ( $schema['properties']['widgets']['items']['properties'] as $property_id => $property ) {
+ if ( isset( $widget[ $property_id ] ) && gettype( $widget[ $property_id ] ) === $property['type'] ) {
+ $widget_data[ $property_id ] = $widget[ $property_id ];
+ } elseif ( 'settings' === $property_id && isset( $widget[ $property_id ] ) && 'array' === gettype( $widget[ $property_id ] ) ) {
+ $widget_data[ $property_id ] = $widget['settings'];
+ } elseif ( isset( $property['default'] ) ) {
+ $widget_data[ $property_id ] = $property['default'];
+ }
+ }
+ $data['widgets'][ $widget_id ] = $widget_data;
+ }
+
+ $response = rest_ensure_response( $data );
+
+ /**
+ * Filters a sidebar location returned from the REST API.
+ *
+ * Allows modification of the menu location data right before it is
+ * returned.
+ *
+ * @param WP_REST_Response $response The response object.
+ * @param object $sidebar The original status object.
+ * @param WP_REST_Request $request Request used to generate the response.
+ */
+ return apply_filters( 'rest_prepare_sidebar', $response, $sidebar, $request );
+ }
+
+ /**
+ * Retrieves the block type' schema, conforming to JSON Schema.
+ *
+ * @return array Item schema data.
+ */
+ public function get_item_schema() {
+ if ( $this->schema ) {
+ return $this->add_additional_fields_schema( $this->schema );
+ }
+
+ $schema = array(
+ '$schema' => 'http://json-schema.org/draft-04/schema#',
+ 'title' => 'sidebar',
+ 'type' => 'object',
+ 'properties' => array(
+ 'id' => array(
+ 'description' => __( 'ID of sidebar.', 'gutenberg' ),
+ 'type' => 'string',
+ 'default' => '',
+ 'context' => array( 'embed', 'view', 'edit' ),
+ 'readonly' => true,
+ ),
+ 'name' => array(
+ 'description' => __( 'Unique name identifying the sidebar.', 'gutenberg' ),
+ 'type' => 'string',
+ 'default' => '',
+ 'context' => array( 'embed', 'view', 'edit' ),
+ 'readonly' => true,
+ ),
+ 'description' => array(
+ 'description' => __( 'Description of sidebar.', 'gutenberg' ),
+ 'type' => 'string',
+ 'default' => '',
+ 'context' => array( 'embed', 'view', 'edit' ),
+ 'readonly' => true,
+ ),
+ 'status' => array(
+ 'description' => __( 'Status of sidebar.', 'gutenberg' ),
+ 'type' => 'string',
+ 'enum' => array( 'active', 'inactive' ),
+ 'default' => '',
+ 'context' => array( 'embed', 'view', 'edit' ),
+ 'readonly' => true,
+ ),
+ 'widgets' => array(
+ 'description' => __( 'Nested widgets.', 'gutenberg' ),
+ 'type' => 'array',
+ 'items' => array(
+ 'type' => 'object',
+ 'properties' => array(
+ 'id' => array(
+ 'description' => __( 'Unique identifier for the widget.', 'gutenberg' ),
+ 'type' => 'string',
+ 'context' => array( 'view', 'edit', 'embed' ),
+ ),
+ 'id_base' => array(
+ 'description' => __( 'Type of widget for the object.', 'gutenberg' ),
+ 'type' => 'string',
+ 'context' => array( 'view', 'edit', 'embed' ),
+ ),
+ 'widget_class' => array(
+ 'description' => __( 'Class name of the widget implementation.', 'gutenberg' ),
+ 'type' => 'string',
+ 'context' => array( 'view', 'edit', 'embed' ),
+ ),
+ 'name' => array(
+ 'description' => __( 'Name of the widget.', 'gutenberg' ),
+ 'type' => 'string',
+ 'context' => array( 'view', 'edit', 'embed' ),
+ ),
+ 'description' => array(
+ 'description' => __( 'Description of the widget.', 'gutenberg' ),
+ 'type' => 'string',
+ 'context' => array( 'view', 'edit', 'embed' ),
+ ),
+ 'number' => array(
+ 'description' => __( 'Number of the widget.', 'gutenberg' ),
+ 'type' => 'integer',
+ 'context' => array( 'view', 'edit', 'embed' ),
+ ),
+ 'rendered' => array(
+ 'description' => __( 'HTML representation of the widget.', 'gutenberg' ),
+ 'type' => 'string',
+ 'context' => array( 'view', 'embed' ),
+ 'readonly' => true,
+ ),
+ 'rendered_form' => array(
+ 'description' => __( 'HTML representation of the widget admin form.', 'gutenberg' ),
+ 'type' => 'string',
+ 'context' => array( 'edit' ),
+ 'readonly' => true,
+ ),
+ 'settings' => array(
+ 'description' => __( 'Settings of the widget.', 'gutenberg' ),
+ 'type' => 'object',
+ 'context' => array( 'view', 'edit', 'embed' ),
+ 'default' => array(),
+ ),
+ ),
+ ),
+ 'default' => array(),
+ 'context' => array( 'embed', 'view', 'edit' ),
+ ),
+ ),
+ );
+
+ $this->schema = $schema;
+
+ return $this->add_additional_fields_schema( $this->schema );
+ }
+
+ /**
+ * Retrieves a widget instance.
+ *
+ * @param array $sidebar sidebar data available at $wp_registered_sidebars.
+ * @param string $id Identifier of the widget instance.
+ *
+ * @return array Array containing the widget instance.
+ * @since 5.7.0
+ */
+ public static function get_sidebar_widget_instance( $sidebar, $id ) {
+ list( $object, $number, $name ) = static::get_widget_info( $id );
+ if ( ! $object ) {
+ return array();
+ }
+
+ $object->_set( $number );
+
+ $instances = $object->get_settings();
+ $instance = $instances[ $number ];
+
+ $args = array_merge(
+ $sidebar,
+ array(
+ 'widget_id' => $id,
+ 'widget_name' => $name,
+ )
+ );
+
+ /**
+ * Filters the settings for a particular widget instance.
+ *
+ * Returning false will effectively short-circuit display of the widget.
+ *
+ * @param array $instance The current widget instance's settings.
+ * @param WP_Widget $this The current widget instance.
+ * @param array $args An array of default widget arguments.
+ *
+ * @since 2.8.0
+ */
+ $instance = apply_filters( 'widget_display_callback', $instance, $object, $args );
+
+ if ( false === $instance ) {
+ return array();
+ }
+
+ return $instance;
+ }
+
+ /**
+ * Given a widget id returns an array containing information about the widget.
+ *
+ * @param string $widget_id Identifier of the widget.
+ *
+ * @return array Array containing the the widget object, the number, and the name.
+ * @since 5.7.0
+ */
+ private static function get_widget_info( $widget_id ) {
+ global $wp_registered_widgets;
+
+ if (
+ ! isset( $wp_registered_widgets[ $widget_id ]['callback'][0] ) ||
+ ! isset( $wp_registered_widgets[ $widget_id ]['params'][0]['number'] ) ||
+ ! isset( $wp_registered_widgets[ $widget_id ]['name'] ) ||
+ ! ( $wp_registered_widgets[ $widget_id ]['callback'][0] instanceof WP_Widget )
+ ) {
+ return array( null, null, null );
+ }
+
+ $object = $wp_registered_widgets[ $widget_id ]['callback'][0];
+ $number = $wp_registered_widgets[ $widget_id ]['params'][0]['number'];
+ $name = $wp_registered_widgets[ $widget_id ]['name'];
+
+ return array( $object, $number, $name );
+ }
+
+}
diff --git a/src/wp-includes/rest-api/endpoints/class-wp-rest-widget-utils-controller.php b/src/wp-includes/rest-api/endpoints/class-wp-rest-widget-utils-controller.php
new file mode 100644
index 0000000000000..ac02218d48333
--- /dev/null
+++ b/src/wp-includes/rest-api/endpoints/class-wp-rest-widget-utils-controller.php
@@ -0,0 +1,160 @@
+namespace = '__experimental';
+ $this->rest_base = 'widget-utils';
+ }
+
+ /**
+ * Registers the necessary REST API route.
+ *
+ * @access public
+ */
+ public function register_routes() {
+ register_rest_route(
+ $this->namespace,
+ '/' . $this->rest_base . '/form/(?P[^/]*)/',
+ array(
+ 'args' => array(
+ 'widget_class' => array(
+ 'description' => __( 'Class name of the widget.', 'gutenberg' ),
+ 'type' => 'string',
+ 'required' => true,
+ 'validate_callback' => array( $this, 'is_valid_widget' ),
+ ),
+ 'instance' => array(
+ 'description' => __( 'Current widget instance', 'gutenberg' ),
+ 'type' => 'object',
+ 'default' => array(),
+ ),
+ ),
+ array(
+ 'methods' => WP_REST_Server::EDITABLE,
+ 'permission_callback' => array( $this, 'permissions_check' ),
+ 'callback' => array( $this, 'compute_widget_form' ),
+ ),
+ )
+ );
+ }
+
+ /**
+ * Checks if the user has permissions to make the request.
+ *
+ * @return true|WP_Error True if the request has read access, WP_Error object otherwise.
+ * @since 5.2.0
+ * @access public
+ */
+ public function permissions_check() {
+ // Verify if the current user has edit_theme_options capability.
+ // This capability is required to access the widgets screen.
+ if ( ! current_user_can( 'edit_theme_options' ) ) {
+ return new WP_Error(
+ 'widgets_cannot_access',
+ __( 'Sorry, you are not allowed to access widgets on this site.', 'gutenberg' ),
+ array(
+ 'status' => rest_authorization_required_code(),
+ )
+ );
+ }
+
+ return true;
+ }
+
+ /**
+ * Checks if the widget being referenced is valid.
+ *
+ * @param string $widget_class Name of the class the widget references.
+ *
+ * @return boolean| True if the widget being referenced exists and false otherwise.
+ * @since 5.2.0
+ * @access public
+ */
+ public function is_valid_widget( $widget_class ) {
+ $widget_class = urldecode( $widget_class );
+ global $wp_widget_factory;
+ if ( ! $widget_class ) {
+ return false;
+ }
+
+ return isset( $wp_widget_factory->widgets[ $widget_class ] ) &&
+ ( $wp_widget_factory->widgets[ $widget_class ] instanceof WP_Widget );
+ }
+
+ /**
+ * Returns the new widget instance and the form that represents it.
+ *
+ * @param WP_REST_Request $request Full details about the request.
+ *
+ * @return WP_REST_Response|WP_Error Response object on success, or WP_Error object on failure.
+ * @since 5.7.0
+ * @access public
+ */
+ public function compute_widget_form( $request ) {
+ $widget_class = urldecode( $request->get_param( 'widget_class' ) );
+ $instance = $request->get_param( 'instance' );
+
+ global $wp_widget_factory;
+ $widget_obj = $wp_widget_factory->widgets[ $widget_class ];
+
+ $widget_obj->_set( -1 );
+ ob_start();
+
+ $instance = apply_filters( 'widget_form_callback', $instance, $widget_obj );
+
+ $return = null;
+ if ( false !== $instance ) {
+ $return = $widget_obj->form( $instance );
+
+ /**
+ * Fires at the end of the widget control form.
+ *
+ * Use this hook to add extra fields to the widget form. The hook
+ * is only fired if the value passed to the 'widget_form_callback'
+ * hook is not false.
+ *
+ * Note: If the widget has no form, the text echoed from the default
+ * form method can be hidden using CSS.
+ *
+ * @param WP_Widget $widget_obj The widget instance (passed by reference).
+ * @param null $return Return null if new fields are added.
+ * @param array $instance An array of the widget's settings.
+ *
+ * @since 5.2.0
+ */
+ do_action_ref_array( 'in_widget_form', array( &$widget_obj, &$return, $instance ) );
+ }
+ $form = ob_get_clean();
+
+ return rest_ensure_response(
+ array(
+ 'instance' => $instance,
+ 'form' => $form,
+ )
+ );
+ }
+
+}
+/**
+ * End: Include for phase 2
+ */
diff --git a/src/wp-includes/script-loader.php b/src/wp-includes/script-loader.php
index be95eee4cb953..e368c08aa7e09 100644
--- a/src/wp-includes/script-loader.php
+++ b/src/wp-includes/script-loader.php
@@ -1514,6 +1514,12 @@ function wp_default_styles( $styles ) {
'format-library' => array(),
'list-reusable-blocks' => array( 'wp-components' ),
'nux' => array( 'wp-components' ),
+ 'edit-widgets' => array(
+ 'wp-components',
+ 'wp-block-editor',
+ 'wp-edit-blocks',
+ 'wp-block-library',
+ ),
);
foreach ( $package_styles as $package => $dependencies ) {
diff --git a/src/wp-includes/widgets.php b/src/wp-includes/widgets.php
index 0d176687fb080..449e0c45da1b8 100644
--- a/src/wp-includes/widgets.php
+++ b/src/wp-includes/widgets.php
@@ -291,6 +291,7 @@ function register_sidebar( $args = array() ) {
$wp_registered_sidebars[ $sidebar['id'] ] = $sidebar;
add_theme_support( 'widgets' );
+ add_theme_support( 'widgets-block-editor' );
/**
* Fires once a sidebar has been registered.
@@ -1765,6 +1766,8 @@ function wp_widgets_init() {
register_widget( 'WP_Widget_Custom_HTML' );
+ register_widget( 'WP_Widget_Block' );
+
/**
* Fires after all default WordPress widgets have been registered.
*
diff --git a/src/wp-includes/widgets/class-wp-widget-block.php b/src/wp-includes/widgets/class-wp-widget-block.php
new file mode 100644
index 0000000000000..5a31cfec8ffd6
--- /dev/null
+++ b/src/wp-includes/widgets/class-wp-widget-block.php
@@ -0,0 +1,118 @@
+ '',
+ );
+
+ /**
+ * Sets up a new Block widget instance.
+ *
+ * @since 5.6.0
+ */
+ public function __construct() {
+ $widget_ops = array(
+ 'classname' => 'widget_block',
+ 'description' => __( 'A block.' ),
+ 'customize_selective_refresh' => true,
+ );
+ $control_ops = array(
+ 'width' => 400,
+ 'height' => 350,
+ );
+ parent::__construct( 'block', __( 'Block' ), $widget_ops, $control_ops );
+ add_action( 'is_wide_widget_in_customizer', array( $this, 'set_is_wide_widget_in_customizer' ), 10, 2 );
+ }
+
+ /**
+ * Outputs the content for the current Block widget instance.
+ *
+ * @since 5.6.0
+ *
+ * @param array $args Display arguments including 'before_title', 'after_title', 'before_widget', and 'after_widget'.
+ * @param array $instance Settings for the current Block widget instance.
+ *
+ * @global WP_Post $post Global post object.
+ */
+ public function widget( $args, $instance ) {
+ echo $args['before_widget'];
+ echo do_blocks( $instance['content'] );
+ echo $args['after_widget'];
+ }
+
+ /**
+ * Handles updating settings for the current Block widget instance.
+
+ * @since 5.6.0
+ *
+ * @param array $new_instance New settings for this instance as input by the user via WP_Widget::form().
+ * @param array $old_instance Old settings for this instance.
+ *
+ * @return array Settings to save or bool false to cancel saving.
+ */
+ public function update( $new_instance, $old_instance ) {
+ $instance = array_merge( $this->default_instance, $old_instance );
+ $instance['content'] = $new_instance['content'];
+
+ return $instance;
+ }
+
+ /**
+ * Outputs the Block widget settings form.
+ *
+ * @since 5.6.0
+ *
+ * @param array $instance Current instance.
+ * @return string Default return is 'noform'.
+ */
+ public function form( $instance ) {
+ $instance = wp_parse_args( (array) $instance, $this->default_instance );
+ echo do_blocks( $instance['content'] );
+ $textarea_id = $this->get_field_id( 'content' );
+ ?>
+
+
+ [\\w-]+)": {
+ "namespace": "__experimental",
+ "methods": [
+ "GET",
+ "POST",
+ "PUT",
+ "PATCH"
+ ],
+ "endpoints": [
+ {
+ "methods": [
+ "GET"
+ ],
+ "args": {
+ "id": {
+ "required": false,
+ "description": "The id of a registered sidebar",
+ "type": "string"
+ }
+ }
+ },
+ {
+ "methods": [
+ "POST",
+ "PUT",
+ "PATCH"
+ ],
+ "args": {
+ "widgets": {
+ "required": false,
+ "description": "Nested widgets.",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "properties": {
+ "id": {
+ "description": "Unique identifier for the widget.",
+ "type": "string",
+ "context": [
+ "view",
+ "edit",
+ "embed"
+ ]
+ },
+ "id_base": {
+ "description": "Type of widget for the object.",
+ "type": "string",
+ "context": [
+ "view",
+ "edit",
+ "embed"
+ ]
+ },
+ "widget_class": {
+ "description": "Class name of the widget implementation.",
+ "type": "string",
+ "context": [
+ "view",
+ "edit",
+ "embed"
+ ]
+ },
+ "name": {
+ "description": "Name of the widget.",
+ "type": "string",
+ "context": [
+ "view",
+ "edit",
+ "embed"
+ ]
+ },
+ "description": {
+ "description": "Description of the widget.",
+ "type": "string",
+ "context": [
+ "view",
+ "edit",
+ "embed"
+ ]
+ },
+ "number": {
+ "description": "Number of the widget.",
+ "type": "integer",
+ "context": [
+ "view",
+ "edit",
+ "embed"
+ ]
+ },
+ "rendered": {
+ "description": "HTML representation of the widget.",
+ "type": "string",
+ "context": [
+ "view",
+ "embed"
+ ],
+ "readonly": true
+ },
+ "rendered_form": {
+ "description": "HTML representation of the widget admin form.",
+ "type": "string",
+ "context": [
+ "edit"
+ ],
+ "readonly": true
+ },
+ "settings": {
+ "description": "Settings of the widget.",
+ "type": "object",
+ "context": [
+ "view",
+ "edit",
+ "embed"
+ ],
+ "default": []
+ }
+ }
+ }
+ }
+ }
+ }
+ ]
+ },
+ "/__experimental/widget-utils/form/(?P[^/]*)": {
+ "namespace": "__experimental",
+ "methods": [
+ "POST",
+ "PUT",
+ "PATCH"
+ ],
+ "endpoints": [
+ {
+ "methods": [
+ "POST",
+ "PUT",
+ "PATCH"
+ ],
+ "args": {
+ "widget_class": {
+ "required": true,
+ "description": "Class name of the widget.",
+ "type": "string"
+ },
+ "instance": {
+ "required": false,
+ "default": [],
+ "description": "Current widget instance",
+ "type": "object"
+ }
+ }
+ }
+ ]
}
}
};
diff --git a/tools/webpack/packages.js b/tools/webpack/packages.js
index d3665571a64ca..99d040188140c 100644
--- a/tools/webpack/packages.js
+++ b/tools/webpack/packages.js
@@ -154,12 +154,15 @@ module.exports = function( env = { environment: 'production', watch: false, buil
files[ `block-library/src/${ blockName }/index.php` ] = `wp-includes/blocks/${ blockName }.php`;
return files;
} , {} ),
+ 'edit-widgets/src/blocks/legacy-widget/index.php': 'wp-includes/blocks/legacy-widget.php',
};
const blockMetadataFiles = {
...blockFolders.reduce( ( files, blockName ) => {
files[ `block-library/src/${ blockName }/block.json` ] = `wp-includes/blocks/${ blockName }/block.json`;
return files;
} , {} ),
+ 'edit-widgets/src/blocks/legacy-widget/block.json': 'wp-includes/blocks/legacy-widget/block.json',
+ 'edit-widgets/src/blocks/widget-area/block.json': 'wp-includes/blocks/widget-area/block.json',
};
const developmentCopies = mapVendorCopies( vendors, buildTarget );