Skip to content
Merged

Dev #997

Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
15 commits
Select commit Hold shift + click to select a range
6169c36
fix: improve category handling in WordPress service and update UI com…
aishwarya-cstk Mar 5, 2026
9453164
Merge branch 'dev' of https://github.com/contentstack/migration-v2 in…
aishwarya-cstk Mar 5, 2026
54318ed
feat: implement block name resolution for media blocks
aishwarya-cstk Mar 5, 2026
0b29233
feat: enhance createSchema and ContentMapper to support duplicate blo…
aishwarya-cstk Mar 10, 2026
ec2bbd9
refactor: streamline schemaMapper function by removing unnecessary br…
aishwarya-cstk Mar 11, 2026
3af2480
Merge branch 'dev' of https://github.com/contentstack/migration-v2 in…
aishwarya-cstk Mar 11, 2026
d4161cb
refactor: remove redundant file writing logic in WordPress service an…
aishwarya-cstk Mar 11, 2026
f6a6e0b
Merge branch 'dev' of https://github.com/contentstack/migration-v2 in…
aishwarya-cstk Mar 11, 2026
0746b4a
Merge branch 'dev' into feature/wordpress
umeshmore45 Mar 11, 2026
390fa54
refactor: resolved PR comments ( optional chaining)
aishwarya-cstk Mar 11, 2026
b1bd41b
Merge branch 'dev' of https://github.com/contentstack/migration-v2 in…
aishwarya-cstk Mar 11, 2026
ca63c99
Merge branch 'feature/wordpress' of https://github.com/contentstack/m…
aishwarya-cstk Mar 11, 2026
a5e9e92
fix: update schemaMapper to correctly handle button UIDs and inner bl…
aishwarya-cstk Mar 11, 2026
8286ac1
test: add unit tests for schemaMapper functions in WordPress migration
aishwarya-cstk Mar 11, 2026
f3a32cc
Merge pull request #991 from contentstack/feature/wordpress
umeshmore45 Mar 11, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
80 changes: 57 additions & 23 deletions api/src/services/wordpress.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -124,7 +124,7 @@ function getLastUid(uid : string) {
return uid?.split?.('.')?.[uid?.split?.('.')?.length - 1];
}

async function createSchema(fields: any, blockJson : any, title: string, uid: string, assetData: any) {
async function createSchema(fields: any, blockJson : any, title: string, uid: string, assetData: any, duplicateBlockMappings?: Record<string, string>) {
const schema : any = {
title: title,
uid: uid,
Expand Down Expand Up @@ -162,16 +162,37 @@ async function createSchema(fields: any, blockJson : any, title: string, uid: st
const blockName = (block?.attrs?.metadata?.name?.toLowerCase() || getFieldName(block?.blockName?.toLowerCase()));

// Find which modular block child this block matches
const matchingChildField = fields.find((childField: any) => {
let matchingChildField = fields.find((childField: any) => {
const fieldName = childField?.otherCmsField?.toLowerCase() ;

return (childField?.contentstackFieldType !== 'modular_blocks_child') && (blockName === fieldName)
});

const matchingModularBlockChild = modularBlockChildren.find((childField: any) => {
let matchingModularBlockChild = modularBlockChildren.find((childField: any) => {
const fieldName = childField?.otherCmsField?.toLowerCase() ;
return blockName === fieldName
});

// Fallback: if no direct match, check duplicate block mappings
if (!matchingModularBlockChild && duplicateBlockMappings) {
const mappedName = duplicateBlockMappings[blockName];

if (mappedName) {

matchingModularBlockChild = modularBlockChildren.find((childField: any) => {
const fieldName = childField?.otherCmsField?.toLowerCase();
return mappedName === fieldName;
});

//if (!matchingChildField) {
matchingChildField = fields.find((childField: any) => {
const fieldName = childField?.otherCmsField?.toLowerCase();
return (childField?.contentstackFieldType !== 'modular_blocks_child') && (mappedName === fieldName);
});

// }
}
}

//if (matchingChildField) {
// Process innerBlocks (children) if they exist
Expand All @@ -186,12 +207,13 @@ async function createSchema(fields: any, blockJson : any, title: string, uid: st
const childField = fields.find((f: any) => {
const fUid = f?.contentstackFieldUid || '';
const fOtherCmsField = f?.otherCmsType?.toLowerCase();
const childBlockName = (child?.attrs?.metadata?.name?.toLowerCase() || getFieldName(child?.blockName?.toLowerCase()));
// Check if this field belongs to the modular_blocks_child and matches the block name
const childBlockName = matchingChildField ? matchingChildField?.otherCmsField?.toLowerCase() : (child?.attrs?.metadata?.name?.toLowerCase() || getFieldName(child?.blockName?.toLowerCase()));
const childKey = getLastUid(f?.contentstackFieldUid);
const alreadyPopulated = childrenObject[childKey] !== undefined && childrenObject[childKey] !== null;
return fUid.startsWith(childFieldUid + '.') &&
(fOtherCmsField === childBlockName) && !childrenObject[getLastUid(f?.contentstackFieldUid)]?.length;
(fOtherCmsField === childBlockName) && (!alreadyPopulated || f?.advanced?.multiple === true);
});

if (childField) {
const childKey = getLastUid(childField?.contentstackFieldUid);

Expand All @@ -218,6 +240,7 @@ async function createSchema(fields: any, blockJson : any, title: string, uid: st
childrenObject[childKey] = [formattedChild];
}
} else {

formattedChild && (childrenObject[childKey] = formattedChild);
}
}
Expand All @@ -228,7 +251,13 @@ async function createSchema(fields: any, blockJson : any, title: string, uid: st
});

// Add the block to the modular blocks array with the child field's UID as the key
Object.keys(childrenObject).length > 0 && modularBlocksArray.push({[getLastUid(matchingModularBlockChild?.contentstackFieldUid)] : childrenObject });
if (Object?.keys(childrenObject)?.length > 0) {
modularBlocksArray.push({[getLastUid(matchingModularBlockChild?.contentstackFieldUid)] : childrenObject });
} else if (getLastUid(matchingModularBlockChild?.contentstackFieldUid) && matchingChildField) {
// Fallback: inner blocks didn't match child fields (e.g., duplicate-mapped block with different inner block types)
const formattedBlock = formatChildByType(block, matchingChildField, assetData);
formattedBlock && modularBlocksArray.push({[getLastUid(matchingModularBlockChild?.contentstackFieldUid)] : { [getLastUid(matchingChildField?.contentstackFieldUid)]: formattedBlock }});
}
} else if(getLastUid(matchingModularBlockChild?.contentstackFieldUid) && matchingChildField){
// Handle blocks with no inner blocks - format the block itself
const formattedBlock = formatChildByType(block, matchingChildField, assetData);
Expand Down Expand Up @@ -389,9 +418,17 @@ function formatChildByType(child: any, field: any, assetData: any) {
formatted = Boolean(child?.attrs[attrKey]);
break;

case 'json':
formatted = child?.blockName ? RteJsonConverter(formatted ?? child?.innerHTML) : RteJsonConverter(formatted ?? child);
case 'json': {
let htmlContent = formatted;
if (!htmlContent && child?.innerBlocks?.length > 0) {
htmlContent = collectHtmlFromInnerBlocks(child);
}
if (!htmlContent) {
htmlContent = child?.blockName ? child?.innerHTML : child;
}
formatted = RteJsonConverter(htmlContent);
break;
}

case 'html':
formatted = child?.blockName ? formatted ?? child?.innerHTML : `<p>${child}</p>`;
Expand Down Expand Up @@ -471,7 +508,7 @@ const extractTermsReference = (terms: any) => {
const termReference = termArray?.filter((term: any) => term?.attributes?.domain !== 'category');
return termReference;
}
async function saveEntry(fields: any, entry: any, file_path: string, assetData : any, categories: any, master_locale: string, destinationStackId: string, project: any, allTerms: any) {
async function saveEntry(fields: any, entry: any, file_path: string, assetData : any, categories: any, master_locale: string, destinationStackId: string, project: any, allTerms: any, duplicateBlockMappings?: Record<string, string>) {
const locale = getLocale(master_locale, project);
const mapperKeys = project?.mapperKeys || {};
const authorsCtName = mapperKeys[MIGRATION_DATA_CONFIG.AUTHORS_DIR_NAME] ? mapperKeys[MIGRATION_DATA_CONFIG.AUTHORS_DIR_NAME] : MIGRATION_DATA_CONFIG.AUTHORS_DIR_NAME;
Expand Down Expand Up @@ -544,10 +581,11 @@ async function saveEntry(fields: any, entry: any, file_path: string, assetData
const contentEncoded = $(xmlItem)?.find("content\\:encoded")?.text() || '';
const blocksJson = await setupWordPressBlocks(contentEncoded);
customLogger(project?.id, destinationStackId,'info', `Processed blocks for entry ${uid}`);
//await writeFileAsync(`${uid}.json`, JSON.stringify(blocksJson, null, 4), 4);



// Pass individual content to createSchema
entryData[uid] = await createSchema(fields, blocksJson, item?.title, uid, assetData);
entryData[uid] = await createSchema(fields, blocksJson, item?.title, uid, assetData, duplicateBlockMappings);
const categoryReference = extractCategoryReference(item?.['category']);
if (categoryReference?.length > 0) {
entryData[uid]['taxonomies'] = taxonomies;
Expand Down Expand Up @@ -586,6 +624,7 @@ async function createEntry(file_path: string, packagePath: string, destinationSt
const entriesJsonData = JSON.parse(Jsondata);
const entries = entriesJsonData?.rss?.channel?.["item"];
const categories = entriesJsonData?.rss?.channel?.["wp:category"];
const allCategories = Array?.isArray(categories) ? categories : (categories ? [categories] : []);

const authorsData = entriesJsonData?.rss?.channel?.["wp:author"];
const authors = Array?.isArray(authorsData) ? authorsData : [authorsData];
Expand Down Expand Up @@ -669,15 +708,8 @@ async function createEntry(file_path: string, packagePath: string, destinationSt
const entry = entries?.filter((entry: any) => {
return entry?.['wp:post_type']?.toLowerCase() === contentTypeUid;
});

// for (const [type, items] of Object.entries(groupedByType)) {
// if (Array.isArray(items) && items.length > 0) {
// await extractItems(items,file_path);
// } else {
// console.log(`No ${type} found to extract`);
// }
// }
const content = await saveEntry(contentType?.fieldMapping, entry,file_path, assetData, categories, master_locale, destinationStackId, project, allTerms) || {};

const content = await saveEntry(contentType?.fieldMapping, entry,file_path, assetData, allCategories, master_locale, destinationStackId, project, allTerms, contentType?.duplicateBlockMappings) || {};

const filePath = path.join(postFolderPath, `${locale}.json`);
await writeFileAsync(filePath, content, 4);
Expand All @@ -696,7 +728,9 @@ async function createTaxonomy(file_path: string, packagePath: string, destinatio

const Jsondata = await fs.promises.readFile(packagePath, "utf8");
const xmlData = await fs.promises.readFile(file_path, "utf8");
const categoriesJsonData = JSON.parse(Jsondata)?.rss?.channel?.["wp:category"] || JSON.parse(Jsondata)?.channel?.["wp:category"] || [];
const categoriesData = JSON.parse(Jsondata)?.rss?.channel?.["wp:category"] || JSON.parse(Jsondata)?.channel?.["wp:category"];
const categoriesJsonData = Array?.isArray(categoriesData) ? categoriesData : (categoriesData ? [categoriesData] : []);

if(categoriesJsonData?.length > 0){
const allTaxonomies : any = {}
for(const category of categoriesJsonData){
Expand Down
12 changes: 2 additions & 10 deletions ui/src/components/AdvancePropertise/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -805,7 +805,7 @@ const AdvancePropertise = (props: SchemaProps) => {
<Select
value={referencedTaxonomies}
isMulti={true}
isDisabled={isTaxonomiesLoading}
//isDisabled={isTaxonomiesLoading}
onChange={(selectedOptions: ContentTypeOption[]) => {

setReferencedTaxonomies(selectedOptions);
Expand Down Expand Up @@ -858,15 +858,7 @@ const AdvancePropertise = (props: SchemaProps) => {
width="350px"
maxMenuHeight={200}
/>
{isTaxonomiesLoading ? (
<InstructionText>
Loading taxonomies...
</InstructionText>
) : sourceTaxonomies?.length === 0 && destinationTaxonomies?.length === 0 ? (
<InstructionText>
No taxonomies found. Please upload source data or create taxonomies in your destination stack.
</InstructionText>
) : null}

</Field>
)}

Expand Down
Loading
Loading