From 690e7f60e1aeea22103444d430a116fe94fe711e Mon Sep 17 00:00:00 2001 From: Sebastien Ros Date: Wed, 4 Sep 2013 12:40:59 -0700 Subject: [PATCH] Fixing field indexing with nullable or multiple values --- .../Core/Common/Drivers/TextFieldDriver.cs | 6 +-- .../Drivers/BooleanFieldDriver.cs | 4 +- .../Drivers/DateTimeFieldDriver.cs | 18 +++++--- .../Drivers/EnumerationFieldDriver.cs | 18 ++++---- .../Drivers/InputFieldDriver.cs | 3 +- .../Orchard.Fields/Drivers/LinkFieldDriver.cs | 3 +- .../Drivers/NumericFieldDriver.cs | 4 +- .../Handlers/InfosetFieldIndexingHandler.cs | 44 +++++++++++-------- .../DefinitionTemplates/FieldIndexing.cshtml | 9 ++-- .../Themes/TheAdmin/Styles/site.css | 2 +- .../Handlers/DescribeMembersContext.cs | 31 ++++++++++++- 11 files changed, 93 insertions(+), 49 deletions(-) diff --git a/src/Orchard.Web/Core/Common/Drivers/TextFieldDriver.cs b/src/Orchard.Web/Core/Common/Drivers/TextFieldDriver.cs index 7d6668644..2fcfb4c84 100644 --- a/src/Orchard.Web/Core/Common/Drivers/TextFieldDriver.cs +++ b/src/Orchard.Web/Core/Common/Drivers/TextFieldDriver.cs @@ -1,5 +1,4 @@ -using System; -using System.Collections.Generic; +using System.Collections.Generic; using System.Linq; using System.Web; using JetBrains.Annotations; @@ -91,7 +90,8 @@ namespace Orchard.Core.Common.Drivers { protected override void Describe(DescribeMembersContext context) { context - .Member(null, typeof(string), T("Value"), T("The text associated with the field.")); + .Member(null, typeof(string), T("Value"), T("The text associated with the field.")) + .Enumerate(() => field => new[] { field.Value }); } } } \ No newline at end of file diff --git a/src/Orchard.Web/Modules/Orchard.Fields/Drivers/BooleanFieldDriver.cs b/src/Orchard.Web/Modules/Orchard.Fields/Drivers/BooleanFieldDriver.cs index ba4e2d1dc..7b0de3e1b 100644 --- a/src/Orchard.Web/Modules/Orchard.Fields/Drivers/BooleanFieldDriver.cs +++ b/src/Orchard.Web/Modules/Orchard.Fields/Drivers/BooleanFieldDriver.cs @@ -65,7 +65,9 @@ namespace Orchard.Fields.Drivers { protected override void Describe(DescribeMembersContext context) { context - .Member(null, typeof(Boolean), T("Value"), T("The boolean value of the field.")); + .Member(null, typeof(Boolean), T("Value"), T("The boolean value of the field.")) + .Enumerate(() => field => new [] { field.Value }) + ; } } } diff --git a/src/Orchard.Web/Modules/Orchard.Fields/Drivers/DateTimeFieldDriver.cs b/src/Orchard.Web/Modules/Orchard.Fields/Drivers/DateTimeFieldDriver.cs index 0d18e0ae2..33cf8c14f 100644 --- a/src/Orchard.Web/Modules/Orchard.Fields/Drivers/DateTimeFieldDriver.cs +++ b/src/Orchard.Web/Modules/Orchard.Fields/Drivers/DateTimeFieldDriver.cs @@ -4,6 +4,7 @@ using System.Xml; using JetBrains.Annotations; using Orchard.ContentManagement; using Orchard.ContentManagement.Drivers; +using Orchard.Fields.Fields; using Orchard.Fields.Settings; using Orchard.Fields.ViewModels; using Orchard.ContentManagement.Handlers; @@ -11,7 +12,7 @@ using Orchard.Localization; namespace Orchard.Fields.Drivers { [UsedImplicitly] - public class DateTimeFieldDriver : ContentFieldDriver { + public class DateTimeFieldDriver : ContentFieldDriver { public IOrchardServices Services { get; set; } private const string TemplateName = "Fields/DateTime.Edit"; // EditorTemplates/Fields/DateTime.Edit.cshtml private readonly Lazy _cultureInfo; @@ -33,7 +34,7 @@ namespace Orchard.Fields.Drivers { return field.Name; } - protected override DriverResult Display(ContentPart part, Fields.DateTimeField field, string displayType, dynamic shapeHelper) { + protected override DriverResult Display(ContentPart part, DateTimeField field, string displayType, dynamic shapeHelper) { return ContentShape("Fields_DateTime", // this is just a key in the Shape Table GetDifferentiator(field, part), () => { @@ -57,7 +58,7 @@ namespace Orchard.Fields.Drivers { ); } - protected override DriverResult Editor(ContentPart part, Fields.DateTimeField field, dynamic shapeHelper) { + protected override DriverResult Editor(ContentPart part, DateTimeField field, dynamic shapeHelper) { var settings = field.PartFieldDefinition.Settings.GetModel(); var value = field.DateTime; @@ -76,7 +77,7 @@ namespace Orchard.Fields.Drivers { () => shapeHelper.EditorTemplate(TemplateName: TemplateName, Model: viewModel, Prefix: GetPrefix(field, part))); } - protected override DriverResult Editor(ContentPart part, Fields.DateTimeField field, IUpdateModel updater, dynamic shapeHelper) { + protected override DriverResult Editor(ContentPart part, DateTimeField field, IUpdateModel updater, dynamic shapeHelper) { var viewModel = new DateTimeFieldViewModel(); if(updater.TryUpdateModel(viewModel, GetPrefix(field, part), null, null)) { @@ -116,17 +117,20 @@ namespace Orchard.Fields.Drivers { return Editor(part, field, shapeHelper); } - protected override void Importing(ContentPart part, Fields.DateTimeField field, ImportContentContext context) { + protected override void Importing(ContentPart part, DateTimeField field, ImportContentContext context) { context.ImportAttribute(GetPrefix(field, part), "Value", v => field.Storage.Set(null, XmlConvert.ToDateTime(v, XmlDateTimeSerializationMode.Utc))); } - protected override void Exporting(ContentPart part, Fields.DateTimeField field, ExportContentContext context) { + protected override void Exporting(ContentPart part, DateTimeField field, ExportContentContext context) { context.Element(GetPrefix(field, part)).SetAttributeValue("Value", XmlConvert.ToString(field.Storage.Get(null), XmlDateTimeSerializationMode.Utc)); } protected override void Describe(DescribeMembersContext context) { context - .Member(null, typeof(DateTime), T("Value"), T("The date time value of the field.")); + .Member(null, typeof(DateTime), T("Value"), T("The date time value of the field.")) + .Enumerate(() => field => new[] { field.DateTime }) + ; + } } } diff --git a/src/Orchard.Web/Modules/Orchard.Fields/Drivers/EnumerationFieldDriver.cs b/src/Orchard.Web/Modules/Orchard.Fields/Drivers/EnumerationFieldDriver.cs index 8b6ec4d95..3d1607f39 100644 --- a/src/Orchard.Web/Modules/Orchard.Fields/Drivers/EnumerationFieldDriver.cs +++ b/src/Orchard.Web/Modules/Orchard.Fields/Drivers/EnumerationFieldDriver.cs @@ -1,15 +1,12 @@ -using System; -using Orchard; -using Orchard.ContentManagement; +using Orchard.ContentManagement; using Orchard.ContentManagement.Drivers; using Orchard.ContentManagement.Handlers; using Orchard.Fields.Settings; using Orchard.Fields.Fields; using Orchard.Localization; -using Orchard.Utility.Extensions; namespace Orchard.Fields.Drivers { - public class EnumerationFieldDriver : ContentFieldDriver { + public class EnumerationFieldDriver : ContentFieldDriver { public IOrchardServices Services { get; set; } private const string TemplateName = "Fields/Enumeration.Edit"; @@ -24,21 +21,21 @@ namespace Orchard.Fields.Drivers { return part.PartDefinition.Name + "." + field.Name; } - private static string GetDifferentiator(Fields.EnumerationField field, ContentPart part) { + private static string GetDifferentiator(EnumerationField field, ContentPart part) { return field.Name; } - protected override DriverResult Display(ContentPart part, Fields.EnumerationField field, string displayType, dynamic shapeHelper) { + protected override DriverResult Display(ContentPart part, EnumerationField field, string displayType, dynamic shapeHelper) { return ContentShape("Fields_Enumeration", GetDifferentiator(field, part), () => shapeHelper.Fields_Enumeration()); } - protected override DriverResult Editor(ContentPart part, Fields.EnumerationField field, dynamic shapeHelper) { + protected override DriverResult Editor(ContentPart part, EnumerationField field, dynamic shapeHelper) { return ContentShape("Fields_Enumeration_Edit", GetDifferentiator(field, part), () => shapeHelper.EditorTemplate(TemplateName: TemplateName, Model: field, Prefix: GetPrefix(field, part))); } - protected override DriverResult Editor(ContentPart part, Fields.EnumerationField field, IUpdateModel updater, dynamic shapeHelper) { + protected override DriverResult Editor(ContentPart part, EnumerationField field, IUpdateModel updater, dynamic shapeHelper) { if (updater.TryUpdateModel(field, GetPrefix(field, part), null, null)) { var settings = field.PartFieldDefinition.Settings.GetModel(); if (settings.Required && field.SelectedValues.Length == 0) { @@ -59,7 +56,8 @@ namespace Orchard.Fields.Drivers { protected override void Describe(DescribeMembersContext context) { context - .Member(null, typeof(string), T("Value"), T("The selected values of the field.")); + .Member(null, typeof(string), T("Value"), T("The selected values of the field.")) + .Enumerate(() => field => field.SelectedValues); } } } diff --git a/src/Orchard.Web/Modules/Orchard.Fields/Drivers/InputFieldDriver.cs b/src/Orchard.Web/Modules/Orchard.Fields/Drivers/InputFieldDriver.cs index f5788e007..aefd92b55 100644 --- a/src/Orchard.Web/Modules/Orchard.Fields/Drivers/InputFieldDriver.cs +++ b/src/Orchard.Web/Modules/Orchard.Fields/Drivers/InputFieldDriver.cs @@ -61,7 +61,8 @@ namespace Orchard.Fields.Drivers { protected override void Describe(DescribeMembersContext context) { context - .Member(null, typeof(string), T("Value"), T("The value of the field.")); + .Member(null, typeof(string), T("Value"), T("The value of the field.")) + .Enumerate(() => field => new[] { field.Value }); } } } diff --git a/src/Orchard.Web/Modules/Orchard.Fields/Drivers/LinkFieldDriver.cs b/src/Orchard.Web/Modules/Orchard.Fields/Drivers/LinkFieldDriver.cs index c1160cd81..24727c63f 100644 --- a/src/Orchard.Web/Modules/Orchard.Fields/Drivers/LinkFieldDriver.cs +++ b/src/Orchard.Web/Modules/Orchard.Fields/Drivers/LinkFieldDriver.cs @@ -70,7 +70,8 @@ namespace Orchard.Fields.Drivers { protected override void Describe(DescribeMembersContext context) { context .Member("Text", typeof(string), T("Text"), T("The text of the link.")) - .Member(null, typeof(string), T("Url"), T("The url of the link.")); + .Member(null, typeof(string), T("Url"), T("The url of the link.")) + .Enumerate(() => field => new[] { field.Value }); } } } diff --git a/src/Orchard.Web/Modules/Orchard.Fields/Drivers/NumericFieldDriver.cs b/src/Orchard.Web/Modules/Orchard.Fields/Drivers/NumericFieldDriver.cs index be6adbd9b..95114fe2b 100644 --- a/src/Orchard.Web/Modules/Orchard.Fields/Drivers/NumericFieldDriver.cs +++ b/src/Orchard.Web/Modules/Orchard.Fields/Drivers/NumericFieldDriver.cs @@ -108,7 +108,9 @@ namespace Orchard.Fields.Drivers { } protected override void Describe(DescribeMembersContext context) { - context.Member(null, typeof(decimal), T("Value"), T("The value of the field.")); + context + .Member(null, typeof(decimal), T("Value"), T("The value of the field.")) + .Enumerate (() => field => new[] { field.Value }); } } } diff --git a/src/Orchard.Web/Modules/Orchard.Indexing/Handlers/InfosetFieldIndexingHandler.cs b/src/Orchard.Web/Modules/Orchard.Indexing/Handlers/InfosetFieldIndexingHandler.cs index 6a34d0146..8359c5330 100644 --- a/src/Orchard.Web/Modules/Orchard.Indexing/Handlers/InfosetFieldIndexingHandler.cs +++ b/src/Orchard.Web/Modules/Orchard.Indexing/Handlers/InfosetFieldIndexingHandler.cs @@ -29,7 +29,6 @@ namespace Orchard.Indexing.Handlers { return; } - // part fields foreach ( var part in infosetPart.ContentItem.Parts ) { foreach ( var field in part.PartDefinition.Fields ) { @@ -43,29 +42,36 @@ namespace Orchard.Indexing.Handlers { ContentPart localPart = part; ContentPartFieldDefinition localField = field; - var membersContext = new DescribeMembersContext( - (storageName, storageType, displayName, description) => - { - var fieldStorage = _fieldStorageProvider.BindStorage(localPart, localField); + var fieldStorage = _fieldStorageProvider.BindStorage(localPart, localField); + var indexName = infosetPart.TypeDefinition.Name.ToLower() + "-" + field.Name.ToLower(); - // fieldStorage.Get(storageName) - var getter = typeof(IFieldStorage).GetMethod("Get").MakeGenericMethod(storageType); - var fieldValue = getter.Invoke(fieldStorage, new[] { storageName }); - var indexName = String.Format("{0}-{1}", infosetPart.TypeDefinition.Name.ToLower(), field.Name.ToLower()); + var membersContext = new DescribeMembersContext(fieldStorage, values => { - TypeCode typeCode = Type.GetTypeCode(storageType); + foreach (var value in values) { + + if (value == null) { + continue; + } + + var t = value.GetType(); + + // the T is nullable, convert using underlying type + if (t.IsGenericType && t.GetGenericTypeDefinition() == typeof(Nullable<>)) { + t = Nullable.GetUnderlyingType(t); + } - switch (typeCode) - { + var typeCode = Type.GetTypeCode(t); + + switch (typeCode) { case TypeCode.Empty: case TypeCode.Object: case TypeCode.DBNull: case TypeCode.String: case TypeCode.Char: - context.DocumentIndex.Add(indexName, Convert.ToString(fieldValue)).RemoveTags().Analyze(); + context.DocumentIndex.Add(indexName, Convert.ToString(value)).RemoveTags().Analyze(); break; case TypeCode.Boolean: - context.DocumentIndex.Add(indexName, Convert.ToBoolean(fieldValue)); + context.DocumentIndex.Add(indexName, Convert.ToBoolean(value)); break; case TypeCode.SByte: case TypeCode.Int16: @@ -74,19 +80,19 @@ namespace Orchard.Indexing.Handlers { case TypeCode.UInt32: case TypeCode.Int64: case TypeCode.UInt64: - context.DocumentIndex.Add(indexName, Convert.ToInt32(fieldValue)); + context.DocumentIndex.Add(indexName, Convert.ToInt32(value)); break; case TypeCode.Single: case TypeCode.Double: case TypeCode.Decimal: - context.DocumentIndex.Add(indexName, Convert.ToDouble(fieldValue)); + context.DocumentIndex.Add(indexName, Convert.ToDouble(value)); break; case TypeCode.DateTime: - context.DocumentIndex.Add(indexName, Convert.ToDateTime(fieldValue)); + context.DocumentIndex.Add(indexName, Convert.ToDateTime(value)); break; } - - }); + } + }); foreach (var driver in drivers) { driver.Describe(membersContext); diff --git a/src/Orchard.Web/Modules/Orchard.Indexing/Views/DefinitionTemplates/FieldIndexing.cshtml b/src/Orchard.Web/Modules/Orchard.Indexing/Views/DefinitionTemplates/FieldIndexing.cshtml index 86335ecd4..4929b751c 100644 --- a/src/Orchard.Web/Modules/Orchard.Indexing/Views/DefinitionTemplates/FieldIndexing.cshtml +++ b/src/Orchard.Web/Modules/Orchard.Indexing/Views/DefinitionTemplates/FieldIndexing.cshtml @@ -1,7 +1,10 @@ @model Orchard.Indexing.Settings.FieldIndexing
- @Html.EditorFor(m=>m.Included) - - @Html.ValidationMessageFor(m => m.Included) +
+ @Html.EditorFor(m=>m.Included) + + @Html.ValidationMessageFor(m => m.Included) + @T("Check to add content of this field in the selected indexes.") +
\ No newline at end of file diff --git a/src/Orchard.Web/Themes/TheAdmin/Styles/site.css b/src/Orchard.Web/Themes/TheAdmin/Styles/site.css index f74267f25..8aa3b04c2 100644 --- a/src/Orchard.Web/Themes/TheAdmin/Styles/site.css +++ b/src/Orchard.Web/Themes/TheAdmin/Styles/site.css @@ -631,7 +631,7 @@ select { select:focus, textarea:focus, input.text:focus, input.text-box:focus, input.text-small:focus, input.textMedium:focus { border-color:#666d51; } -input.check-box { +input.check-box, input[type=checkbox] { margin-left:0; vertical-align:-.1em; } diff --git a/src/Orchard/ContentManagement/Handlers/DescribeMembersContext.cs b/src/Orchard/ContentManagement/Handlers/DescribeMembersContext.cs index 27929727a..a3c0b70c5 100644 --- a/src/Orchard/ContentManagement/Handlers/DescribeMembersContext.cs +++ b/src/Orchard/ContentManagement/Handlers/DescribeMembersContext.cs @@ -1,12 +1,25 @@ using System; +using System.Collections; +using Orchard.ContentManagement.FieldStorage; using Orchard.Localization; namespace Orchard.ContentManagement.Handlers { public class DescribeMembersContext { private readonly Action _processMember; + private readonly IFieldStorage _storage; + private readonly Action _apply; - public DescribeMembersContext(Action processMember) { + public DescribeMembersContext(Action processMember) : this(processMember, null, null) { + } + + public DescribeMembersContext(IFieldStorage storage, Action apply) + : this(null, storage, apply) { + } + + public DescribeMembersContext(Action processMember, IFieldStorage storage, Action apply) { _processMember = processMember; + _storage = storage; + _apply = apply; } public DescribeMembersContext Member(string storageName, Type storageType) { @@ -18,7 +31,21 @@ namespace Orchard.ContentManagement.Handlers { } public DescribeMembersContext Member(string storageName, Type storageType, LocalizedString displayName, LocalizedString description) { - _processMember(storageName, storageType, displayName, description); + if (_processMember != null) { + _processMember(storageName, storageType, displayName, description); + } + return this; + } + + public DescribeMembersContext Enumerate(Func> enumerate) where TField : ContentField, new() { + + if (enumerate != null) { + var f = enumerate(); + var field = Activator.CreateInstance(); + field.Storage = _storage; + _apply(f(field)); + } + return this; } }