// @ts-check /** * WordPress dependencies */ import { serialize, parse, createBlock } from '@wordpress/blocks' import { addWidgetIdToBlock } from '@wordpress/widgets' /** * External dependencies */ import { omit } from 'lodash' /** * Convert settingId to widgetId. * * @param {string} settingId The setting id. * @return {string} The widget id. */ export function settingIdToWidgetId(settingId) { const matches = settingId.match(/^widget_(.+)(?:\[(\d+)\])$/) if (matches) { const idBase = matches[1] const number = parseInt(matches[2], 10) return `${idBase}-${number}` } return settingId } /** * Transform a block to a customizable widget. * * @param {WPBlock} block The block to be transformed from. * @param {Object} existingWidget The widget to be extended from. * @return {Object} The transformed widget. */ export function blockToWidget(block, existingWidget = null) { let widget const isValidLegacyWidgetBlock = block.name === 'core/legacy-widget' && (block.attributes.id || block.attributes.instance) if (isValidLegacyWidgetBlock) { if (block.attributes.id) { // Widget that does not extend WP_Widget. widget = { id: block.attributes.id, } } else { const { encoded, hash, raw, ...rest } = block.attributes.instance // Widget that extends WP_Widget. widget = { idBase: block.attributes.idBase, instance: { ...existingWidget?.instance, // Required only for the customizer. is_widget_customizer_js_value: true, encoded_serialized_instance: encoded, instance_hash_key: hash, raw_instance: raw, ...rest, }, } } } else { const instance = { content: serialize(block), } widget = { idBase: 'block', widgetClass: 'WP_Widget_Block', instance: { raw_instance: instance, }, } } return { ...omit(existingWidget, ['form', 'rendered']), ...widget, } } /** * Transform a widget to a block. * * @param {Object} widget The widget to be transformed from. * @param {string} widget.id The widget id. * @param {string} widget.idBase The id base of the widget. * @param {number} widget.number The number/index of the widget. * @param {Object} widget.instance The instance of the widget. * @return {WPBlock} The transformed block. */ export function widgetToBlock({ id, idBase, number, instance }) { let block const { encoded_serialized_instance: encoded, instance_hash_key: hash, raw_instance: raw, ...rest } = instance if (idBase === 'block') { const parsedBlocks = parse(raw.content) block = parsedBlocks.length ? parsedBlocks[0] : createBlock('core/paragraph', {}) } else if (number) { // Widget that extends WP_Widget. block = createBlock('core/legacy-widget', { idBase, instance: { encoded, hash, raw, ...rest, }, }) } else { // Widget that does not extend WP_Widget. block = createBlock('core/legacy-widget', { id, }) } return addWidgetIdToBlock(block, id) }