From f808aac4cdbd9034f48855c86305fada22f44542 Mon Sep 17 00:00:00 2001 From: Shannon Deminick Date: Mon, 6 May 2013 14:36:47 -1000 Subject: [PATCH] Fixes: #U4-644 - DynamicNode and MVC don't output RTE values for media --- src/Umbraco.Core/XmlHelper.cs | 4 +- src/Umbraco.Web.UI/Umbraco.Web.UI.csproj | 4 ++ .../config/ClientDependency.config | 2 +- .../XmlPublishedCache/PublishedMediaCache.cs | 13 +++-- src/UmbracoExamine/UmbracoContentIndexer.cs | 48 +++++++++++++++---- .../RazorDynamicNode/DynamicNode.cs | 6 +-- .../RazorDynamicNode/ExamineBackedMedia.cs | 6 ++- 7 files changed, 63 insertions(+), 20 deletions(-) diff --git a/src/Umbraco.Core/XmlHelper.cs b/src/Umbraco.Core/XmlHelper.cs index ff2a08b35b..60b3d85777 100644 --- a/src/Umbraco.Core/XmlHelper.cs +++ b/src/Umbraco.Core/XmlHelper.cs @@ -288,11 +288,11 @@ namespace Umbraco.Core /// public static bool CouldItBeXml(string xml) { - if (!string.IsNullOrEmpty(xml)) + if (string.IsNullOrEmpty(xml) == false) { xml = xml.Trim(); - if (xml.StartsWith("<") && xml.EndsWith(">")) + if (xml.StartsWith("<") && xml.EndsWith(">") && xml.Contains("/")) { return true; } diff --git a/src/Umbraco.Web.UI/Umbraco.Web.UI.csproj b/src/Umbraco.Web.UI/Umbraco.Web.UI.csproj index e9cfbd1e30..12c989f9df 100644 --- a/src/Umbraco.Web.UI/Umbraco.Web.UI.csproj +++ b/src/Umbraco.Web.UI/Umbraco.Web.UI.csproj @@ -96,6 +96,10 @@ AllRules.ruleset + + {07fbc26b-2927-4a22-8d96-d644c667fecc} + UmbracoExamine + False ..\packages\ClientDependency.1.6.0.0\lib\ClientDependency.Core.dll diff --git a/src/Umbraco.Web.UI/config/ClientDependency.config b/src/Umbraco.Web.UI/config/ClientDependency.config index 8c7187dd63..f2bc1255b9 100644 --- a/src/Umbraco.Web.UI/config/ClientDependency.config +++ b/src/Umbraco.Web.UI/config/ClientDependency.config @@ -10,7 +10,7 @@ NOTES: * Compression/Combination/Minification is not enabled unless debug="false" is specified on the 'compiliation' element in the web.config * A new version will invalidate both client and server cache and create new persisted files --> - + diff --git a/src/Umbraco.Web/PublishedCache/XmlPublishedCache/PublishedMediaCache.cs b/src/Umbraco.Web/PublishedCache/XmlPublishedCache/PublishedMediaCache.cs index b42aae843b..1470cb4d89 100644 --- a/src/Umbraco.Web/PublishedCache/XmlPublishedCache/PublishedMediaCache.cs +++ b/src/Umbraco.Web/PublishedCache/XmlPublishedCache/PublishedMediaCache.cs @@ -322,9 +322,9 @@ namespace Umbraco.Web.PublishedCache.XmlPublishedCache //ok it doesn't exist, we might assume now that Examine didn't index this property because the index is not set up correctly //so before we go loading this from the database, we can check if the alias exists on the content type at all, this information //is cached so will be quicker to look up. - if (dd.Properties.Any(x => x.Alias == "__NodeTypeAlias")) + if (dd.Properties.Any(x => x.Alias == UmbracoContentIndexer.NodeTypeAliasFieldName)) { - var aliasesAndNames = ContentType.GetAliasesAndNames(dd.Properties.First(x => x.Alias.InvariantEquals("__NodeTypeAlias")).Value.ToString()); + var aliasesAndNames = ContentType.GetAliasesAndNames(dd.Properties.First(x => x.Alias.InvariantEquals(UmbracoContentIndexer.NodeTypeAliasFieldName)).Value.ToString()); if (aliasesAndNames != null) { if (!aliasesAndNames.ContainsKey(alias)) @@ -346,7 +346,12 @@ namespace Umbraco.Web.PublishedCache.XmlPublishedCache } } - return dd.Properties.FirstOrDefault(x => x.Alias.InvariantEquals(alias)); + //We've made it here which means that the value is stored in the Examine index. + //We are going to check for a special field however, that is because in some cases we store a 'Raw' + //value in the index such as for xml/html. + var rawValue = dd.Properties.FirstOrDefault(x => x.Alias.InvariantEquals(UmbracoContentIndexer.RawFieldPrefix + alias)); + return rawValue + ?? dd.Properties.FirstOrDefault(x => x.Alias.InvariantEquals(alias)); } /// @@ -471,7 +476,7 @@ namespace Umbraco.Web.PublishedCache.XmlPublishedCache ValidateAndSetProperty(valueDictionary, val => _sortOrder = int.Parse(val), "sortOrder"); ValidateAndSetProperty(valueDictionary, val => _name = val, "nodeName", "__nodeName"); ValidateAndSetProperty(valueDictionary, val => _urlName = val, "urlName"); - ValidateAndSetProperty(valueDictionary, val => _documentTypeAlias = val, "nodeTypeAlias", "__NodeTypeAlias"); + ValidateAndSetProperty(valueDictionary, val => _documentTypeAlias = val, "nodeTypeAlias", UmbracoContentIndexer.NodeTypeAliasFieldName); ValidateAndSetProperty(valueDictionary, val => _documentTypeId = int.Parse(val), "nodeType"); ValidateAndSetProperty(valueDictionary, val => _writerName = val, "writerName"); ValidateAndSetProperty(valueDictionary, val => _creatorName = val, "creatorName", "writerName"); //this is a bit of a hack fix for: U4-1132 diff --git a/src/UmbracoExamine/UmbracoContentIndexer.cs b/src/UmbracoExamine/UmbracoContentIndexer.cs index d5cca06462..c7a8db9551 100644 --- a/src/UmbracoExamine/UmbracoContentIndexer.cs +++ b/src/UmbracoExamine/UmbracoContentIndexer.cs @@ -11,6 +11,8 @@ using System.Xml.Linq; using Examine; using Examine.Config; using Examine.Providers; +using Lucene.Net.Documents; +using Umbraco.Core; using umbraco.cms.businesslogic; using UmbracoExamine.DataServices; using Examine.LuceneEngine; @@ -69,6 +71,11 @@ namespace UmbracoExamine public const string IndexPathFieldName = "__Path"; public const string NodeTypeAliasFieldName = "__NodeTypeAlias"; + /// + /// The prefix added to a field when it is duplicated in order to store the original raw value. + /// + public const string RawFieldPrefix = "__Raw_"; + /// /// A type that defines the type of index for each Umbraco field (non user defined fields) /// Alot of standard umbraco fields shouldn't be tokenized or even indexed, just stored into lucene @@ -169,11 +176,25 @@ namespace UmbracoExamine base.OnIndexingError(e); } - //protected override void OnDocumentWriting(DocumentWritingEventArgs docArgs) - //{ - // DataService.LogService.AddVerboseLog(docArgs.NodeId, string.Format("({0}) DocumentWriting event for node ({1})", this.Name, LuceneIndexFolder.FullName)); - // base.OnDocumentWriting(docArgs); - //} + /// + /// This ensures that the special __Raw_ fields are indexed + /// + /// + protected override void OnDocumentWriting(DocumentWritingEventArgs docArgs) + { + var d = docArgs.Document; + foreach (var f in docArgs.Fields.Where(x => x.Key.StartsWith(RawFieldPrefix))) + { + d.Add(new Field( + f.Key, + f.Value, + Field.Store.YES, + Field.Index.NO, //don't index this field, we never want to search by it + Field.TermVector.NO)); + } + + base.OnDocumentWriting(docArgs); + } protected override void OnNodeIndexed(IndexedNodeEventArgs e) { @@ -282,13 +303,22 @@ namespace UmbracoExamine /// protected override void OnGatheringNodeData(IndexingNodeDataEventArgs e) { - //strip html of all users fields + //strip html of all users fields if we detect it has HTML in it. + //if that is the case, we'll create a duplicate 'raw' copy of it so that we can return + //the value of the field 'as-is'. // Get all user data that we want to index and store into a dictionary foreach (var field in IndexerData.UserFields) { if (e.Fields.ContainsKey(field.Name)) { - e.Fields[field.Name] = DataService.ContentService.StripHtml(e.Fields[field.Name]); + //check if the field value has html + if (XmlHelper.CouldItBeXml(e.Fields[field.Name])) + { + //First save the raw value to a raw field, we will change the policy of this field by detecting the prefix later + e.Fields[RawFieldPrefix + field.Name] = e.Fields[field.Name]; + //now replace the original value with the stripped html + e.Fields[field.Name] = DataService.ContentService.StripHtml(e.Fields[field.Name]); + } } } @@ -365,8 +395,8 @@ namespace UmbracoExamine /// protected override FieldIndexTypes GetPolicy(string fieldName) { - var def = IndexFieldPolicies.Where(x => x.Name == fieldName); - return (!def.Any() ? FieldIndexTypes.ANALYZED : def.Single().IndexType); + var def = IndexFieldPolicies.Where(x => x.Name == fieldName).ToArray(); + return (def.Any() == false ? FieldIndexTypes.ANALYZED : def.Single().IndexType); } /// diff --git a/src/umbraco.MacroEngines/RazorDynamicNode/DynamicNode.cs b/src/umbraco.MacroEngines/RazorDynamicNode/DynamicNode.cs index 23385093d8..dfed1641f6 100644 --- a/src/umbraco.MacroEngines/RazorDynamicNode/DynamicNode.cs +++ b/src/umbraco.MacroEngines/RazorDynamicNode/DynamicNode.cs @@ -790,7 +790,7 @@ namespace umbraco.MacroEngines if (result != null) { //a really rough check to see if this may be valid xml - if (sResult.StartsWith("<") && sResult.EndsWith(">") && sResult.Contains("/")) + if (XmlHelper.CouldItBeXml(sResult)) { try { @@ -800,8 +800,8 @@ namespace umbraco.MacroEngines //check that the document element is not one of the disallowed elements //allows RTE to still return as html if it's valid xhtml string documentElement = e.Name.LocalName; - if (!UmbracoSettings.NotDynamicXmlDocumentElements.Any(tag => - string.Equals(tag, documentElement, StringComparison.CurrentCultureIgnoreCase))) + if (UmbracoSettings.NotDynamicXmlDocumentElements.Any(tag => + string.Equals(tag, documentElement, StringComparison.CurrentCultureIgnoreCase)) == false) { result = new DynamicXml(e); return true; diff --git a/src/umbraco.MacroEngines/RazorDynamicNode/ExamineBackedMedia.cs b/src/umbraco.MacroEngines/RazorDynamicNode/ExamineBackedMedia.cs index 8a1dd6a88b..1e929aebbe 100644 --- a/src/umbraco.MacroEngines/RazorDynamicNode/ExamineBackedMedia.cs +++ b/src/umbraco.MacroEngines/RazorDynamicNode/ExamineBackedMedia.cs @@ -467,11 +467,15 @@ namespace umbraco.MacroEngines public IProperty GetProperty(string alias, out bool propertyExists) { string value = null; - if (Values.TryGetValue(alias, out value)) + + //First, try to get the 'raw' value, if that doesn't work try to get the normal one + if (Values.TryGetValue(UmbracoContentIndexer.RawFieldPrefix + alias, out value) + || Values.TryGetValue(alias, out value)) { propertyExists = true; return new PropertyResult(alias, value, Guid.Empty); } + propertyExists = false; return null; }