UNPKG

@progress/sitefinity-nextjs-sdk

Version:

Provides OOB widgets developed using the Next.js framework, which includes an abstraction layer for Sitefinity communication. Additionally, it offers an expanded API, typings, and tools for further development and integration.

170 lines (169 loc) 8.53 kB
import { FilterOperators, StringOperators } from '../filters/filter-clause'; import { FieldType } from '../service-metadata'; import { SitefinityContentTypesFilterMetadataProvider } from './sitefinity-content-types-filter-metadata-provider'; export class ODataFilterSerializer { filterMetadata; propertyPrefix; lambdaVariableName; constructor(filterMetadata, lambdaVariableName = 'a') { this.filterMetadata = filterMetadata || new SitefinityContentTypesFilterMetadataProvider(); this.lambdaVariableName = lambdaVariableName; this.propertyPrefix = lambdaVariableName === 'a' ? '' : `${lambdaVariableName}/`; } serialize(filterContext) { if (filterContext.Filter?.hasOwnProperty('ChildFilters')) { return this.serializeCombinedFilter(filterContext.Filter, filterContext); } else if (filterContext.Filter?.hasOwnProperty('FieldName')) { return this.serializeFilterClause(filterContext.Filter, filterContext); } else if (filterContext.Filter?.hasOwnProperty('Name')) { return this.serializeRelationFilter(filterContext.Filter, filterContext); } return null; } serializeCombinedFilter(filter, filterContext) { if (filter.ChildFilters.length === 0) { return null; } let serializedChildFilters = filter.ChildFilters.map((x => { if (x.hasOwnProperty('FieldName')) { return this.serializeFilterClause(x, filterContext); } else if (x.hasOwnProperty('ChildFilters')) { let serializedFilter = this.serializeCombinedFilter(x, filterContext); if (serializedFilter) { serializedFilter = `(${serializedFilter})`; } return serializedFilter; } else if (x.hasOwnProperty('Name')) { return this.serializeRelationFilter(x, filterContext); } return null; })).filter(x => x); if (serializedChildFilters.length === 1 && filter.Operator !== 'NOT') { return serializedChildFilters[0]; } if (filter.Operator === 'NOT') { return `(not ${serializedChildFilters[0]})`; } serializedChildFilters = serializedChildFilters.map(x => { if (!x) { return null; } if (x.startsWith('(') && x.endsWith(')')) { return x; } return `(${x})`; }).filter(x => x); return serializedChildFilters.join(` ${filter.Operator.toLowerCase()} `); } serializeFilterClause(filter, filterContext) { let fieldNameWithPrefix = `${this.propertyPrefix}${filter.FieldName}`; const nextVariableName = String.fromCharCode(this.lambdaVariableName.charCodeAt(0) + 1); const fieldType = this.filterMetadata.getFieldType(filter, filterContext); switch (filter.Operator) { case FilterOperators.Equal: case FilterOperators.NotEqual: const serializedValue1 = this.serializeFilterValue(filter.FieldValue, filter.FieldName, filterContext); let filterResult = null; switch (fieldType) { case FieldType.ChoiceField: filterResult = `cast(${fieldNameWithPrefix}, 'Edm.String') ${filter.Operator} '${serializedValue1}'`; break; case FieldType.ClassificationField: filterResult = `${fieldNameWithPrefix}/any(x:x eq ${serializedValue1})`; if (filter.Operator === 'ne') { filterResult = 'not ' + filter; } break; default: filterResult = `(${fieldNameWithPrefix} ${filter.Operator} ${serializedValue1})`; break; } return filterResult; case FilterOperators.GreaterThan: case FilterOperators.LessThan: case FilterOperators.GreaterThanOrEqual: case FilterOperators.LessThanOrEqual: const serializedValue = this.serializeFilterValue(filter.FieldValue, filter.FieldName, filterContext); return `(${fieldNameWithPrefix} ${filter.Operator} ${serializedValue})`; case FilterOperators.ContainsOr: case FilterOperators.DoesNotContain: let containsOrFilter = this.getContainsTypeOperatorsFilterExpression(filter, filterContext, fieldNameWithPrefix, nextVariableName, 'or'); if (containsOrFilter && filter.Operator === FilterOperators.DoesNotContain) { containsOrFilter = 'not (' + containsOrFilter + ')'; } return containsOrFilter; case FilterOperators.ContainsAnd: return this.getContainsTypeOperatorsFilterExpression(filter, filterContext, fieldNameWithPrefix, nextVariableName, 'and'); case StringOperators.StartsWith: case StringOperators.EndsWith: case StringOperators.Contains: const serializedValueForString = this.serializeFilterValue(filter.FieldValue, filter.FieldName, filterContext); return `${filter.Operator}(${fieldNameWithPrefix}, ${serializedValueForString})`; case FilterOperators.NotStartsWith: const serializedValueForNotStartsWith = this.serializeFilterValue(filter.FieldValue, filter.FieldName, filterContext); return `not startswith(${fieldNameWithPrefix}, ${serializedValueForNotStartsWith})`; case FilterOperators.In: return `${filter.FieldName} ${filter.Operator} (${filter.FieldValue})`; default: throw new Error(`The value provided for the operator filter clause: ${filter.Operator} is not supported`); } } serializeRelationFilter(filter, filterContext) { let relatedType = this.filterMetadata.getRelatedType(filter.Name, filterContext); if (!relatedType) { return null; } let newFilterContext = { Type: relatedType, Filter: filter.ChildFilter }; const nextVariableName = String.fromCharCode(this.lambdaVariableName.charCodeAt(0) + 1); let serializedChildFilter = new ODataFilterSerializer(this.filterMetadata, nextVariableName).serialize(newFilterContext); switch (filter.Operator) { case 'Any': return `${this.propertyPrefix}${filter.Name}/any(${nextVariableName}:${serializedChildFilter})`; case 'All': return `${this.propertyPrefix}${filter.Name}/all(${nextVariableName}:${serializedChildFilter})`; default: break; } return null; } serializeFilterValue(value, propName, filterContext) { const { success, result } = this.filterMetadata.trySerializeFilterValue(propName, value, filterContext); if (!success || result === null || result === undefined) { return value.toString(); } return result; } serializeFilterValuesArray(value, propName, filterContext) { if (typeof value === 'string') { return [this.serializeFilterValue(value, propName, filterContext)]; } if (Array.isArray(value)) { return value.map(x => this.serializeFilterValue(x, propName, filterContext)); } const serialized = this.serializeFilterValue(value, propName, filterContext); return [serialized]; } getContainsTypeOperatorsFilterExpression(clause, filterContext, fieldNameWithPrefix, nextVariableName, operatorName) { const serializedValues = this.serializeFilterValuesArray(clause.FieldValue, clause.FieldName, filterContext); if (serializedValues.length > 0) { if (this.filterMetadata.isPropertyACollection(filterContext, clause)) { return serializedValues .map(x => `${fieldNameWithPrefix}/any(${nextVariableName}: ${nextVariableName} eq ${x})`) .join(` ${operatorName} `); } else { return serializedValues .map(x => `${fieldNameWithPrefix} eq ${x}`) .join(` ${operatorName} `); } } return null; } }