import { useEffect } from '@wordpress/element';
import { getBlockType } from '@wordpress/blocks';
import hasNumericValue from '../utils/has-numeric-value';
import wasBlockJustInserted from '../utils/was-block-just-inserted';
import isBlockVersionLessThan from '../utils/check-block-version';
import { migrationPipe, updateBlockVersion, setIsDynamic } from './migrations/utils';
import migrateSpacing from './migrations/migrateSpacing';
import migrateBorders from './migrations/migrateBorders';
import migrateTypography from './migrations/migrateTypography';
import migrateSizing from './migrations/migrateSizing';
import { isEmpty } from 'lodash';
/**
* Add late-added attributes to the bgOptions object.
* This was to prevent an error where `selector` was undefined.
*
* @param {Object} attrs New attributes from previous migrations.
* @param {Object} existingAttrs Pre-existing block attributes.
* @param {string} mode The migration mode.
* @return {Object} Updated attributes.
* @since 1.1.2
*/
export function migrateBgSelectorOpacity( attrs, existingAttrs, mode ) {
if ( 'css' === mode ) {
return attrs;
}
if ( ! existingAttrs.bgOptions || ! Object.keys( existingAttrs.bgOptions ).length ) {
return attrs;
}
if ( 'undefined' === typeof existingAttrs.bgOptions.selector ) {
attrs = {
...attrs,
bgOptions: {
...existingAttrs.bgOptions,
...attrs.bgOptions,
selector: 'element',
},
};
}
if ( 'undefined' === typeof existingAttrs.bgOptions.opacity ) {
attrs = {
...attrs,
bgOptions: {
...existingAttrs.bgOptions,
...attrs.bgOptions,
opacity: 1,
},
};
}
return attrs;
}
/**
* Set our old defaults as static values.
*
* @param {Object} Props Function props.
* @param {number} Props.blockVersionLessThan The version blocks should be less than for this to run.
* @param {Object} Props.oldDefaults Old defaults that were changed and need to be added to attributes.
* @return {Object} Updated attributes.
* @since 1.4.0
*/
export function migrateOldContainerDefaults( { blockVersionLessThan, oldDefaults } ) {
return function( attrs, existingAttrs, mode ) {
if ( 'css' === mode ) {
return attrs;
}
if ( ! wasBlockJustInserted( existingAttrs ) && isBlockVersionLessThan( existingAttrs.blockVersion, blockVersionLessThan ) ) {
const useGlobalStyle = 'undefined' !== typeof existingAttrs.useGlobalStyle && existingAttrs.useGlobalStyle;
const items = [];
if ( ! useGlobalStyle ) {
items.push(
'paddingTop',
'paddingRight',
'paddingBottom',
'paddingLeft',
);
}
if ( existingAttrs.isGrid ) {
items.push(
'width',
'widthMobile',
);
}
if ( existingAttrs.gradient ) {
items.push(
'gradientDirection',
'gradientColorOne',
'gradientColorOneOpacity',
'gradientColorTwo',
'gradientColorTwoOpacity'
);
}
items.forEach( ( item ) => {
if ( ! hasNumericValue( existingAttrs[ item ] ) ) {
attrs[ item ] = oldDefaults[ item ];
}
} );
}
return attrs;
};
}
/**
* Set our inner z-index if we're using a gradient overlay or pseudo background.
*
* @param {Object} Props Function props.
* @param {number} Props.blockVersionLessThan The version blocks should be less than for this to run.
* @return {Object} Updated attributes.
* @since 1.4.0
*/
export function migrateContainerZIndex( { blockVersionLessThan } ) {
return function( attrs, existingAttrs, mode ) {
if ( 'css' === mode ) {
return attrs;
}
if ( ! wasBlockJustInserted( existingAttrs ) && isBlockVersionLessThan( existingAttrs.blockVersion, blockVersionLessThan ) ) {
let updateOldZindex =
existingAttrs.gradient && 'pseudo-element' === existingAttrs.gradientSelector &&
! hasNumericValue( existingAttrs.innerZindex );
if ( ! updateOldZindex ) {
updateOldZindex = !! existingAttrs.bgImage && 'undefined' !== typeof existingAttrs.bgOptions.selector && 'pseudo-element' === existingAttrs.bgOptions.selector;
}
if ( ! updateOldZindex ) {
updateOldZindex = 'undefined' !== typeof existingAttrs.useAdvBackgrounds && existingAttrs.useAdvBackgrounds;
}
if ( updateOldZindex ) {
attrs.innerZindex = 1;
}
}
return attrs;
};
}
/**
* Set our useInnerContainer attribute on old Containers.
*
* @param {Object} Props Function props.
* @param {number} Props.blockVersionLessThan The version blocks should be less than for this to run.
* @return {Object} Updated attributes.
* @since 1.7.0
*/
export function migrateInnerContainer( { blockVersionLessThan } ) {
return function( attrs, existingAttrs, mode ) {
if ( 'css' === mode ) {
return attrs;
}
if ( ! wasBlockJustInserted( existingAttrs ) && isBlockVersionLessThan( existingAttrs.blockVersion, blockVersionLessThan ) ) {
attrs.useInnerContainer = true;
}
return attrs;
};
}
/**
* Migrate our flexBasis attributes to include their unit.
*
* @param {Object} Props Function props.
* @param {number} Props.blockVersionLessThan The version blocks should be less than for this to run.
* @return {Object} Updated attributes.
* @since 1.7.0
*/
export function migrateFlexBasis( { blockVersionLessThan } ) {
return function( attrs, existingAttrs, mode ) {
if ( 'css' === mode ) {
return attrs;
}
if ( ! wasBlockJustInserted( existingAttrs ) && isBlockVersionLessThan( existingAttrs.blockVersion, blockVersionLessThan ) ) {
[ '', 'Tablet', 'Mobile' ].forEach( ( device ) => {
if ( existingAttrs[ 'flexBasis' + device ] && ! isNaN( existingAttrs[ 'flexBasis' + device ] ) ) {
attrs[ 'flexBasis' + device ] = existingAttrs[ 'flexBasis' + device ] + existingAttrs.flexBasisUnit;
}
} );
}
return attrs;
};
}
export const currentBlockVersion = 4;
/**
* Migrate our Container attributes.
*
* @param {Object} Props Function props.
* @param {Object} Props.attributes The block attributes.
* @param {Object} Props.defaults The block defaults.
* @param {string} Props.mode The migration mode.
* @param {Object} Props.oldDefaults An object of old defaults keyed by version.
* @return {Object} Updated attributes.
* @since 1.8.0
*/
export function migrateContainerAttributes( { attributes, defaults, mode = '', oldDefaults = {} } ) {
return migrationPipe(
attributes,
[
setIsDynamic,
migrateBgSelectorOpacity,
migrateContainerZIndex( {
blockVersionLessThan: 2,
} ),
migrateOldContainerDefaults( {
blockVersionLessThan: 2,
oldDefaults: oldDefaults.v1_4_0,
} ),
migrateInnerContainer( {
blockVersionLessThan: 3,
} ),
migrateFlexBasis( {
blockVersionLessThan: 3,
} ),
migrateSizing( {
blockVersionLessThan: 3,
} ),
migrateSpacing( {
blockVersionLessThan: 4,
defaults,
attributesToMigrate: [
'paddingTop',
'paddingRight',
'paddingBottom',
'paddingLeft',
'marginTop',
'marginRight',
'marginBottom',
'marginLeft',
],
} ),
migrateBorders( {
blockVersionLessThan: 4,
defaults,
attributesToMigrate: [
'borderSizeTop',
'borderSizeRight',
'borderSizeBottom',
'borderSizeLeft',
'borderRadiusTopRight',
'borderRadiusBottomRight',
'borderRadiusBottomLeft',
'borderRadiusTopLeft',
],
} ),
migrateTypography( {
blockVersionLessThan: 4,
defaults,
attributesToMigrate: [
'fontFamily',
'fontSize',
'fontWeight',
'textTransform',
'alignment',
],
} ),
updateBlockVersion( currentBlockVersion ),
],
mode
);
}
export default ( WrappedComponent ) => {
return ( props ) => {
const {
attributes,
setAttributes,
} = props;
useEffect( () => {
const newAttributes = migrateContainerAttributes( {
attributes,
defaults: getBlockType( 'generateblocks/container' )?.attributes,
oldDefaults: {
v1_4_0: generateBlocksLegacyDefaults.v_1_4_0.container,
},
} );
if ( ! isEmpty( newAttributes ) ) {
setAttributes( newAttributes );
}
}, [] );
return ( <WrappedComponent { ...props } /> );
};
};