Skip to content

Commit

Permalink
Expose Content Fields Indexing via GraphQL for content field filtering (
Browse files Browse the repository at this point in the history
#16092)

Co-authored-by: mdameer <mohammad_dameer@hotmail.com>
Co-authored-by: Hisham Bin Ateya <hishamco_2007@yahoo.com>
Co-authored-by: Tony Han <hyzx86@live.com>
Co-authored-by: Georg von Kries <georg.von.kries@creativbox.net>
  • Loading branch information
5 people committed Jun 15, 2024
1 parent f60b224 commit 3853b97
Show file tree
Hide file tree
Showing 37 changed files with 927 additions and 102 deletions.
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using System.Collections.Generic;
using System.Threading.Tasks;
using OrchardCore.Alias.Indexes;
using OrchardCore.ContentManagement.GraphQL.Queries;

Expand All @@ -16,9 +17,9 @@ public class AliasPartIndexAliasProvider : IIndexAliasProvider
}
];

public IEnumerable<IndexAlias> GetAliases()
public ValueTask<IEnumerable<IndexAlias>> GetAliasesAsync()
{
return _aliases;
return ValueTask.FromResult<IEnumerable<IndexAlias>>(_aliases);
}
}
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using System.Collections.Generic;
using System.Threading.Tasks;
using OrchardCore.Autoroute.Core.Indexes;
using OrchardCore.ContentManagement.GraphQL.Queries;

Expand All @@ -16,9 +17,9 @@ public class AutoroutePartIndexAliasProvider : IIndexAliasProvider
}
];

public IEnumerable<IndexAlias> GetAliases()
public ValueTask<IEnumerable<IndexAlias>> GetAliasesAsync()
{
return _aliases;
return ValueTask.FromResult<IEnumerable<IndexAlias>>(_aliases);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,9 @@
using System.Collections.Generic;
using GraphQL.Resolvers;
using GraphQL.Types;
using OrchardCore.Apis.GraphQL.Queries.Types;
using OrchardCore.ContentFields.Fields;
using OrchardCore.ContentFields.GraphQL.Types;
using OrchardCore.ContentFields.Indexing.SQL;
using OrchardCore.ContentManagement;
using OrchardCore.ContentManagement.GraphQL.Queries.Types;
using OrchardCore.ContentManagement.Metadata.Models;
Expand All @@ -23,6 +24,8 @@ public class ContentFieldsProvider : IContentFieldProvider
FieldType = typeof(BooleanGraphType),
UnderlyingType = typeof(BooleanField),
FieldAccessor = field => ((BooleanField)field).Value,
IndexType = typeof(BooleanFieldIndex),
Index = nameof(BooleanFieldIndex.Boolean)
}
},
{
Expand All @@ -33,6 +36,8 @@ public class ContentFieldsProvider : IContentFieldProvider
FieldType = typeof(DateGraphType),
UnderlyingType = typeof(DateField),
FieldAccessor = field => ((DateField)field).Value,
IndexType = typeof(DateFieldIndex),
Index = nameof(DateFieldIndex.Date)
}
},
{
Expand All @@ -43,6 +48,8 @@ public class ContentFieldsProvider : IContentFieldProvider
FieldType = typeof(DateTimeGraphType),
UnderlyingType = typeof(DateTimeField),
FieldAccessor = field => ((DateTimeField)field).Value,
IndexType = typeof(DateTimeFieldIndex),
Index = nameof(DateTimeFieldIndex.DateTime)
}
},
{
Expand All @@ -53,6 +60,8 @@ public class ContentFieldsProvider : IContentFieldProvider
FieldType = typeof(DecimalGraphType),
UnderlyingType = typeof(NumericField),
FieldAccessor = field => ((NumericField)field).Value,
IndexType = typeof(NumericFieldIndex),
Index = nameof(NumericFieldIndex.Numeric)
}
},
{
Expand All @@ -63,6 +72,8 @@ public class ContentFieldsProvider : IContentFieldProvider
FieldType = typeof(StringGraphType),
UnderlyingType = typeof(TextField),
FieldAccessor = field => ((TextField)field).Text,
IndexType = typeof(TextFieldIndex),
Index = nameof(TextFieldIndex.Text)
}
},
{
Expand All @@ -73,6 +84,8 @@ public class ContentFieldsProvider : IContentFieldProvider
FieldType = typeof(TimeSpanGraphType),
UnderlyingType = typeof(TimeField),
FieldAccessor = field => ((TimeField)field).Value,
IndexType = typeof(TimeFieldIndex),
Index = nameof(TimeFieldIndex.Time)
}
},
{
Expand Down Expand Up @@ -118,12 +131,35 @@ public FieldType GetField(ISchema schema, ContentPartFieldDefinition field, stri

public bool HasField(ISchema schema, ContentPartFieldDefinition field) => _contentFieldTypeMappings.ContainsKey(field.FieldDefinition.Name);

public FieldTypeIndexDescriptor GetFieldIndex(ContentPartFieldDefinition field)
{
if (!HasFieldIndex(field))
{
return null;
}

var fieldDescriptor = _contentFieldTypeMappings[field.FieldDefinition.Name];

return new FieldTypeIndexDescriptor
{
Index = fieldDescriptor.Index,
IndexType = fieldDescriptor.IndexType
};
}

public bool HasFieldIndex(ContentPartFieldDefinition field) =>
_contentFieldTypeMappings.TryGetValue(field.FieldDefinition.Name, out var fieldTypeDescriptor) &&
fieldTypeDescriptor.IndexType != null &&
!string.IsNullOrWhiteSpace(fieldTypeDescriptor.Index);

private sealed class FieldTypeDescriptor
{
public string Description { get; set; }
public Type FieldType { get; set; }
public Type UnderlyingType { get; set; }
public Func<ContentElement, object> FieldAccessor { get; set; }
public string Index { get; set; }
public Type IndexType { get; set; }
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,8 @@ public FieldType GetField(ISchema schema, ContentPartFieldDefinition field, stri
ResolvedType = queryGraphType,
Resolver = new FuncFieldResolver<ContentElement, ContentElement>(context =>
{
var typeToResolve = context.FieldDefinition.ResolvedType.GetType().BaseType.GetGenericArguments().First();
var typeToResolve = context.FieldDefinition.ResolvedType.GetType().BaseType
.GetGenericArguments().First();
// Check if part has been collapsed by trying to get the parent part.
ContentElement contentPart = context.Source.Get<ContentPart>(field.PartDefinition.Name);
Expand All @@ -44,8 +45,15 @@ public FieldType GetField(ISchema schema, ContentPartFieldDefinition field, stri
return null;
}

public FieldTypeIndexDescriptor GetFieldIndex(ContentPartFieldDefinition field)
{
return null;
}

public bool HasField(ISchema schema, ContentPartFieldDefinition field) => GetObjectGraphType(schema, field) != null;

public bool HasFieldIndex(ContentPartFieldDefinition field) => false;

private static IObjectGraphType GetObjectGraphType(ISchema schema, ContentPartFieldDefinition field) =>
schema.AdditionalTypeInstances
.FirstOrDefault(x => x is IObjectGraphType && x.GetType().BaseType.GetGenericArguments().First().Name == field.FieldDefinition.Name) as IObjectGraphType;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
using OrchardCore.ContentFields.Fields;
using OrchardCore.ContentFields.GraphQL.Fields;
using OrchardCore.ContentFields.GraphQL.Types;
using OrchardCore.ContentManagement.GraphQL;
using OrchardCore.ContentManagement.GraphQL.Queries.Types;
using OrchardCore.Modules;

Expand All @@ -22,4 +23,13 @@ public override void ConfigureServices(IServiceCollection services)
services.AddObjectGraphType<UserPickerField, UserPickerFieldQueryObjectType>();
}
}

[RequireFeatures("OrchardCore.Apis.GraphQL", "OrchardCore.ContentFields.Indexing.SQL")]
public class IndexStartup : StartupBase
{
public override void ConfigureServices(IServiceCollection services)
{
services.AddContentFieldsInputGraphQL();
}
}
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using System.Collections.Generic;
using System.Threading.Tasks;
using OrchardCore.ContentLocalization.Records;
using OrchardCore.ContentManagement.GraphQL.Queries;

Expand All @@ -16,9 +17,9 @@ public class LocalizationPartIndexAliasProvider : IIndexAliasProvider
}
];

public IEnumerable<IndexAlias> GetAliases()
public ValueTask<IEnumerable<IndexAlias>> GetAliasesAsync()
{
return _aliases;
return ValueTask.FromResult<IEnumerable<IndexAlias>>(_aliases);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -369,6 +369,12 @@ public async Task AlterFieldAsync(EditPartViewModel partViewModel, EditFieldView
fieldBuilder.WithDisplayMode(fieldViewModel.DisplayMode);
});
});

_contentDefinitionEventHandlers.Invoke((handler, context) => handler.ContentPartFieldUpdated(context), new ContentPartFieldUpdatedContext
{
ContentPartName = partViewModel.Name,
ContentFieldName = fieldViewModel.Name
}, _logger);
}

public async Task AlterTypePartAsync(EditTypePartViewModel typePartViewModel)
Expand All @@ -385,10 +391,17 @@ public async Task AlterTypePartAsync(EditTypePartViewModel typePartViewModel)
part.WithDisplayMode(typePartViewModel.DisplayMode);
});
});

_contentDefinitionEventHandlers.Invoke((handler, context) => handler.ContentTypePartUpdated(context), new ContentTypePartUpdatedContext
{
ContentTypeName = typeDefinition.Name,
ContentPartName = typePartViewModel.Name
}, _logger);
}

public Task AlterTypePartsOrderAsync(ContentTypeDefinition typeDefinition, string[] partNames)
=> _contentDefinitionManager.AlterTypeDefinitionAsync(typeDefinition.Name, type =>
public async Task AlterTypePartsOrderAsync(ContentTypeDefinition typeDefinition, string[] partNames)
{
await _contentDefinitionManager.AlterTypeDefinitionAsync(typeDefinition.Name, type =>
{
if (partNames is null)
{
Expand All @@ -411,8 +424,15 @@ public Task AlterTypePartsOrderAsync(ContentTypeDefinition typeDefinition, strin
}
});

public Task AlterPartFieldsOrderAsync(ContentPartDefinition partDefinition, string[] fieldNames)
=> _contentDefinitionManager.AlterPartDefinitionAsync(partDefinition.Name, type =>
_contentDefinitionEventHandlers.Invoke((handler, context) => handler.ContentTypeUpdated(context), new ContentTypeUpdatedContext
{
ContentTypeDefinition = typeDefinition
}, _logger);
}

public async Task AlterPartFieldsOrderAsync(ContentPartDefinition partDefinition, string[] fieldNames)
{
await _contentDefinitionManager.AlterPartDefinitionAsync(partDefinition.Name, type =>
{
if (fieldNames is null)
{
Expand All @@ -429,6 +449,12 @@ public Task AlterPartFieldsOrderAsync(ContentPartDefinition partDefinition, stri
}
});

_contentDefinitionEventHandlers.Invoke((handler, context) => handler.ContentPartUpdated(context), new ContentPartUpdatedContext
{
ContentPartDefinition = partDefinition
}, _logger);
}

public async Task<string> GenerateContentTypeNameFromDisplayNameAsync(string displayName)
{
displayName = displayName.ToSafeName();
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using System.Collections.Generic;
using System.Threading.Tasks;
using OrchardCore.ContentManagement.GraphQL.Queries;
using OrchardCore.Lists.Indexes;

Expand All @@ -16,9 +17,9 @@ public class ContainedPartIndexAliasProvider : IIndexAliasProvider
}
];

public IEnumerable<IndexAlias> GetAliases()
public ValueTask<IEnumerable<IndexAlias>> GetAliasesAsync()
{
return _aliases;
return ValueTask.FromResult<IEnumerable<IndexAlias>>(_aliases);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
using GraphQL.Types;
using GraphQLParser.AST;

namespace OrchardCore.ContentFields.GraphQL.Types
namespace OrchardCore.Apis.GraphQL.Queries.Types
{
public class TimeSpanGraphType : ScalarGraphType
{
Expand Down
Original file line number Diff line number Diff line change
@@ -1,14 +1,22 @@
using System;
using System.Collections.Generic;
using GraphQL.Types;
using OrchardCore.Apis.GraphQL.Queries.Types;

namespace OrchardCore.Apis.GraphQL.Queries
{
public class WhereInputObjectGraphType : WhereInputObjectGraphType<object>
public interface IFilterInputObjectGraphType : IInputObjectGraphType
{
void AddScalarFilterFields<TGraphType>(string fieldName, string description);

void AddScalarFilterFields(Type graphType, string fieldName, string description);
}

public class WhereInputObjectGraphType : WhereInputObjectGraphType<object>, IFilterInputObjectGraphType
{
}

public class WhereInputObjectGraphType<TSourceType> : InputObjectGraphType<TSourceType>
public class WhereInputObjectGraphType<TSourceType> : InputObjectGraphType<TSourceType>, IFilterInputObjectGraphType
{
// arguments of typed input graph types return typed object, without additional input fields (_in, _contains,..)
// so we return dictionary as it was before.
Expand Down Expand Up @@ -51,22 +59,37 @@ public override object ParseDictionary(IDictionary<string, object> value)
{"_not_ends_with", "does not end with the string"},
};

public void AddScalarFilterFields<TGraphType>(string fieldName, string description)
public virtual void AddScalarFilterFields<TGraphType>(string fieldName, string description)
{
AddScalarFilterFields(typeof(TGraphType), fieldName, description);
}

public void AddScalarFilterFields(Type graphType, string fieldName, string description)
public virtual void AddScalarFilterFields(Type graphType, string fieldName, string description)
{
if (!typeof(ScalarGraphType).IsAssignableFrom(graphType) &&
!typeof(IInputObjectGraphType).IsAssignableFrom(graphType))
{
return;
}

AddEqualityFilters(graphType, fieldName, description);
AddMultiValueFilters(graphType, fieldName, description);

if (graphType == typeof(StringGraphType))
{
AddMultiValueFilters(graphType, fieldName, description);
AddStringFilters(graphType, fieldName, description);
}
else if (graphType == typeof(DateTimeGraphType))
else if (graphType == typeof(DateTimeGraphType) ||
graphType == typeof(DateGraphType) ||
graphType == typeof(DateOnlyGraphType) ||
graphType == typeof(TimeSpanGraphType) ||
graphType == typeof(DecimalGraphType) ||
graphType == typeof(IntGraphType) ||
graphType == typeof(LongGraphType) ||
graphType == typeof(FloatGraphType) ||
graphType == typeof(BigIntGraphType))
{
AddMultiValueFilters(graphType, fieldName, description);
AddNonStringFilters(graphType, fieldName, description);
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -232,7 +232,7 @@ internal static string GetFieldName(ContentTypePartDefinition definition, string
return partName.ToFieldName() + fieldName.ToPascalCase();
}

return fieldName;
return fieldName.ToCamelCase();
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
<ItemGroup>
<ProjectReference Include="..\..\OrchardCore\OrchardCore.Apis.GraphQL.Abstractions\OrchardCore.Apis.GraphQL.Abstractions.csproj" />
<ProjectReference Include="..\OrchardCore.ContentManagement.Abstractions\OrchardCore.ContentManagement.Abstractions.csproj" />
<ProjectReference Include="..\OrchardCore.ContentTypes.Abstractions\OrchardCore.ContentTypes.Abstractions.csproj" />
<ProjectReference Include="..\OrchardCore.ContentManagement.Display\OrchardCore.ContentManagement.Display.csproj" />
<ProjectReference Include="..\OrchardCore.ContentManagement\OrchardCore.ContentManagement.csproj" />
<ProjectReference Include="..\OrchardCore.Contents.Core\OrchardCore.Contents.Core.csproj" />
Expand Down
Loading

0 comments on commit 3853b97

Please sign in to comment.