Skip to content

Commit

Permalink
fix: join field with the target relationship inside localized array (#…
Browse files Browse the repository at this point in the history
  • Loading branch information
r1tsuu authored Jan 21, 2025
1 parent 46c1b37 commit 25a70ab
Show file tree
Hide file tree
Showing 8 changed files with 133 additions and 20 deletions.
10 changes: 9 additions & 1 deletion packages/db-mongodb/src/utilities/buildJoinAggregation.ts
Original file line number Diff line number Diff line change
Expand Up @@ -151,11 +151,19 @@ export const buildJoinAggregation = async ({
join.field.localized && adapter.payload.config.localization && locale ? `.${locale}` : ''
const as = `${versions ? `version.${join.joinPath}` : join.joinPath}${localeSuffix}`

let foreignField: string

if (join.getForeignPath) {
foreignField = `${join.getForeignPath({ locale })}${polymorphicSuffix}`
} else {
foreignField = `${join.field.on}${polymorphicSuffix}`
}

aggregate.push(
{
$lookup: {
as: `${as}.docs`,
foreignField: `${join.field.on}${localeSuffix}${polymorphicSuffix}`,
foreignField,
from: adapter.collections[slug].collection.name,
localField: versions ? 'parent' : '_id',
pipeline,
Expand Down
1 change: 1 addition & 0 deletions packages/payload/src/collections/config/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -517,6 +517,7 @@ export type SanitizedJoin = {
* The field configuration defining the join
*/
field: JoinField
getForeignPath?(args: { locale?: TypedLocale }): string
/**
* The path of the join field in dot notation
*/
Expand Down
25 changes: 24 additions & 1 deletion packages/payload/src/fields/config/sanitizeJoinField.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ export const sanitizeJoinField = ({
const pathSegments = field.on.split('.') // Split the schema path into segments
let currentSegmentIndex = 0

let localized = false
// Traverse fields and match based on the schema path
traverseFields({
callback: ({ field, next }) => {
Expand All @@ -48,6 +49,27 @@ export const sanitizeJoinField = ({
const currentSegment = pathSegments[currentSegmentIndex]
// match field on path segments
if ('name' in field && field.name === currentSegment) {
if ('localized' in field && field.localized) {
localized = true
const fieldIndex = currentSegmentIndex

join.getForeignPath = ({ locale }) => {
return pathSegments.reduce((acc, segment, index) => {
let result = `${acc}${segment}`

if (index === fieldIndex) {
result = `${result}.${locale}`
}

if (index !== pathSegments.length - 1) {
result = `${result}.`
}

return result
}, '')
}
}

// Check if this is the last segment in the path
if (
(currentSegmentIndex === pathSegments.length - 1 &&
Expand Down Expand Up @@ -78,7 +100,8 @@ export const sanitizeJoinField = ({
join.targetField = joinRelationship

// override the join field localized property to use whatever the relationship field has
field.localized = joinRelationship.localized
// or if it's nested to a localized array / blocks / tabs / group
field.localized = localized
// override the join field hasMany property to use whatever the relationship field has
field.hasMany = joinRelationship.hasMany

Expand Down
70 changes: 52 additions & 18 deletions packages/payload/src/utilities/traverseFields.ts
Original file line number Diff line number Diff line change
Expand Up @@ -109,15 +109,36 @@ export const traverseFields = ({
if (field.type === 'tabs' && 'tabs' in field) {
for (const tab of field.tabs) {
let tabRef = ref

if (skip) {
return false
}

if ('name' in tab && tab.name) {
if (!ref[tab.name] || typeof ref[tab.name] !== 'object') {
if (fillEmpty) {
ref[tab.name] = {}
if (tab.localized) {
ref[tab.name] = { en: {} }
} else {
ref[tab.name] = {}
}
} else {
continue
}
}

if (
callback &&
callback({
field: { ...tab, type: 'tab' },
next,
parentRef: currentParentRef,
ref: tabRef,
})
) {
return true
}

tabRef = tabRef[tab.name]

if (tab.localized) {
Expand All @@ -132,29 +153,34 @@ export const traverseFields = ({
})
}
}
continue
}
} else {
if (
callback &&
callback({
field: { ...tab, type: 'tab' },
next,
parentRef: currentParentRef,
ref: tabRef,
})
) {
return true
}
}

if (
callback &&
callback({
field: { ...tab, type: 'tab' },
next,
if (!tab.localized) {
traverseFields({
callback,
fields: tab.fields,
fillEmpty,
parentRef: currentParentRef,
ref: tabRef,
})
) {
return true
}

traverseFields({
callback,
fields: tab.fields,
fillEmpty,
parentRef: currentParentRef,
ref: tabRef,
})
if (skip) {
return false
}
}

return
Expand All @@ -166,10 +192,18 @@ export const traverseFields = ({
if (!ref[field.name]) {
if (fillEmpty) {
if (field.type === 'group') {
ref[field.name] = {}
} else if (field.type === 'array' || field.type === 'blocks') {
if (field.localized) {
ref[field.name] = {
en: {},
}
} else {
ref[field.name] = {}
}
} else if (field.type === 'array' || field.type === 'blocks') {
if (field.localized) {
ref[field.name] = {
en: [],
}
} else {
ref[field.name] = []
}
Expand Down
6 changes: 6 additions & 0 deletions test/joins/collections/Categories.ts
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,12 @@ export const Categories: CollectionConfig = {
collection: 'posts',
on: 'array.category',
},
{
name: 'localizedArrayPosts',
type: 'join',
collection: 'posts',
on: 'localizedArray.category',
},
{
name: 'blocksPosts',
type: 'join',
Expand Down
12 changes: 12 additions & 0 deletions test/joins/collections/Posts.ts
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,18 @@ export const Posts: CollectionConfig = {
},
],
},
{
name: 'localizedArray',
type: 'array',
localized: true,
fields: [
{
name: 'category',
type: 'relationship',
relationTo: categoriesSlug,
},
],
},
{
name: 'blocks',
type: 'blocks',
Expand Down
11 changes: 11 additions & 0 deletions test/joins/int.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,7 @@ describe('Joins Field', () => {
camelCaseCategory: category.id,
},
array: [{ category: category.id }],
localizedArray: [{ category: category.id }],
blocks: [{ blockType: 'block', category: category.id }],
})
}
Expand Down Expand Up @@ -214,6 +215,16 @@ describe('Joins Field', () => {
expect(categoryWithPosts.arrayPosts.docs).toBeDefined()
})

it('should populate joins with localized array relationships', async () => {
const categoryWithPosts = await payload.findByID({
id: category.id,
collection: categoriesSlug,
})

expect(categoryWithPosts.localizedArrayPosts.docs).toBeDefined()
expect(categoryWithPosts.localizedArrayPosts.docs).toHaveLength(10)
})

it('should populate joins with blocks relationships', async () => {
const categoryWithPosts = await payload.findByID({
id: category.id,
Expand Down
18 changes: 18 additions & 0 deletions test/joins/payload-types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ export interface Config {
'group.relatedPosts': 'posts';
'group.camelCasePosts': 'posts';
arrayPosts: 'posts';
localizedArrayPosts: 'posts';
blocksPosts: 'posts';
polymorphic: 'posts';
polymorphics: 'posts';
Expand Down Expand Up @@ -199,6 +200,12 @@ export interface Post {
id?: string | null;
}[]
| null;
localizedArray?:
| {
category?: (string | null) | Category;
id?: string | null;
}[]
| null;
blocks?:
| {
category?: (string | null) | Category;
Expand Down Expand Up @@ -272,6 +279,10 @@ export interface Category {
docs?: (string | Post)[] | null;
hasNextPage?: boolean | null;
} | null;
localizedArrayPosts?: {
docs?: (string | Post)[] | null;
hasNextPage?: boolean | null;
} | null;
blocksPosts?: {
docs?: (string | Post)[] | null;
hasNextPage?: boolean | null;
Expand Down Expand Up @@ -649,6 +660,12 @@ export interface PostsSelect<T extends boolean = true> {
category?: T;
id?: T;
};
localizedArray?:
| T
| {
category?: T;
id?: T;
};
blocks?:
| T
| {
Expand Down Expand Up @@ -680,6 +697,7 @@ export interface CategoriesSelect<T extends boolean = true> {
camelCasePosts?: T;
};
arrayPosts?: T;
localizedArrayPosts?: T;
blocksPosts?: T;
polymorphic?: T;
polymorphics?: T;
Expand Down

0 comments on commit 25a70ab

Please # to comment.