Skip to content

Commit a4d7d5e

Browse files
authored
Added a helper to check for child selections. (#6942)
1 parent 1865894 commit a4d7d5e

File tree

35 files changed

+1586
-1
lines changed

35 files changed

+1586
-1
lines changed

src/HotChocolate/Core/src/Types/Extensions/ResolverContextExtensions.cs

Lines changed: 323 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
using System;
2+
using System.Collections.Generic;
23
using System.Security.Claims;
34
using HotChocolate.Resolvers;
5+
using HotChocolate.Types;
46
using static HotChocolate.Utilities.ThrowHelper;
57
using static HotChocolate.Properties.TypeResources;
68

@@ -540,4 +542,325 @@ public static T GetEventMessage<T>(this IResolverContext context)
540542
/// </returns>
541543
public static ClaimsPrincipal? GetUser(this IResolverContext context)
542544
=> context.GetGlobalStateOrDefault<ClaimsPrincipal?>(nameof(ClaimsPrincipal));
545+
546+
/// <summary>
547+
/// Checks if a field is selected in the current selection set.
548+
/// </summary>
549+
/// <param name="context">
550+
/// The resolver context.
551+
/// </param>
552+
/// <param name="fieldName">
553+
/// The name of the field that shall be checked.
554+
/// </param>
555+
/// <returns>
556+
/// <c>true</c> if the field is selected; otherwise, <c>false</c>.
557+
/// </returns>
558+
/// <exception cref="ArgumentNullException">
559+
/// <paramref name="context" /> is <c>null</c>.
560+
/// </exception>
561+
/// <exception cref="ArgumentException">
562+
/// <paramref name="fieldName" /> is <c>null</c> or whitespace.
563+
/// </exception>
564+
public static bool IsSelected(this IResolverContext context, string fieldName)
565+
{
566+
if (context is null)
567+
{
568+
throw new ArgumentNullException(nameof(context));
569+
}
570+
571+
if (string.IsNullOrWhiteSpace(fieldName))
572+
{
573+
throw new ArgumentException(
574+
ResolverContextExtensions_IsSelected_FieldNameEmpty,
575+
nameof(fieldName));
576+
}
577+
578+
if (!context.Selection.Type.IsCompositeType())
579+
{
580+
return false;
581+
}
582+
583+
var namedType = context.Selection.Type.NamedType();
584+
585+
if (namedType.IsAbstractType())
586+
{
587+
foreach (var possibleType in context.Schema.GetPossibleTypes(namedType))
588+
{
589+
var selections = context.GetSelections(possibleType, context.Selection);
590+
591+
for (var i = 0; i < selections.Count; i++)
592+
{
593+
if (selections[i].Field.Name.Equals(fieldName))
594+
{
595+
return true;
596+
}
597+
}
598+
}
599+
}
600+
else
601+
{
602+
var selections = context.GetSelections((ObjectType)namedType, context.Selection);
603+
604+
for (var i = 0; i < selections.Count; i++)
605+
{
606+
if (selections[i].Field.Name.Equals(fieldName))
607+
{
608+
return true;
609+
}
610+
}
611+
}
612+
613+
return false;
614+
}
615+
616+
/// <summary>
617+
/// Checks if a field is selected in the current selection set.
618+
/// </summary>
619+
/// <param name="context">
620+
/// The resolver context.
621+
/// </param>
622+
/// <param name="fieldName1">
623+
/// The name of the first field that shall be checked.
624+
/// </param>
625+
/// <param name="fieldName2">
626+
/// The name of the second field that shall be checked.
627+
/// </param>
628+
/// <returns></returns>
629+
/// <exception cref="ArgumentNullException">
630+
/// <paramref name="context" /> is <c>null</c>.
631+
/// </exception>
632+
/// <exception cref="ArgumentException">
633+
/// <paramref name="fieldName1" /> is <c>null</c> or whitespace or
634+
/// <paramref name="fieldName2" /> is <c>null</c> or whitespace.
635+
/// </exception>
636+
public static bool IsSelected(this IResolverContext context, string fieldName1, string fieldName2)
637+
{
638+
if (context is null)
639+
{
640+
throw new ArgumentNullException(nameof(context));
641+
}
642+
643+
if (string.IsNullOrWhiteSpace(fieldName1))
644+
{
645+
throw new ArgumentException(
646+
ResolverContextExtensions_IsSelected_FieldNameEmpty,
647+
nameof(fieldName1));
648+
}
649+
650+
if (string.IsNullOrWhiteSpace(fieldName2))
651+
{
652+
throw new ArgumentException(
653+
ResolverContextExtensions_IsSelected_FieldNameEmpty,
654+
nameof(fieldName2));
655+
}
656+
657+
if (!context.Selection.Type.IsCompositeType())
658+
{
659+
return false;
660+
}
661+
662+
var namedType = context.Selection.Type.NamedType();
663+
664+
if (namedType.IsAbstractType())
665+
{
666+
foreach (var possibleType in context.Schema.GetPossibleTypes(namedType))
667+
{
668+
var selections = context.GetSelections(possibleType, context.Selection);
669+
670+
for (var i = 0; i < selections.Count; i++)
671+
{
672+
var selection = selections[i];
673+
674+
if (selection.Field.Name.Equals(fieldName1) || selection.Field.Name.Equals(fieldName2))
675+
{
676+
return true;
677+
}
678+
}
679+
}
680+
}
681+
else
682+
{
683+
var selections = context.GetSelections((ObjectType)namedType, context.Selection);
684+
685+
for (var i = 0; i < selections.Count; i++)
686+
{
687+
var selection = selections[i];
688+
689+
if (selection.Field.Name.Equals(fieldName1) || selection.Field.Name.Equals(fieldName2))
690+
{
691+
return true;
692+
}
693+
}
694+
}
695+
696+
return false;
697+
}
698+
699+
/// <summary>
700+
/// Checks if a field is selected in the current selection set.
701+
/// </summary>
702+
/// <param name="context">
703+
/// The resolver context.
704+
/// </param>
705+
/// <param name="fieldName1">
706+
/// The name of the first field that shall be checked.
707+
/// </param>
708+
/// <param name="fieldName2">
709+
/// The name of the second field that shall be checked.
710+
/// </param>
711+
/// <param name="fieldName3">
712+
/// The name of the third field that shall be checked.
713+
/// </param>
714+
/// <returns></returns>
715+
/// <exception cref="ArgumentNullException">
716+
/// <paramref name="context" /> is <c>null</c>.
717+
/// </exception>
718+
/// <exception cref="ArgumentException">
719+
/// <paramref name="fieldName1" /> is <c>null</c> or whitespace or
720+
/// <paramref name="fieldName2" /> is <c>null</c> or whitespace or
721+
/// <paramref name="fieldName3" /> is <c>null</c> or whitespace.
722+
/// </exception>
723+
public static bool IsSelected(
724+
this IResolverContext context,
725+
string fieldName1,
726+
string fieldName2,
727+
string fieldName3)
728+
{
729+
if (context is null)
730+
{
731+
throw new ArgumentNullException(nameof(context));
732+
}
733+
734+
if (string.IsNullOrWhiteSpace(fieldName1))
735+
{
736+
throw new ArgumentException(
737+
ResolverContextExtensions_IsSelected_FieldNameEmpty,
738+
nameof(fieldName1));
739+
}
740+
741+
if (string.IsNullOrWhiteSpace(fieldName2))
742+
{
743+
throw new ArgumentException(
744+
ResolverContextExtensions_IsSelected_FieldNameEmpty,
745+
nameof(fieldName2));
746+
}
747+
748+
if(string.IsNullOrWhiteSpace(fieldName3))
749+
{
750+
throw new ArgumentException(
751+
ResolverContextExtensions_IsSelected_FieldNameEmpty,
752+
nameof(fieldName3));
753+
}
754+
755+
if (!context.Selection.Type.IsCompositeType())
756+
{
757+
return false;
758+
}
759+
760+
var namedType = context.Selection.Type.NamedType();
761+
762+
if (namedType.IsAbstractType())
763+
{
764+
foreach (var possibleType in context.Schema.GetPossibleTypes(namedType))
765+
{
766+
var selections = context.GetSelections(possibleType, context.Selection);
767+
768+
for (var i = 0; i < selections.Count; i++)
769+
{
770+
var selection = selections[i];
771+
772+
if (selection.Field.Name.Equals(fieldName1) ||
773+
selection.Field.Name.Equals(fieldName2) ||
774+
selection.Field.Name.Equals(fieldName3))
775+
{
776+
return true;
777+
}
778+
}
779+
}
780+
}
781+
else
782+
{
783+
var selections = context.GetSelections((ObjectType)namedType, context.Selection);
784+
785+
for (var i = 0; i < selections.Count; i++)
786+
{
787+
var selection = selections[i];
788+
789+
if (selection.Field.Name.Equals(fieldName1) ||
790+
selection.Field.Name.Equals(fieldName2) ||
791+
selection.Field.Name.Equals(fieldName3))
792+
{
793+
return true;
794+
}
795+
}
796+
}
797+
798+
return false;
799+
}
800+
801+
/// <summary>
802+
/// Checks if a field is selected in the current selection set.
803+
/// </summary>
804+
/// <param name="context">
805+
/// The resolver context.
806+
/// </param>
807+
/// <param name="fieldNames">
808+
/// The names of the fields that shall be checked.
809+
/// </param>
810+
/// <returns></returns>
811+
/// <exception cref="ArgumentNullException">
812+
/// <paramref name="context" /> is <c>null</c> or
813+
/// <paramref name="fieldNames" /> is <c>null</c>.
814+
/// </exception>
815+
public static bool IsSelected(
816+
this IResolverContext context,
817+
ISet<string> fieldNames)
818+
{
819+
if(context is null)
820+
{
821+
throw new ArgumentNullException(nameof(context));
822+
}
823+
824+
if(fieldNames is null)
825+
{
826+
throw new ArgumentNullException(nameof(fieldNames));
827+
}
828+
829+
if (!context.Selection.Type.IsCompositeType())
830+
{
831+
return false;
832+
}
833+
834+
var namedType = context.Selection.Type.NamedType();
835+
836+
if (namedType.IsAbstractType())
837+
{
838+
foreach (var possibleType in context.Schema.GetPossibleTypes(namedType))
839+
{
840+
var selections = context.GetSelections(possibleType, context.Selection);
841+
842+
for (var i = 0; i < selections.Count; i++)
843+
{
844+
if (fieldNames.Contains(selections[i].Field.Name))
845+
{
846+
return true;
847+
}
848+
}
849+
}
850+
}
851+
else
852+
{
853+
var selections = context.GetSelections((ObjectType)namedType, context.Selection);
854+
855+
for (var i = 0; i < selections.Count; i++)
856+
{
857+
if (fieldNames.Contains(selections[i].Field.Name))
858+
{
859+
return true;
860+
}
861+
}
862+
}
863+
864+
return false;
865+
}
543866
}

src/HotChocolate/Core/src/Types/Properties/TypeResources.Designer.cs

Lines changed: 6 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/HotChocolate/Core/src/Types/Properties/TypeResources.resx

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1012,4 +1012,7 @@ Type: `{0}`</value>
10121012
<data name="ThrowHelper_PooledServicesNotAllowed" xml:space="preserve">
10131013
<value>The keyed service `{0}` cannot be used as a pooled service.</value>
10141014
</data>
1015+
<data name="ResolverContextExtensions_IsSelected_FieldNameEmpty" xml:space="preserve">
1016+
<value>The field name mustn't be null, empty or consist only of white spaces.</value>
1017+
</data>
10151018
</root>

src/HotChocolate/Core/src/Types/Resolvers/IResolverContext.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -146,4 +146,4 @@ IReadOnlyList<ISelection> GetSelections(
146146
/// Returns the cloned resolver context.
147147
/// </returns>
148148
IResolverContext Clone();
149-
}
149+
}

0 commit comments

Comments
 (0)