Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fixes errors when filtering by content fields in GraphQL #17378

Open
wants to merge 3 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using System.Collections.Frozen;
using GraphQL;
using GraphQL.Resolvers;
using GraphQL.Types;
using Microsoft.Extensions.Localization;
Expand All @@ -25,7 +26,7 @@ public class ContentFieldsProvider : IContentFieldProvider
UnderlyingType = typeof(BooleanField),
FieldAccessor = field => ((BooleanField)field).Value,
IndexType = typeof(BooleanFieldIndex),
Index = nameof(BooleanFieldIndex.Boolean),
IndexProperty = nameof(BooleanFieldIndex.Boolean),
}
},
{
Expand All @@ -38,7 +39,7 @@ public class ContentFieldsProvider : IContentFieldProvider
UnderlyingType = typeof(DateField),
FieldAccessor = field => ((DateField)field).Value,
IndexType = typeof(DateFieldIndex),
Index = nameof(DateFieldIndex.Date),
IndexProperty = nameof(DateFieldIndex.Date),
}
},
{
Expand All @@ -51,7 +52,7 @@ public class ContentFieldsProvider : IContentFieldProvider
UnderlyingType = typeof(DateTimeField),
FieldAccessor = field => ((DateTimeField)field).Value,
IndexType = typeof(DateTimeFieldIndex),
Index = nameof(DateTimeFieldIndex.DateTime),
IndexProperty = nameof(DateTimeFieldIndex.DateTime),
}
},
{
Expand All @@ -64,7 +65,7 @@ public class ContentFieldsProvider : IContentFieldProvider
UnderlyingType = typeof(NumericField),
FieldAccessor = field => ((NumericField)field).Value,
IndexType = typeof(NumericFieldIndex),
Index = nameof(NumericFieldIndex.Numeric)
IndexProperty = nameof(NumericFieldIndex.Numeric)
}
},
{
Expand All @@ -77,7 +78,7 @@ public class ContentFieldsProvider : IContentFieldProvider
UnderlyingType = typeof(TextField),
FieldAccessor = field => ((TextField)field).Text,
IndexType = typeof(TextFieldIndex),
Index = nameof(TextFieldIndex.Text)
IndexProperty = nameof(TextFieldIndex.Text)
}
},
{
Expand All @@ -90,7 +91,7 @@ public class ContentFieldsProvider : IContentFieldProvider
UnderlyingType = typeof(TimeField),
FieldAccessor = field => ((TimeField)field).Value,
IndexType = typeof(TimeFieldIndex),
Index = nameof(TimeFieldIndex.Time)
IndexProperty = nameof(TimeFieldIndex.Time)
}
},
{
Expand Down Expand Up @@ -157,15 +158,16 @@ public FieldTypeIndexDescriptor GetFieldIndex(ContentPartFieldDefinition field)

return new FieldTypeIndexDescriptor
{
Index = fieldDescriptor.Index,
IndexType = fieldDescriptor.IndexType,
AliasName = $"{field.PartDefinition.Name.ToFieldName()}:{field.Name.ToCamelCase()}:{fieldDescriptor.IndexProperty}",
Index = fieldDescriptor.IndexType.Name,
IndexType = fieldDescriptor.IndexType
};
}

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

private sealed class FieldTypeDescriptor
{
Expand All @@ -179,7 +181,7 @@ private sealed class FieldTypeDescriptor

public Func<ContentElement, object> FieldAccessor { get; set; }

public string Index { get; set; }
public string IndexProperty { get; set; }

public Type IndexType { get; set; }
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
using GraphQL.Types;

namespace OrchardCore.ContentManagement.GraphQL;
namespace OrchardCore.Apis.GraphQL;

public static class GraphQLTypeExtensions
{
Expand All @@ -10,6 +10,15 @@ public static FieldType WithPartCollapsedMetaData(this FieldType fieldType, bool
public static FieldType WithPartNameMetaData(this FieldType fieldType, string partName)
=> fieldType.WithMetaData("PartName", partName);

public static FieldType WithAliasNameMetaData(this FieldType fieldType, string aliasName)
=> fieldType.WithMetaData("AliasName", aliasName);

public static FieldType WithContentPartMetaData(this FieldType fieldType, string contentPart)
=> fieldType.WithMetaData("ContentPart", contentPart);

public static FieldType WithContentFieldMetaData(this FieldType fieldType, string contentField)
=> fieldType.WithMetaData("ContentField", contentField);

/// <summary>
/// Checks if the field exists in the GraphQL type in a case-insensitive way.
/// </summary>
Expand All @@ -27,10 +36,13 @@ public static bool HasFieldIgnoreCase(this IComplexGraphType graphType, string f

private static FieldType WithMetaData(this FieldType fieldType, string name, object value)
{
// TODO: Understand if locking is the best solution to https://github.com/OrchardCMS/OrchardCore/issues/15308
lock (fieldType.Metadata)
if (value != null)
{
fieldType.Metadata.TryAdd(name, value);
// TODO: Understand if locking is the best solution to https://github.com/OrchardCMS/OrchardCore/issues/15308
lock (fieldType.Metadata)
{
fieldType.Metadata.TryAdd(name, value);
}
}

return fieldType;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,16 @@
using GraphQL.Types;
using GraphQL.Types;

namespace OrchardCore.Apis.GraphQL.Queries;

public interface IFilterInputObjectGraphType : IInputObjectGraphType
{
void AddScalarFilterFields<TGraphType>(string fieldName, string description);

void AddScalarFilterFields<TGraphType>(string fieldName, string description, string aliasName, string contentPart, string contentField)
=> AddScalarFilterFields<TGraphType>(fieldName, description);

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

void AddScalarFilterFields(Type graphType, string fieldName, string description, string aliasName, string contentPart, string contentField)
=> AddScalarFilterFields(graphType, fieldName, description);
}
Original file line number Diff line number Diff line change
Expand Up @@ -62,25 +62,31 @@ public override object ParseDictionary(IDictionary<string, object> value)
{ "_not_ends_with", (S, description) => S["{0} does not end with the string", description] },
};

public virtual void AddScalarFilterFields<TGraphType>(string fieldName, string description)
public void AddScalarFilterFields<TGraphType>(string fieldName, string description)
=> AddScalarFilterFields<TGraphType>(fieldName, description, null, null, null);

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

public virtual void AddScalarFilterFields(Type graphType, string fieldName, string description)
public void AddScalarFilterFields(Type graphType, string fieldName, string description)
=> AddScalarFilterFields(graphType, fieldName, description, null, null, null);

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

AddEqualityFilters(graphType, fieldName, description);
AddEqualityFilters(graphType, fieldName, description, aliasName, contentPart, contentField);

if (graphType == typeof(StringGraphType))
{
AddMultiValueFilters(graphType, fieldName, description);
AddStringFilters(graphType, fieldName, description);
AddMultiValueFilters(graphType, fieldName, description, aliasName, contentPart, contentField);
AddStringFilters(graphType, fieldName, description, aliasName, contentPart, contentField);
}
else if (graphType == typeof(DateTimeGraphType) ||
graphType == typeof(DateGraphType) ||
Expand All @@ -92,36 +98,39 @@ public virtual void AddScalarFilterFields(Type graphType, string fieldName, stri
graphType == typeof(FloatGraphType) ||
graphType == typeof(BigIntGraphType))
{
AddMultiValueFilters(graphType, fieldName, description);
AddNonStringFilters(graphType, fieldName, description);
AddMultiValueFilters(graphType, fieldName, description, aliasName, contentPart, contentField);
AddNonStringFilters(graphType, fieldName, description, aliasName, contentPart, contentField);
}
}

private void AddEqualityFilters(Type graphType, string fieldName, string description)
private void AddEqualityFilters(Type graphType, string fieldName, string description, string aliasName, string contentPart, string contentField)
{
AddFilterFields(graphType, EqualityOperators, fieldName, description);
AddFilterFields(graphType, EqualityOperators, fieldName, description, aliasName, contentPart, contentField);
}

private void AddStringFilters(Type graphType, string fieldName, string description)
private void AddStringFilters(Type graphType, string fieldName, string description, string aliasName, string contentPart, string contentField)
{
AddFilterFields(graphType, StringComparisonOperators, fieldName, description);
AddFilterFields(graphType, StringComparisonOperators, fieldName, description, aliasName, contentPart, contentField);
}

private void AddNonStringFilters(Type graphType, string fieldName, string description)
private void AddNonStringFilters(Type graphType, string fieldName, string description, string aliasName, string contentPart, string contentField)
{
AddFilterFields(graphType, NonStringValueComparisonOperators, fieldName, description);
AddFilterFields(graphType, NonStringValueComparisonOperators, fieldName, description, aliasName, contentPart, contentField);
}

private void AddMultiValueFilters(Type graphType, string fieldName, string description)
private void AddMultiValueFilters(Type graphType, string fieldName, string description, string aliasName, string contentPart, string contentField)
{
AddFilterFields(graphType, MultiValueComparisonOperators, fieldName, description);
AddFilterFields(graphType, MultiValueComparisonOperators, fieldName, description, aliasName, contentPart, contentField);
}

private void AddFilterFields(
Type graphType,
IDictionary<string, Func<IStringLocalizer, string, string>> filters,
string fieldName,
string description)
string description,
string aliasName,
string contentPart,
string contentField)
{
foreach (var filter in filters)
{
Expand All @@ -130,7 +139,9 @@ private void AddFilterFields(
Name = fieldName + filter.Key,
Description = filter.Value(S, description),
Type = graphType,
});
}.WithAliasNameMetaData(aliasName)
.WithContentPartMetaData(contentPart)
.WithContentFieldMetaData(contentField));
}
}
}
Loading