From ce9be79ec689cffc950d5aed7f29fe31cc60083b Mon Sep 17 00:00:00 2001 From: Shannon Deminick Date: Sat, 8 Sep 2012 11:59:01 +0700 Subject: [PATCH] Added the Examine Search methods to DynamicDocument as extension methods. Renamed a few things. --- .../Dynamics/DynamicBackingItem.cs | 2 +- src/Umbraco.Core/Dynamics/DynamicDocument.cs | 34 ++++---- src/Umbraco.Core/Dynamics/PropertyResult.cs | 17 +--- .../Dynamics/PropertyResultType.cs | 23 ++++++ src/Umbraco.Core/Umbraco.Core.csproj | 1 + .../DynamicDocumentSearchExtensions.cs | 82 +++++++++++++++++++ ...er.cs => PublishedContentStoreResolver.cs} | 4 +- src/Umbraco.Web/Umbraco.Web.csproj | 3 +- src/Umbraco.Web/UmbracoModule.cs | 4 +- src/Umbraco.Web/WebBootManager.cs | 2 +- src/Umbraco.Web/XmlPublishedContentStore.cs | 35 +++++--- .../RazorDynamicNode/DynamicNode.cs | 2 +- .../RazorDynamicNode/ExamineSearchUtill.cs | 19 ++--- .../RazorDynamicNode/RazorLibraryCore.cs | 4 +- 14 files changed, 168 insertions(+), 64 deletions(-) create mode 100644 src/Umbraco.Core/Dynamics/PropertyResultType.cs create mode 100644 src/Umbraco.Web/DynamicDocumentSearchExtensions.cs rename src/Umbraco.Web/{ContentStoreResolver.cs => PublishedContentStoreResolver.cs} (72%) diff --git a/src/Umbraco.Core/Dynamics/DynamicBackingItem.cs b/src/Umbraco.Core/Dynamics/DynamicBackingItem.cs index d3220682a9..f80b204bd4 100644 --- a/src/Umbraco.Core/Dynamics/DynamicBackingItem.cs +++ b/src/Umbraco.Core/Dynamics/DynamicBackingItem.cs @@ -113,7 +113,7 @@ namespace Umbraco.Core.Dynamics return prop == null ? null - : new PropertyResult(prop) + : new PropertyResult(prop, PropertyResultType.UserProperty) { DocumentTypeAlias = content.DocumentTypeAlias, DocumentId = content.Id diff --git a/src/Umbraco.Core/Dynamics/DynamicDocument.cs b/src/Umbraco.Core/Dynamics/DynamicDocument.cs index 64795205db..cb8546b15b 100644 --- a/src/Umbraco.Core/Dynamics/DynamicDocument.cs +++ b/src/Umbraco.Core/Dynamics/DynamicDocument.cs @@ -13,7 +13,7 @@ using System.Xml.Linq; namespace Umbraco.Core.Dynamics { - + /// /// The dynamic model for views /// @@ -105,7 +105,7 @@ namespace Umbraco.Core.Dynamics return DynamicDocumentWalker.Sibling(this, nodeTypeAlias); } - //public DynamicNodeList XPath(string xPath) + //public DynamicDocumentList XPath(string xPath) //{ // //if this DN was initialized with an underlying NodeFactory.Node // if (n != null && n.Type == DynamicBackingItemType.Content) @@ -122,7 +122,7 @@ namespace Umbraco.Core.Dynamics // if (n.Id == 0) // { // List selfList = new List() { this }; - // return new DynamicNodeList(selfList); + // return new DynamicDocumentList(selfList); // } // XmlNode node = doc.SelectSingleNode(string.Format("//*[@id='{0}']", n.Id)); // if (node != null) @@ -142,7 +142,7 @@ namespace Umbraco.Core.Dynamics // } // catch (Exception) { } //swallow the exceptions - the returned nodes might not be full nodes, e.g. property // } - // //Wanted to do this, but because we return DynamicNodeList here, the only + // //Wanted to do this, but because we return DynamicDocumentList here, the only // //common parent class is DynamicObject // //maybe some future refactoring will solve this? // //if (nodeFactoryNodeList.Count == 0) @@ -152,13 +152,13 @@ namespace Umbraco.Core.Dynamics // // //return // // return new DynamicXml(xElement); // //} - // //convert the NodeFactory nodelist to IEnumerable and return it as a DynamicNodeList - // return new DynamicNodeList(nodeFactoryNodeList.ConvertAll(nfNode => new DynamicNode((INode)nfNode))); + // //convert the NodeFactory nodelist to IEnumerable and return it as a DynamicDocumentList + // return new DynamicDocumentList(nodeFactoryNodeList.ConvertAll(nfNode => new DynamicNode((INode)nfNode))); // } // else // { - // // XPath returned no nodes, return an empty DynamicNodeList - // return new DynamicNodeList(); + // // XPath returned no nodes, return an empty DynamicDocumentList + // return new DynamicDocumentList(); // } // } // else @@ -178,7 +178,7 @@ namespace Umbraco.Core.Dynamics //} - //public DynamicNodeList Search(string term, bool useWildCards = true, string searchProvider = null) + //public DynamicDocumentList Search(string term, bool useWildCards = true, string searchProvider = null) //{ // var searcher = Examine.ExamineManager.Instance.DefaultSearchProvider; // if(!string.IsNullOrEmpty(searchProvider)) @@ -194,12 +194,12 @@ namespace Umbraco.Core.Dynamics // return Search(crit, searcher); //} - //public DynamicNodeList SearchDescendants(string term, bool useWildCards = true, string searchProvider = null) + //public DynamicDocumentList SearchDescendants(string term, bool useWildCards = true, string searchProvider = null) //{ // return Search(term, useWildCards, searchProvider); //} - //public DynamicNodeList SearchChildren(string term, bool useWildCards = true, string searchProvider = null) + //public DynamicDocumentList SearchChildren(string term, bool useWildCards = true, string searchProvider = null) //{ // var searcher = Examine.ExamineManager.Instance.DefaultSearchProvider; // if (!string.IsNullOrEmpty(searchProvider)) @@ -216,7 +216,7 @@ namespace Umbraco.Core.Dynamics //} - //public DynamicNodeList Search(Examine.SearchCriteria.ISearchCriteria criteria, Examine.Providers.BaseSearchProvider searchProvider = null) + //public DynamicDocumentList Search(Examine.SearchCriteria.ISearchCriteria criteria, Examine.Providers.BaseSearchProvider searchProvider = null) //{ // var s = Examine.ExamineManager.Instance.DefaultSearchProvider; // if (searchProvider != null) @@ -1147,12 +1147,12 @@ namespace Umbraco.Core.Dynamics } else { - throw new IndexOutOfRangeException(string.Format("Node {0} belongs to a DynamicNodeList but could not retrieve the index for it's position in the list", this.Id)); + throw new IndexOutOfRangeException(string.Format("Node {0} belongs to a DynamicDocumentList but could not retrieve the index for it's position in the list", this.Id)); } } else { - throw new ArgumentNullException(string.Format("Node {0} has been orphaned and doesn't belong to a DynamicNodeList", this.Id)); + throw new ArgumentNullException(string.Format("Node {0} has been orphaned and doesn't belong to a DynamicDocumentList", this.Id)); } } public bool IsFirst() @@ -1465,9 +1465,9 @@ namespace Umbraco.Core.Dynamics public bool Where(string predicate) { //Totally gonna cheat here - var dynamicNodeList = new DynamicDocumentList(); - dynamicNodeList.Add(this); - var filtered = dynamicNodeList.Where(predicate); + var dynamicDocumentList = new DynamicDocumentList(); + dynamicDocumentList.Add(this); + var filtered = dynamicDocumentList.Where(predicate); if (Queryable.Count(filtered) == 1) { //this node matches the predicate diff --git a/src/Umbraco.Core/Dynamics/PropertyResult.cs b/src/Umbraco.Core/Dynamics/PropertyResult.cs index c5ea656ebe..ebefc76ea5 100644 --- a/src/Umbraco.Core/Dynamics/PropertyResult.cs +++ b/src/Umbraco.Core/Dynamics/PropertyResult.cs @@ -5,29 +5,16 @@ using System.Web; namespace Umbraco.Core.Dynamics { - internal enum PropertyResultType - { - /// - /// The property resolved was a normal document property - /// - NormalProperty, - - /// - /// The property resolved was a property defined as a member on the document object (IDocument) itself - /// - ReflectedProperty - } - internal class PropertyResult : IDocumentProperty, IHtmlString { - public PropertyResult(IDocumentProperty source) + public PropertyResult(IDocumentProperty source, PropertyResultType type) { if (source == null) throw new ArgumentNullException("source"); Alias = source.Alias; Value = source.Value; Version = source.Version; - PropertyType = PropertyResultType.NormalProperty; + PropertyType = type; } public PropertyResult(string alias, object value, Guid version, PropertyResultType type) { diff --git a/src/Umbraco.Core/Dynamics/PropertyResultType.cs b/src/Umbraco.Core/Dynamics/PropertyResultType.cs new file mode 100644 index 0000000000..8475e7dba6 --- /dev/null +++ b/src/Umbraco.Core/Dynamics/PropertyResultType.cs @@ -0,0 +1,23 @@ +namespace Umbraco.Core.Dynamics +{ + /// + /// Currently just used for informational purposes as to where a PropertyResult object was created from. + /// + internal enum PropertyResultType + { + /// + /// The property resolved was a normal document property + /// + UserProperty, + + /// + /// The property resolved was a property defined as a member on the document object (IDocument) itself + /// + ReflectedProperty, + + /// + /// The property was created manually for a custom purpose + /// + CustomProperty + } +} \ No newline at end of file diff --git a/src/Umbraco.Core/Umbraco.Core.csproj b/src/Umbraco.Core/Umbraco.Core.csproj index b1c8606d1e..221f573c1f 100644 --- a/src/Umbraco.Core/Umbraco.Core.csproj +++ b/src/Umbraco.Core/Umbraco.Core.csproj @@ -84,6 +84,7 @@ + diff --git a/src/Umbraco.Web/DynamicDocumentSearchExtensions.cs b/src/Umbraco.Web/DynamicDocumentSearchExtensions.cs new file mode 100644 index 0000000000..8f9773bec9 --- /dev/null +++ b/src/Umbraco.Web/DynamicDocumentSearchExtensions.cs @@ -0,0 +1,82 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Xml; +using Examine; +using Examine.LuceneEngine.SearchCriteria; +using Umbraco.Core.Dynamics; + +namespace Umbraco.Web +{ + /// + /// DynamicDocument extension methods for searching using Examine + /// + public static class DynamicDocumentSearchExtensions + { + public static DynamicDocumentList Search(this DynamicDocument d, string term, bool useWildCards = true, string searchProvider = null) + { + var searcher = Examine.ExamineManager.Instance.DefaultSearchProvider; + if (!string.IsNullOrEmpty(searchProvider)) + searcher = Examine.ExamineManager.Instance.SearchProviderCollection[searchProvider]; + + var t = term.Escape().Value; + if (useWildCards) + t = term.MultipleCharacterWildcard().Value; + + string luceneQuery = "+__Path:(" + d.Path.Replace("-", "\\-") + "*) +" + t; + var crit = searcher.CreateSearchCriteria().RawQuery(luceneQuery); + + return d.Search(crit, searcher); + } + + public static DynamicDocumentList SearchDescendants(this DynamicDocument d, string term, bool useWildCards = true, string searchProvider = null) + { + return d.Search(term, useWildCards, searchProvider); + } + + public static DynamicDocumentList SearchChildren(this DynamicDocument d, string term, bool useWildCards = true, string searchProvider = null) + { + var searcher = Examine.ExamineManager.Instance.DefaultSearchProvider; + if (!string.IsNullOrEmpty(searchProvider)) + searcher = Examine.ExamineManager.Instance.SearchProviderCollection[searchProvider]; + + var t = term.Escape().Value; + if (useWildCards) + t = term.MultipleCharacterWildcard().Value; + + string luceneQuery = "+parentID:" + d.Id.ToString() + " +" + t; + var crit = searcher.CreateSearchCriteria().RawQuery(luceneQuery); + + return d.Search(crit, searcher); + } + + public static DynamicDocumentList Search(this DynamicDocument d, Examine.SearchCriteria.ISearchCriteria criteria, Examine.Providers.BaseSearchProvider searchProvider = null) + { + var s = Examine.ExamineManager.Instance.DefaultSearchProvider; + if (searchProvider != null) + s = searchProvider; + + var results = s.Search(criteria); + return ConvertSearchResultToDynamicNode(results); + } + + private static DynamicDocumentList ConvertSearchResultToDynamicNode(IEnumerable results) + { + var list = new DynamicDocumentList(); + var xd = new XmlDocument(); + + foreach (var result in results.OrderByDescending(x => x.Score)) + { + var doc = PublishedContentStoreResolver.Current.PublishedContentStore.GetDocumentById( + UmbracoContext.Current, + result.Id); + if (doc == null) continue; //skip if this doesn't exist in the cache + doc.Properties.Add( + new PropertyResult("examineScore", result.Score.ToString(), Guid.Empty, PropertyResultType.CustomProperty)); + var dynamicDoc = new DynamicDocument(doc); + list.Add(dynamicDoc); + } + return list; + } + } +} \ No newline at end of file diff --git a/src/Umbraco.Web/ContentStoreResolver.cs b/src/Umbraco.Web/PublishedContentStoreResolver.cs similarity index 72% rename from src/Umbraco.Web/ContentStoreResolver.cs rename to src/Umbraco.Web/PublishedContentStoreResolver.cs index 7e22beffba..e8450efe43 100644 --- a/src/Umbraco.Web/ContentStoreResolver.cs +++ b/src/Umbraco.Web/PublishedContentStoreResolver.cs @@ -5,9 +5,9 @@ namespace Umbraco.Web /// /// An object resolver to return the IContentStore /// - internal class ContentStoreResolver : SingleObjectResolverBase + internal class PublishedContentStoreResolver : SingleObjectResolverBase { - internal ContentStoreResolver(IPublishedContentStore publishedContentStore) + internal PublishedContentStoreResolver(IPublishedContentStore publishedContentStore) : base(publishedContentStore) { } diff --git a/src/Umbraco.Web/Umbraco.Web.csproj b/src/Umbraco.Web/Umbraco.Web.csproj index b8cddbfc82..5f723910fe 100644 --- a/src/Umbraco.Web/Umbraco.Web.csproj +++ b/src/Umbraco.Web/Umbraco.Web.csproj @@ -243,6 +243,7 @@ + ASPXCodeBehind @@ -271,7 +272,7 @@ - + diff --git a/src/Umbraco.Web/UmbracoModule.cs b/src/Umbraco.Web/UmbracoModule.cs index e7c0951723..b4c70bf6c1 100644 --- a/src/Umbraco.Web/UmbracoModule.cs +++ b/src/Umbraco.Web/UmbracoModule.cs @@ -55,13 +55,13 @@ namespace Umbraco.Web UmbracoContext.Current = umbracoContext; //create the nice urls - var niceUrls = new NiceUrlProvider(ContentStoreResolver.Current.PublishedContentStore, umbracoContext); + var niceUrls = new NiceUrlProvider(PublishedContentStoreResolver.Current.PublishedContentStore, umbracoContext); //create the RoutingContext var routingContext = new RoutingContext( umbracoContext, DocumentLookupsResolver.Current.DocumentLookups, LastChanceLookupResolver.Current.LastChanceLookup, - ContentStoreResolver.Current.PublishedContentStore, + PublishedContentStoreResolver.Current.PublishedContentStore, niceUrls); //assign the routing context back to the umbraco context umbracoContext.RoutingContext = routingContext; diff --git a/src/Umbraco.Web/WebBootManager.cs b/src/Umbraco.Web/WebBootManager.cs index a398b189c3..f045af6a89 100644 --- a/src/Umbraco.Web/WebBootManager.cs +++ b/src/Umbraco.Web/WebBootManager.cs @@ -133,7 +133,7 @@ namespace Umbraco.Web PropertyEditorValueConvertersResolver.Current.RemoveType(); PropertyEditorValueConvertersResolver.Current.AddType(); - ContentStoreResolver.Current = new ContentStoreResolver(new XmlPublishedContentStore()); + PublishedContentStoreResolver.Current = new PublishedContentStoreResolver(new XmlPublishedContentStore()); FilteredControllerFactoriesResolver.Current = new FilteredControllerFactoriesResolver( //add all known factories, devs can then modify this list on application startup either by binding to events diff --git a/src/Umbraco.Web/XmlPublishedContentStore.cs b/src/Umbraco.Web/XmlPublishedContentStore.cs index 6fb91ab891..8eec803f05 100644 --- a/src/Umbraco.Web/XmlPublishedContentStore.cs +++ b/src/Umbraco.Web/XmlPublishedContentStore.cs @@ -25,12 +25,17 @@ namespace Umbraco.Web } public IDocument GetDocumentById(UmbracoContext umbracoContext, int nodeId) - { - return ConvertToDocument(GetXml(umbracoContext).GetElementById(nodeId.ToString())); - } + { + if (umbracoContext == null) throw new ArgumentNullException("umbracoContext"); + + return ConvertToDocument(GetXml(umbracoContext).GetElementById(nodeId.ToString())); + } public IDocument GetDocumentByRoute(UmbracoContext umbracoContext, string route, bool? hideTopLevelNode = null) { + if (umbracoContext == null) throw new ArgumentNullException("umbracoContext"); + if (route == null) throw new ArgumentNullException("route"); + //set the default to be what is in the settings if (hideTopLevelNode == null) { @@ -57,8 +62,10 @@ namespace Umbraco.Web public IDocument GetDocumentByUrlAlias(UmbracoContext umbracoContext, int rootNodeId, string alias) { + if (umbracoContext == null) throw new ArgumentNullException("umbracoContext"); + if (alias == null) throw new ArgumentNullException("alias"); - // the alias may be "foo/bar" or "/foo/bar" + // the alias may be "foo/bar" or "/foo/bar" // there may be spaces as in "/foo/bar, /foo/nil" // these should probably be taken care of earlier on @@ -83,8 +90,12 @@ namespace Umbraco.Web //} public string GetDocumentProperty(UmbracoContext umbracoContext, IDocument node, string propertyAlias) - { - if (propertyAlias.StartsWith("@")) + { + if (umbracoContext == null) throw new ArgumentNullException("umbracoContext"); + if (node == null) throw new ArgumentNullException("node"); + if (propertyAlias == null) throw new ArgumentNullException("propertyAlias"); + + if (propertyAlias.StartsWith("@")) { //if it starts with an @ then its a property of the object, not a user defined property var propName = propertyAlias.TrimStart('@'); @@ -102,14 +113,16 @@ namespace Umbraco.Web //var propertyNode = node.SelectSingleNode("./" + propertyAlias); //return propertyNode == null ? null : propertyNode.InnerText; } - } + } + + XmlDocument GetXml(UmbracoContext umbracoContext) + { + if (umbracoContext == null) throw new ArgumentNullException("umbracoContext"); - XmlDocument GetXml(UmbracoContext umbracoContext) - { return umbracoContext.GetXml(); - } + } - static readonly char[] SlashChar = new char[] { '/' }; + static readonly char[] SlashChar = new char[] { '/' }; protected string CreateXpathQuery(int startNodeId, string path, bool hideTopLevelNodeFromPath) { diff --git a/src/umbraco.MacroEngines/RazorDynamicNode/DynamicNode.cs b/src/umbraco.MacroEngines/RazorDynamicNode/DynamicNode.cs index 15c292ca77..0eb82dfeb3 100644 --- a/src/umbraco.MacroEngines/RazorDynamicNode/DynamicNode.cs +++ b/src/umbraco.MacroEngines/RazorDynamicNode/DynamicNode.cs @@ -274,7 +274,7 @@ namespace umbraco.MacroEngines s = searchProvider; var results = s.Search(criteria); - return ExamineSearchUtill.convertSearchResultToDynamicNode(results); + return ExamineSearchUtill.ConvertSearchResultToDynamicNode(results); } diff --git a/src/umbraco.MacroEngines/RazorDynamicNode/ExamineSearchUtill.cs b/src/umbraco.MacroEngines/RazorDynamicNode/ExamineSearchUtill.cs index 9686ec8887..89fc4660d3 100644 --- a/src/umbraco.MacroEngines/RazorDynamicNode/ExamineSearchUtill.cs +++ b/src/umbraco.MacroEngines/RazorDynamicNode/ExamineSearchUtill.cs @@ -8,23 +8,20 @@ namespace umbraco.MacroEngines { class ExamineSearchUtill { - - internal static DynamicNodeList convertSearchResultToDynamicNode(Examine.ISearchResults results) + internal static DynamicNodeList ConvertSearchResultToDynamicNode(Examine.ISearchResults results) { - DynamicNodeList list = new DynamicNodeList(); - XmlDocument xd = new XmlDocument(); + var list = new DynamicNodeList(); + var xd = new XmlDocument(); foreach (var result in results.OrderByDescending(x => x.Score)) { var item = new DynamicBackingItem(result.Id); - if (item != null && item.Id != 0) - { - var node = (NodeFactory.Node)item.content; - XmlNode examineResultXml = xmlHelper.addTextNode(xd, "examineScore", result.Score.ToString()); - node.Properties.Add(new NodeFactory.Property(examineResultXml)); + if (item.Id == 0) continue; + var node = (NodeFactory.Node)item.content; + var examineResultXml = Umbraco.Core.XmlHelper.AddTextNode(xd, "examineScore", result.Score.ToString()); + node.Properties.Add(new NodeFactory.Property(examineResultXml)); - list.Add(new DynamicNode(item)); - } + list.Add(new DynamicNode(item)); } return list; } diff --git a/src/umbraco.MacroEngines/RazorDynamicNode/RazorLibraryCore.cs b/src/umbraco.MacroEngines/RazorDynamicNode/RazorLibraryCore.cs index dc156591d7..8aaeafec60 100644 --- a/src/umbraco.MacroEngines/RazorDynamicNode/RazorLibraryCore.cs +++ b/src/umbraco.MacroEngines/RazorDynamicNode/RazorLibraryCore.cs @@ -136,7 +136,7 @@ namespace umbraco.MacroEngines.Library searcher = Examine.ExamineManager.Instance.SearchProviderCollection[searchProvider]; var results = searcher.Search(term, useWildCards); - return ExamineSearchUtill.convertSearchResultToDynamicNode(results); + return ExamineSearchUtill.ConvertSearchResultToDynamicNode(results); } public dynamic Search(Examine.SearchCriteria.ISearchCriteria criteria, Examine.Providers.BaseSearchProvider searchProvider = null) @@ -146,7 +146,7 @@ namespace umbraco.MacroEngines.Library s = searchProvider; var results = s.Search(criteria); - return ExamineSearchUtill.convertSearchResultToDynamicNode(results); + return ExamineSearchUtill.ConvertSearchResultToDynamicNode(results); }