| | 1 | | using Plainquire.Filter.Abstractions; |
| | 2 | | using System; |
| | 3 | | using System.Collections.Generic; |
| | 4 | | using System.Linq; |
| | 5 | | using System.Linq.Expressions; |
| | 6 | | using System.Reflection; |
| | 7 | | using System.Web; |
| | 8 | |
|
| | 9 | | namespace Plainquire.Filter; |
| | 10 | |
|
| | 11 | | /// <summary> |
| | 12 | | /// Extension methods for <see cref="EntityFilter{TEntity}"/> |
| | 13 | | /// </summary> |
| | 14 | | public static class EntityFilterExtensions |
| | 15 | | { |
| | 16 | | /// <summary> |
| | 17 | | /// Adds a filter for the given property. Existing filters for the same property are preserved. |
| | 18 | | /// </summary> |
| | 19 | | /// <typeparam name="TEntity">The type of the entity.</typeparam> |
| | 20 | | /// <typeparam name="TProperty">The type of the property.</typeparam> |
| | 21 | | /// <param name="entityFilter">The entity filter.</param> |
| | 22 | | /// <param name="property">The property to filter.</param> |
| | 23 | | /// <param name="filterSyntax">Description of the filter using micro syntax.</param> |
| | 24 | | public static EntityFilter<TEntity> Add<TEntity, TProperty>(this EntityFilter<TEntity> entityFilter, Expression<Func |
| | 25 | | { |
| 70 | 26 | | if (filterSyntax == null) |
| 1 | 27 | | return entityFilter; |
| | 28 | |
|
| 69 | 29 | | var filters = ValueFiltersFactory.Create(filterSyntax, entityFilter.Configuration); |
| 69 | 30 | | entityFilter.Add(property, filters); |
| 68 | 31 | | return entityFilter; |
| | 32 | | } |
| | 33 | |
|
| | 34 | | /// <summary> |
| | 35 | | /// Adds a filter for the given property using the default filter operator. Existing filters for the same property a |
| | 36 | | /// </summary> |
| | 37 | | /// <typeparam name="TEntity">The type of the entity.</typeparam> |
| | 38 | | /// <typeparam name="TProperty">The type of the property.</typeparam> |
| | 39 | | /// <typeparam name="TValue">The type of the value.</typeparam> |
| | 40 | | /// <param name="entityFilter">The entity filter.</param> |
| | 41 | | /// <param name="property">The property to filter.</param> |
| | 42 | | /// <param name="values">The values to filter for. Multiple values are combined with conditional OR.</param> |
| | 43 | | public static EntityFilter<TEntity> Add<TEntity, TProperty, TValue>(this EntityFilter<TEntity> entityFilter, Express |
| | 44 | | { |
| 23 | 45 | | if (values == null || values.Length == 0) |
| 4 | 46 | | return entityFilter; |
| | 47 | |
|
| 19 | 48 | | var valueFilters = values |
| 19 | 49 | | .Select(value => ValueFilter.Create( |
| 19 | 50 | | FilterOperator.Default, |
| 19 | 51 | | value, |
| 19 | 52 | | entityFilter.Configuration |
| 19 | 53 | | )) |
| 19 | 54 | | .ToArray(); |
| | 55 | |
|
| 18 | 56 | | return entityFilter.Add(property, valueFilters); |
| | 57 | | } |
| | 58 | |
|
| | 59 | | /// <summary> |
| | 60 | | /// Adds a filter for the given property. Existing filters for the same property are preserved. |
| | 61 | | /// </summary> |
| | 62 | | /// <typeparam name="TEntity">The type of the entity.</typeparam> |
| | 63 | | /// <typeparam name="TProperty">The type of the property.</typeparam> |
| | 64 | | /// <param name="entityFilter">The entity filter.</param> |
| | 65 | | /// <param name="property">The property to filter.</param> |
| | 66 | | /// <param name="filterOperator">The filter operator to use.</param> |
| | 67 | | public static EntityFilter<TEntity> Add<TEntity, TProperty>(this EntityFilter<TEntity> entityFilter, Expression<Func |
| 6 | 68 | | => entityFilter.Add(property, ValueFilter.Create(filterOperator, entityFilter.Configuration)); |
| | 69 | |
|
| | 70 | | /// <summary> |
| | 71 | | /// Adds a filter for the given property. Existing filters for the same property are preserved. |
| | 72 | | /// </summary> |
| | 73 | | /// <typeparam name="TEntity">The type of the entity.</typeparam> |
| | 74 | | /// <typeparam name="TProperty">The type of the property.</typeparam> |
| | 75 | | /// <typeparam name="TValue">The type of the value.</typeparam> |
| | 76 | | /// <param name="entityFilter">The entity filter.</param> |
| | 77 | | /// <param name="property">The property to filter.</param> |
| | 78 | | /// <param name="filterOperator">The filter operator to use.</param> |
| | 79 | | /// <param name="values">The values to filter for. Multiple values are combined with conditional OR.</param> |
| | 80 | | public static EntityFilter<TEntity> Add<TEntity, TProperty, TValue>(this EntityFilter<TEntity> entityFilter, Express |
| | 81 | | { |
| 15 | 82 | | var isNullableFilterOperator = filterOperator is FilterOperator.IsNull or FilterOperator.NotNull; |
| 15 | 83 | | if ((values == null || values.Length == 0) && !isNullableFilterOperator) |
| 2 | 84 | | return entityFilter; |
| | 85 | |
|
| 13 | 86 | | var valueFilters = values? |
| 13 | 87 | | .Select(value => ValueFilter.Create( |
| 13 | 88 | | filterOperator, |
| 13 | 89 | | value, |
| 13 | 90 | | entityFilter.Configuration |
| 13 | 91 | | )) |
| 13 | 92 | | .ToArray(); |
| | 93 | |
|
| 13 | 94 | | entityFilter.Add(property, valueFilters); |
| 13 | 95 | | return entityFilter; |
| | 96 | | } |
| | 97 | |
|
| | 98 | | /// <summary> |
| | 99 | | /// Replaces the filter for the given property. Existing filters for the same property are removed. |
| | 100 | | /// </summary> |
| | 101 | | /// <typeparam name="TEntity">The type of the entity.</typeparam> |
| | 102 | | /// <typeparam name="TProperty">The type of the property.</typeparam> |
| | 103 | | /// <param name="entityFilter">The entity filter.</param> |
| | 104 | | /// <param name="property">The property to filter.</param> |
| | 105 | | /// <param name="filterSyntax">Description of the filter using micro syntax.</param> |
| | 106 | | public static EntityFilter<TEntity> Replace<TEntity, TProperty>(this EntityFilter<TEntity> entityFilter, Expression< |
| | 107 | | { |
| 6504 | 108 | | if (filterSyntax == null) |
| 1 | 109 | | return entityFilter.Remove(property); |
| | 110 | |
|
| 6503 | 111 | | var valueFilters = ValueFiltersFactory.Create(filterSyntax, entityFilter.Configuration); |
| 6503 | 112 | | entityFilter.Replace(property, valueFilters); |
| 6503 | 113 | | return entityFilter; |
| | 114 | | } |
| | 115 | |
|
| | 116 | | /// <summary> |
| | 117 | | /// Replaces the filter for the given property using the default filter operator. Existing filters for the same prop |
| | 118 | | /// </summary> |
| | 119 | | /// <typeparam name="TEntity">The type of the entity.</typeparam> |
| | 120 | | /// <typeparam name="TProperty">The type of the t property.</typeparam> |
| | 121 | | /// <typeparam name="TValue">The type of the t value.</typeparam> |
| | 122 | | /// <param name="entityFilter">The entity filter.</param> |
| | 123 | | /// <param name="property">The property to filter.</param> |
| | 124 | | /// <param name="values">The values to filter for. Multiple values are combined with conditional OR.</param> |
| | 125 | | public static EntityFilter<TEntity> Replace<TEntity, TProperty, TValue>(this EntityFilter<TEntity> entityFilter, Exp |
| | 126 | | { |
| 4 | 127 | | if (values == null || values.Length == 0) |
| 2 | 128 | | return entityFilter.Remove(property); |
| | 129 | |
|
| 2 | 130 | | var valueFilters = values |
| 2 | 131 | | .Select(value => ValueFilter.Create( |
| 2 | 132 | | FilterOperator.Default, |
| 2 | 133 | | value, |
| 2 | 134 | | entityFilter.Configuration |
| 2 | 135 | | )) |
| 2 | 136 | | .ToArray(); |
| | 137 | |
|
| 2 | 138 | | return entityFilter.Replace(property, valueFilters); |
| | 139 | | } |
| | 140 | |
|
| | 141 | | /// <summary> |
| | 142 | | /// Replaces the filter for the given property. Existing filters for the same property are removed. |
| | 143 | | /// </summary> |
| | 144 | | /// <typeparam name="TEntity">The type of the entity.</typeparam> |
| | 145 | | /// <typeparam name="TProperty">The type of the property.</typeparam> |
| | 146 | | /// <param name="entityFilter">The entity filter.</param> |
| | 147 | | /// <param name="property">The property to filter.</param> |
| | 148 | | /// <param name="filterOperator">The filter operator to use.</param> |
| | 149 | | public static EntityFilter<TEntity> Replace<TEntity, TProperty>(this EntityFilter<TEntity> entityFilter, Expression< |
| 6 | 150 | | => entityFilter.Replace(property, ValueFilter.Create(filterOperator, entityFilter.Configuration)); |
| | 151 | |
|
| | 152 | | /// <summary> |
| | 153 | | /// Replaces the filter for the given property. Existing filters for the same property are removed. |
| | 154 | | /// </summary> |
| | 155 | | /// <typeparam name="TEntity">The type of the entity.</typeparam> |
| | 156 | | /// <typeparam name="TProperty">The type of the property.</typeparam> |
| | 157 | | /// <typeparam name="TValue">The type of the value.</typeparam> |
| | 158 | | /// <param name="entityFilter">The entity filter.</param> |
| | 159 | | /// <param name="property">The property to filter.</param> |
| | 160 | | /// <param name="filterOperator">The filter operator to use.</param> |
| | 161 | | /// <param name="values">The values to filter for. Multiple values are combined with conditional OR.</param> |
| | 162 | | public static EntityFilter<TEntity> Replace<TEntity, TProperty, TValue>(this EntityFilter<TEntity> entityFilter, Exp |
| | 163 | | { |
| 3549 | 164 | | var isNullableFilterOperator = filterOperator is FilterOperator.IsNull or FilterOperator.NotNull; |
| 3549 | 165 | | if ((values == null || values.Length == 0) && !isNullableFilterOperator) |
| 2 | 166 | | return entityFilter.Remove(property); |
| | 167 | |
|
| 3547 | 168 | | var valueFilters = values? |
| 3547 | 169 | | .Select(value => ValueFilter.Create( |
| 3547 | 170 | | filterOperator, |
| 3547 | 171 | | value, |
| 3547 | 172 | | entityFilter.Configuration |
| 3547 | 173 | | )) |
| 3547 | 174 | | .ToArray(); |
| | 175 | |
|
| 3546 | 176 | | entityFilter.Replace(property, valueFilters); |
| 3546 | 177 | | return entityFilter; |
| | 178 | | } |
| | 179 | |
|
| | 180 | | /// <summary> |
| | 181 | | /// Converts an entity filter to it's corresponding HTTP query parameters. |
| | 182 | | /// </summary> |
| | 183 | | /// <typeparam name="TEntity">Type of the entity.</typeparam> |
| | 184 | | /// <param name="entityFilter">The filter to act on.</param> |
| | 185 | | public static string ToQueryParams<TEntity>(this EntityFilter<TEntity> entityFilter) |
| | 186 | | { |
| 1 | 187 | | var filteredType = typeof(TEntity); |
| 1 | 188 | | var filterableProperties = filteredType.GetFilterableProperties(); |
| 1 | 189 | | var entityFilterAttribute = filteredType.GetCustomAttribute<EntityFilterAttribute>(); |
| | 190 | |
|
| 1 | 191 | | var queryParams = new List<string>(); |
| 8 | 192 | | foreach (var property in filterableProperties) |
| | 193 | | { |
| 3 | 194 | | var parameterName = HttpUtility.UrlEncode(property.GetFilterParameterName(entityFilterAttribute?.Prefix)); |
| 3 | 195 | | var propertyFilters = entityFilter.PropertyFilters.Where(x => x.PropertyName.EqualsOrdinal(property.Name)); |
| 14 | 196 | | foreach (var filter in propertyFilters) |
| | 197 | | { |
| 4 | 198 | | var values = string.Join(',', filter.ValueFilters.Select(v => HttpUtility.UrlEncode(v.ToString()))); |
| 4 | 199 | | queryParams.Add($"{parameterName}={values}"); |
| | 200 | | } |
| | 201 | | } |
| | 202 | |
|
| 1 | 203 | | return string.Join('&', queryParams); |
| | 204 | | } |
| | 205 | | } |