diff --git a/src/Umbraco.Examine/ContentValueSetValidator.cs b/src/Umbraco.Examine/ContentValueSetValidator.cs
index e78fe749db..46e4f48c9a 100644
--- a/src/Umbraco.Examine/ContentValueSetValidator.cs
+++ b/src/Umbraco.Examine/ContentValueSetValidator.cs
@@ -12,7 +12,7 @@ namespace Umbraco.Examine
///
/// Used to validate a ValueSet for content/media - based on permissions, parent id, etc....
///
- public class ContentValueSetValidator : ValueSetValidator
+ public class ContentValueSetValidator : ValueSetValidator, IContentValueSetValidator
{
private readonly IPublicAccessService _publicAccessService;
@@ -24,6 +24,46 @@ namespace Umbraco.Examine
public bool SupportProtectedContent { get; }
public int? ParentId { get; }
+ public bool ValidatePath(string path, string category)
+ {
+ //check if this document is a descendent of the parent
+ if (ParentId.HasValue && ParentId.Value > 0)
+ {
+ // we cannot return FAILED here because we need the value set to get into the indexer and then deal with it from there
+ // because we need to remove anything that doesn't pass by parent Id in the cases that umbraco data is moved to an illegal parent.
+ if (!path.Contains(string.Concat(",", ParentId.Value, ",")))
+ return false;
+ }
+
+ return true;
+ }
+
+ public bool ValidateRecycleBin(string path, string category)
+ {
+ var recycleBinId = category == IndexTypes.Content ? Constants.System.RecycleBinContent : Constants.System.RecycleBinMedia;
+
+ //check for recycle bin
+ if (!SupportUnpublishedContent)
+ {
+ if (path.Contains(string.Concat(",", recycleBinId, ",")))
+ return false;
+ }
+ return true;
+ }
+
+ public bool ValidateProtectedContent(string path, string category)
+ {
+ if (category == IndexTypes.Content
+ && !SupportProtectedContent
+ //if the service is null we can't look this up so we'll return false
+ && (_publicAccessService == null || _publicAccessService.IsProtected(path)))
+ {
+ return false;
+ }
+
+ return true;
+ }
+
public ContentValueSetValidator(bool supportUnpublishedContent, int? parentId = null,
IEnumerable includeItemTypes = null, IEnumerable excludeItemTypes = null)
: this(supportUnpublishedContent, true, null, parentId, includeItemTypes, excludeItemTypes)
@@ -41,19 +81,22 @@ namespace Umbraco.Examine
_publicAccessService = publicAccessService;
}
- public override bool Validate(ValueSet valueSet)
+ public override ValueSetValidationResult Validate(ValueSet valueSet)
{
- if (!base.Validate(valueSet))
- return false;
+ var baseValidate = base.Validate(valueSet);
+ if (baseValidate == ValueSetValidationResult.Failed)
+ return ValueSetValidationResult.Failed;
+
+ var isFiltered = baseValidate == ValueSetValidationResult.Filtered;
//check for published content
if (valueSet.Category == IndexTypes.Content && !SupportUnpublishedContent)
{
if (!valueSet.Values.TryGetValue(UmbracoExamineIndexer.PublishedFieldName, out var published))
- return false;
+ return ValueSetValidationResult.Failed;
if (!published[0].Equals(1))
- return false;
+ return ValueSetValidationResult.Failed;
//deal with variants, if there are unpublished variants than we need to remove them from the value set
if (valueSet.Values.TryGetValue(UmbracoContentIndexer.VariesByCultureFieldName, out var variesByCulture)
@@ -69,6 +112,7 @@ namespace Umbraco.Examine
foreach (var cultureField in valueSet.Values.Where(x => x.Key.InvariantEndsWith(cultureSuffix)).ToList())
{
valueSet.Values.Remove(cultureField.Key);
+ isFiltered = true;
}
}
}
@@ -76,37 +120,21 @@ namespace Umbraco.Examine
}
//must have a 'path'
- if (!valueSet.Values.TryGetValue(PathKey, out var pathValues)) return false;
- if (pathValues.Count == 0) return false;
- if (pathValues[0] == null) return false;
- if (pathValues[0].ToString().IsNullOrWhiteSpace()) return false;
+ if (!valueSet.Values.TryGetValue(PathKey, out var pathValues)) return ValueSetValidationResult.Failed;
+ if (pathValues.Count == 0) return ValueSetValidationResult.Failed;
+ if (pathValues[0] == null) return ValueSetValidationResult.Failed;
+ if (pathValues[0].ToString().IsNullOrWhiteSpace()) return ValueSetValidationResult.Failed;
var path = pathValues[0].ToString();
- // return nothing if we're not supporting protected content and it is protected, and we're not supporting unpublished content
- if (valueSet.Category == IndexTypes.Content
- && !SupportProtectedContent
- //if the service is null we can't look this up so we'll return false
- && (_publicAccessService == null || _publicAccessService.IsProtected(path)))
- {
- return false;
- }
+ // We need to validate the path of the content based on ParentId, protected content and recycle bin rules.
+ // We cannot return FAILED here because we need the value set to get into the indexer and then deal with it from there
+ // because we need to remove anything that doesn't pass by protected content in the cases that umbraco data is moved to an illegal parent.
+ if (!ValidatePath(path, valueSet.Category)
+ || !ValidateRecycleBin(path, valueSet.Category)
+ || !ValidateProtectedContent(path, valueSet.Category))
+ return ValueSetValidationResult.Filtered;
- //check if this document is a descendent of the parent
- if (ParentId.HasValue && ParentId.Value > 0)
- {
- if (!path.Contains(string.Concat(",", ParentId.Value, ",")))
- return false;
- }
-
- //check for recycle bin
- if (!SupportUnpublishedContent)
- {
- var recycleBinId = valueSet.Category == IndexTypes.Content ? Constants.System.RecycleBinContent : Constants.System.RecycleBinMedia;
- if (path.Contains(string.Concat(",", recycleBinId, ",")))
- return false;
- }
-
- return true;
+ return isFiltered ? ValueSetValidationResult.Filtered: ValueSetValidationResult.Valid;
}
}
}
diff --git a/src/Umbraco.Examine/IContentValueSetValidator.cs b/src/Umbraco.Examine/IContentValueSetValidator.cs
new file mode 100644
index 0000000000..a7164773bb
--- /dev/null
+++ b/src/Umbraco.Examine/IContentValueSetValidator.cs
@@ -0,0 +1,18 @@
+using Examine;
+
+namespace Umbraco.Examine
+{
+ ///
+ /// An extended for content indexes
+ ///
+ public interface IContentValueSetValidator : IValueSetValidator
+ {
+ bool SupportUnpublishedContent { get; }
+ bool SupportProtectedContent { get; }
+ int? ParentId { get; }
+
+ bool ValidatePath(string path, string category);
+ bool ValidateRecycleBin(string path, string category);
+ bool ValidateProtectedContent(string path, string category);
+ }
+}
diff --git a/src/Umbraco.Examine/IndexRebuilder.cs b/src/Umbraco.Examine/IndexRebuilder.cs
index 4c21f8416f..525b57cc7d 100644
--- a/src/Umbraco.Examine/IndexRebuilder.cs
+++ b/src/Umbraco.Examine/IndexRebuilder.cs
@@ -21,8 +21,8 @@ namespace Umbraco.Examine
public void RebuildIndexes(bool onlyEmptyIndexes)
{
var indexes = (onlyEmptyIndexes
- ? ExamineManager.IndexProviders.Values.Where(x => !x.IndexExists())
- : ExamineManager.IndexProviders.Values).ToArray();
+ ? ExamineManager.Indexes.Where(x => !x.IndexExists())
+ : ExamineManager.Indexes).ToArray();
foreach(var index in indexes)
index.CreateIndex(); // clear the index
diff --git a/src/Umbraco.Examine/Umbraco.Examine.csproj b/src/Umbraco.Examine/Umbraco.Examine.csproj
index cae45edcdb..d2336eedf4 100644
--- a/src/Umbraco.Examine/Umbraco.Examine.csproj
+++ b/src/Umbraco.Examine/Umbraco.Examine.csproj
@@ -48,7 +48,7 @@
-
+
@@ -64,6 +64,7 @@
+
diff --git a/src/Umbraco.Examine/UmbracoContentIndexer.cs b/src/Umbraco.Examine/UmbracoContentIndexer.cs
index ae6d607c63..1387357463 100644
--- a/src/Umbraco.Examine/UmbracoContentIndexer.cs
+++ b/src/Umbraco.Examine/UmbracoContentIndexer.cs
@@ -57,7 +57,7 @@ namespace Umbraco.Examine
Analyzer defaultAnalyzer,
ProfilingLogger profilingLogger,
ILocalizationService languageService,
- IValueSetValidator validator,
+ IContentValueSetValidator validator,
IReadOnlyDictionary> indexValueTypes = null)
: base(name, fieldDefinitions, luceneDirectory, defaultAnalyzer, profilingLogger, validator, indexValueTypes)
{
@@ -121,14 +121,50 @@ namespace Umbraco.Examine
//Using a singleton here, we can't inject this when using config based providers and we don't use this
//anywhere else in this class
Current.Services.PublicAccessService,
- parentId, ConfigIndexCriteria.IncludeItemTypes, ConfigIndexCriteria.ExcludeItemTypes);
+ parentId,
+ ConfigIndexCriteria.IncludeItemTypes, ConfigIndexCriteria.ExcludeItemTypes);
SupportSoftDelete = supportUnpublished;
}
#endregion
- #region Public methods
+ ///
+ /// Special check for invalid paths
+ ///
+ ///
+ ///
+ protected override void PerformIndexItems(IEnumerable values, Action onComplete)
+ {
+ var valid = true;
+
+ // ReSharper disable once PossibleMultipleEnumeration
+ foreach (var v in values)
+ {
+ if (v.Values.TryGetValue("path", out var paths) && paths.Count > 0 && paths[0] != null)
+ {
+ //we know this is an IContentValueSetValidator
+ var validator = (IContentValueSetValidator) ValueSetValidator;
+ var path = paths[0].ToString();
+
+ if (!validator.ValidatePath(path, v.Category)
+ || !validator.ValidateRecycleBin(path, v.Category)
+ || !validator.ValidateProtectedContent(path, v.Category))
+ {
+ //since the path is not valid we need to delete this item in case it exists in the index already and has now
+ //been moved to an invalid parent.
+ PerformDeleteFromIndex(v.Id, x => { /*noop*/ });
+ valid = false;
+ }
+ }
+ }
+
+ if (valid)
+ {
+ // ReSharper disable once PossibleMultipleEnumeration
+ base.PerformIndexItems(values, onComplete);
+ }
+ }
///
///
@@ -155,14 +191,11 @@ namespace Umbraco.Examine
//need to queue a delete item for each one found
foreach (var r in results)
{
- QueueIndexOperation(new IndexOperation(new ValueSet(r.Id, null), IndexOperationType.Delete));
+ QueueIndexOperation(new IndexOperation(new ValueSet(r.Id), IndexOperationType.Delete));
}
base.PerformDeleteFromIndex(nodeId, onComplete);
}
- #endregion
-
- #region Protected
///
/// Overridden to ensure that the variant system fields have the right value types
@@ -184,8 +217,6 @@ namespace Umbraco.Examine
return base.CreateFieldValueTypes(indexValueTypesFactory);
}
-
-
- #endregion
+
}
}
diff --git a/src/Umbraco.Examine/ValueSetValidator.cs b/src/Umbraco.Examine/ValueSetValidator.cs
index a0e926fed0..4db251c0f1 100644
--- a/src/Umbraco.Examine/ValueSetValidator.cs
+++ b/src/Umbraco.Examine/ValueSetValidator.cs
@@ -59,18 +59,20 @@ namespace Umbraco.Examine
///
public IEnumerable ExcludeFields { get; }
- public virtual bool Validate(ValueSet valueSet)
+ public virtual ValueSetValidationResult Validate(ValueSet valueSet)
{
if (ValidIndexCategories != null && !ValidIndexCategories.InvariantContains(valueSet.Category))
- return false;
+ return ValueSetValidationResult.Failed;
//check if this document is of a correct type of node type alias
if (IncludeItemTypes != null && !IncludeItemTypes.InvariantContains(valueSet.ItemType))
- return false;
+ return ValueSetValidationResult.Failed;
//if this node type is part of our exclusion list
if (ExcludeItemTypes != null && ExcludeItemTypes.InvariantContains(valueSet.ItemType))
- return false;
+ return ValueSetValidationResult.Failed;
+
+ var isFiltered = false;
//filter based on the fields provided (if any)
if (IncludeFields != null || ExcludeFields != null)
@@ -78,15 +80,21 @@ namespace Umbraco.Examine
foreach (var key in valueSet.Values.Keys.ToList())
{
if (IncludeFields != null && !IncludeFields.InvariantContains(key))
+ {
valueSet.Values.Remove(key); //remove any value with a key that doesn't match the inclusion list
+ isFiltered = true;
+ }
if (ExcludeFields != null && ExcludeFields.InvariantContains(key))
+ {
valueSet.Values.Remove(key); //remove any value with a key that matches the exclusion list
+ isFiltered = true;
+ }
+
}
}
-
- return true;
+ return isFiltered ? ValueSetValidationResult.Filtered : ValueSetValidationResult.Valid;
}
}
}
diff --git a/src/Umbraco.Tests/TestHelpers/Stubs/TestExamineManager.cs b/src/Umbraco.Tests/TestHelpers/Stubs/TestExamineManager.cs
index ac5671fceb..f8d48c5703 100644
--- a/src/Umbraco.Tests/TestHelpers/Stubs/TestExamineManager.cs
+++ b/src/Umbraco.Tests/TestHelpers/Stubs/TestExamineManager.cs
@@ -24,16 +24,20 @@ namespace Umbraco.Tests.TestHelpers.Stubs
//noop
}
- public IIndex GetIndex(string indexerName)
+ public bool TryGetIndex(string indexName, out IIndex index)
{
- return _indexers.TryGetValue(indexerName, out var indexer) ? indexer : null;
+ return _indexers.TryGetValue(indexName, out index);
}
- public ISearcher GetSearcher(string searcherName)
+ public bool TryGetSearcher(string searcherName, out ISearcher searcher)
{
- return _searchers.TryGetValue(searcherName, out var indexer) ? indexer : null;
+ return _searchers.TryGetValue(searcherName, out searcher);
}
+ public IEnumerable Indexes => _indexers.Values;
+
+ public IEnumerable RegisteredSearchers => _searchers.Values;
+
public IReadOnlyDictionary IndexProviders => _indexers;
}
}
diff --git a/src/Umbraco.Tests/Umbraco.Tests.csproj b/src/Umbraco.Tests/Umbraco.Tests.csproj
index 9e6a7734f3..6ddf99822b 100644
--- a/src/Umbraco.Tests/Umbraco.Tests.csproj
+++ b/src/Umbraco.Tests/Umbraco.Tests.csproj
@@ -77,7 +77,7 @@
-
+
1.8.9
diff --git a/src/Umbraco.Tests/UmbracoExamine/IndexInitializer.cs b/src/Umbraco.Tests/UmbracoExamine/IndexInitializer.cs
index e5d7598080..b478b8f8fc 100644
--- a/src/Umbraco.Tests/UmbracoExamine/IndexInitializer.cs
+++ b/src/Umbraco.Tests/UmbracoExamine/IndexInitializer.cs
@@ -151,7 +151,7 @@ namespace Umbraco.Tests.UmbracoExamine
Directory luceneDir,
Analyzer analyzer = null,
ILocalizationService languageService = null,
- IValueSetValidator validator = null)
+ IContentValueSetValidator validator = null)
{
if (languageService == null)
languageService = GetMockLocalizationService();
diff --git a/src/Umbraco.Tests/UmbracoExamine/UmbracoContentValueSetValidatorTests.cs b/src/Umbraco.Tests/UmbracoExamine/UmbracoContentValueSetValidatorTests.cs
index 0df4750051..6458cd2a80 100644
--- a/src/Umbraco.Tests/UmbracoExamine/UmbracoContentValueSetValidatorTests.cs
+++ b/src/Umbraco.Tests/UmbracoExamine/UmbracoContentValueSetValidatorTests.cs
@@ -19,14 +19,14 @@ namespace Umbraco.Tests.UmbracoExamine
{
var validator = new ContentValueSetValidator(true, true, Mock.Of());
- var result = validator.Validate(new ValueSet("555", IndexTypes.Content, new { hello = "world", path = "-1,555" }));
- Assert.IsTrue(result);
+ var result = validator.Validate(ValueSet.FromObject("555", IndexTypes.Content, new { hello = "world", path = "-1,555" }));
+ Assert.AreEqual(ValueSetValidationResult.Valid, result);
- result = validator.Validate(new ValueSet("777", IndexTypes.Media, new { hello = "world", path = "-1,555" }));
- Assert.IsTrue(result);
+ result = validator.Validate(ValueSet.FromObject("777", IndexTypes.Media, new { hello = "world", path = "-1,555" }));
+ Assert.AreEqual(ValueSetValidationResult.Valid, result);
- result = validator.Validate(new ValueSet("555", "invalid-category", new { hello = "world", path = "-1,555" }));
- Assert.IsFalse(result);
+ result = validator.Validate(ValueSet.FromObject("555", "invalid-category", new { hello = "world", path = "-1,555" }));
+ Assert.AreEqual(ValueSetValidationResult.Failed, result);
}
@@ -35,11 +35,11 @@ namespace Umbraco.Tests.UmbracoExamine
{
var validator = new ContentValueSetValidator(true, true, Mock.Of());
- var result = validator.Validate(new ValueSet("555", IndexTypes.Content, new { hello = "world" }));
- Assert.IsFalse(result);
+ var result = validator.Validate(ValueSet.FromObject("555", IndexTypes.Content, new { hello = "world" }));
+ Assert.AreEqual(ValueSetValidationResult.Failed, result);
- result = validator.Validate(new ValueSet("555", IndexTypes.Content, new { hello = "world", path = "-1,555" }));
- Assert.IsTrue(result);
+ result = validator.Validate(ValueSet.FromObject("555", IndexTypes.Content, new { hello = "world", path = "-1,555" }));
+ Assert.AreEqual(ValueSetValidationResult.Valid, result);
}
[Test]
@@ -47,17 +47,17 @@ namespace Umbraco.Tests.UmbracoExamine
{
var validator = new ContentValueSetValidator(true, true, Mock.Of(), 555);
- var result = validator.Validate(new ValueSet("555", IndexTypes.Content, new { hello = "world", path = "-1,555" }));
- Assert.IsFalse(result);
+ var result = validator.Validate(ValueSet.FromObject("555", IndexTypes.Content, new { hello = "world", path = "-1,555" }));
+ Assert.AreEqual(ValueSetValidationResult.Filtered, result);
- result = validator.Validate(new ValueSet("555", IndexTypes.Content, new { hello = "world", path = "-1,444" }));
- Assert.IsFalse(result);
+ result = validator.Validate(ValueSet.FromObject("555", IndexTypes.Content, new { hello = "world", path = "-1,444" }));
+ Assert.AreEqual(ValueSetValidationResult.Filtered, result);
- result = validator.Validate(new ValueSet("555", IndexTypes.Content, new { hello = "world", path = "-1,555,777" }));
- Assert.IsTrue(result);
+ result = validator.Validate(ValueSet.FromObject("555", IndexTypes.Content, new { hello = "world", path = "-1,555,777" }));
+ Assert.AreEqual(ValueSetValidationResult.Valid, result);
- result = validator.Validate(new ValueSet("555", IndexTypes.Content, new { hello = "world", path = "-1,555,777,999" }));
- Assert.IsTrue(result);
+ result = validator.Validate(ValueSet.FromObject("555", IndexTypes.Content, new { hello = "world", path = "-1,555,777,999" }));
+ Assert.AreEqual(ValueSetValidationResult.Valid, result);
}
[Test]
@@ -67,9 +67,9 @@ namespace Umbraco.Tests.UmbracoExamine
new[] { "hello", "world" },
null);
- var valueSet = new ValueSet("555", IndexTypes.Content, "test-content", new { hello = "world", path = "-1,555", world = "your oyster" });
+ var valueSet = ValueSet.FromObject("555", IndexTypes.Content, "test-content", new { hello = "world", path = "-1,555", world = "your oyster" });
var result = validator.Validate(valueSet);
- Assert.IsTrue(result);
+ Assert.AreEqual(ValueSetValidationResult.Filtered, result);
Assert.IsFalse(valueSet.Values.ContainsKey("path"));
Assert.IsTrue(valueSet.Values.ContainsKey("hello"));
@@ -83,9 +83,9 @@ namespace Umbraco.Tests.UmbracoExamine
null,
new[] { "hello", "world" });
- var valueSet = new ValueSet("555", IndexTypes.Content, "test-content", new { hello = "world", path = "-1,555", world = "your oyster" });
+ var valueSet = ValueSet.FromObject("555", IndexTypes.Content, "test-content", new { hello = "world", path = "-1,555", world = "your oyster" });
var result = validator.Validate(valueSet);
- Assert.IsTrue(result);
+ Assert.AreEqual(ValueSetValidationResult.Filtered, result);
Assert.IsTrue(valueSet.Values.ContainsKey("path"));
Assert.IsFalse(valueSet.Values.ContainsKey("hello"));
@@ -99,9 +99,9 @@ namespace Umbraco.Tests.UmbracoExamine
new[] { "hello", "world" },
new[] { "world" });
- var valueSet = new ValueSet("555", IndexTypes.Content, "test-content", new { hello = "world", path = "-1,555", world = "your oyster" });
+ var valueSet = ValueSet.FromObject("555", IndexTypes.Content, "test-content", new { hello = "world", path = "-1,555", world = "your oyster" });
var result = validator.Validate(valueSet);
- Assert.IsTrue(result);
+ Assert.AreEqual(ValueSetValidationResult.Filtered, result);
Assert.IsFalse(valueSet.Values.ContainsKey("path"));
Assert.IsTrue(valueSet.Values.ContainsKey("hello"));
@@ -114,14 +114,14 @@ namespace Umbraco.Tests.UmbracoExamine
var validator = new ContentValueSetValidator(true, true, Mock.Of(),
includeItemTypes: new List { "include-content" });
- var result = validator.Validate(new ValueSet("555", IndexTypes.Content, "test-content", new { hello = "world", path = "-1,555" }));
- Assert.IsFalse(result);
+ var result = validator.Validate(ValueSet.FromObject("555", IndexTypes.Content, "test-content", new { hello = "world", path = "-1,555" }));
+ Assert.AreEqual(ValueSetValidationResult.Failed, result);
- result = validator.Validate(new ValueSet("555", IndexTypes.Content, new { hello = "world", path = "-1,555" }));
- Assert.IsFalse(result);
+ result = validator.Validate(ValueSet.FromObject("555", IndexTypes.Content, new { hello = "world", path = "-1,555" }));
+ Assert.AreEqual(ValueSetValidationResult.Failed, result);
- result = validator.Validate(new ValueSet("555", IndexTypes.Content, "include-content", new { hello = "world", path = "-1,555" }));
- Assert.IsTrue(result);
+ result = validator.Validate(ValueSet.FromObject("555", IndexTypes.Content, "include-content", new { hello = "world", path = "-1,555" }));
+ Assert.AreEqual(ValueSetValidationResult.Valid, result);
}
[Test]
@@ -130,14 +130,14 @@ namespace Umbraco.Tests.UmbracoExamine
var validator = new ContentValueSetValidator(true, true, Mock.Of(),
excludeItemTypes: new List { "exclude-content" });
- var result = validator.Validate(new ValueSet("555", IndexTypes.Content, "test-content", new { hello = "world", path = "-1,555" }));
- Assert.IsTrue(result);
+ var result = validator.Validate(ValueSet.FromObject("555", IndexTypes.Content, "test-content", new { hello = "world", path = "-1,555" }));
+ Assert.AreEqual(ValueSetValidationResult.Valid, result);
- result = validator.Validate(new ValueSet("555", IndexTypes.Content, new { hello = "world", path = "-1,555" }));
- Assert.IsTrue(result);
+ result = validator.Validate(ValueSet.FromObject("555", IndexTypes.Content, new { hello = "world", path = "-1,555" }));
+ Assert.AreEqual(ValueSetValidationResult.Valid, result);
- result = validator.Validate(new ValueSet("555", IndexTypes.Content, "exclude-content", new { hello = "world", path = "-1,555" }));
- Assert.IsFalse(result);
+ result = validator.Validate(ValueSet.FromObject("555", IndexTypes.Content, "exclude-content", new { hello = "world", path = "-1,555" }));
+ Assert.AreEqual(ValueSetValidationResult.Failed, result);
}
[Test]
@@ -147,17 +147,17 @@ namespace Umbraco.Tests.UmbracoExamine
includeItemTypes: new List { "include-content", "exclude-content" },
excludeItemTypes: new List { "exclude-content" });
- var result = validator.Validate(new ValueSet("555", IndexTypes.Content, "test-content", new { hello = "world", path = "-1,555" }));
- Assert.IsFalse(result);
+ var result = validator.Validate(ValueSet.FromObject("555", IndexTypes.Content, "test-content", new { hello = "world", path = "-1,555" }));
+ Assert.AreEqual(ValueSetValidationResult.Failed, result);
- result = validator.Validate(new ValueSet("555", IndexTypes.Content, new { hello = "world", path = "-1,555" }));
- Assert.IsFalse(result);
+ result = validator.Validate(ValueSet.FromObject("555", IndexTypes.Content, new { hello = "world", path = "-1,555" }));
+ Assert.AreEqual(ValueSetValidationResult.Failed, result);
- result = validator.Validate(new ValueSet("555", IndexTypes.Content, "exclude-content", new { hello = "world", path = "-1,555" }));
- Assert.IsFalse(result);
+ result = validator.Validate(ValueSet.FromObject("555", IndexTypes.Content, "exclude-content", new { hello = "world", path = "-1,555" }));
+ Assert.AreEqual(ValueSetValidationResult.Failed, result);
- result = validator.Validate(new ValueSet("555", IndexTypes.Content, "include-content", new { hello = "world", path = "-1,555" }));
- Assert.IsTrue(result);
+ result = validator.Validate(ValueSet.FromObject("555", IndexTypes.Content, "include-content", new { hello = "world", path = "-1,555" }));
+ Assert.AreEqual(ValueSetValidationResult.Valid, result);
}
[Test]
@@ -165,14 +165,14 @@ namespace Umbraco.Tests.UmbracoExamine
{
var validator = new ContentValueSetValidator(false, false, Mock.Of());
- var result = validator.Validate(new ValueSet("555", IndexTypes.Content, new { hello = "world", path = "-1,-20,555" }));
- Assert.IsFalse(result);
+ var result = validator.Validate(ValueSet.FromObject("555", IndexTypes.Content, new { hello = "world", path = "-1,-20,555" }));
+ Assert.AreEqual(ValueSetValidationResult.Failed, result);
- result = validator.Validate(new ValueSet("555", IndexTypes.Content, new { hello = "world", path = "-1,-20,555,777" }));
- Assert.IsFalse(result);
+ result = validator.Validate(ValueSet.FromObject("555", IndexTypes.Content, new { hello = "world", path = "-1,-20,555,777" }));
+ Assert.AreEqual(ValueSetValidationResult.Failed, result);
- result = validator.Validate(new ValueSet("555", IndexTypes.Content, new { hello = "world", path = "-1,555" }));
- Assert.IsFalse(result);
+ result = validator.Validate(ValueSet.FromObject("555", IndexTypes.Content, new { hello = "world", path = "-1,555" }));
+ Assert.AreEqual(ValueSetValidationResult.Failed, result);
result = validator.Validate(new ValueSet("555", IndexTypes.Content,
new Dictionary
@@ -181,7 +181,7 @@ namespace Umbraco.Tests.UmbracoExamine
["path"] = "-1,555",
[UmbracoExamineIndexer.PublishedFieldName] = 1
}));
- Assert.IsTrue(result);
+ Assert.AreEqual(ValueSetValidationResult.Valid, result);
}
[Test]
@@ -189,15 +189,15 @@ namespace Umbraco.Tests.UmbracoExamine
{
var validator = new ContentValueSetValidator(false, false, Mock.Of());
- var result = validator.Validate(new ValueSet("555", IndexTypes.Media, new { hello = "world", path = "-1,-21,555" }));
- Assert.IsFalse(result);
+ var result = validator.Validate(ValueSet.FromObject("555", IndexTypes.Media, new { hello = "world", path = "-1,-21,555" }));
+ Assert.AreEqual(ValueSetValidationResult.Filtered, result);
- result = validator.Validate(new ValueSet("555", IndexTypes.Media, new { hello = "world", path = "-1,-21,555,777" }));
- Assert.IsFalse(result);
+ result = validator.Validate(ValueSet.FromObject("555", IndexTypes.Media, new { hello = "world", path = "-1,-21,555,777" }));
+ Assert.AreEqual(ValueSetValidationResult.Filtered, result);
+
+ result = validator.Validate(ValueSet.FromObject("555", IndexTypes.Media, new { hello = "world", path = "-1,555" }));
+ Assert.AreEqual(ValueSetValidationResult.Valid, result);
- result = validator.Validate(new ValueSet("555", IndexTypes.Media, new { hello = "world", path = "-1,555" }));
- Assert.IsTrue(result);
-
}
[Test]
@@ -205,8 +205,8 @@ namespace Umbraco.Tests.UmbracoExamine
{
var validator = new ContentValueSetValidator(false, true, Mock.Of());
- var result = validator.Validate(new ValueSet("555", IndexTypes.Content, new { hello = "world", path = "-1,555" }));
- Assert.IsFalse(result);
+ var result = validator.Validate(ValueSet.FromObject("555", IndexTypes.Content, new { hello = "world", path = "-1,555" }));
+ Assert.AreEqual(ValueSetValidationResult.Failed, result);
result = validator.Validate(new ValueSet("555", IndexTypes.Content,
new Dictionary
@@ -215,7 +215,7 @@ namespace Umbraco.Tests.UmbracoExamine
["path"] = "-1,555",
[UmbracoExamineIndexer.PublishedFieldName] = 0
}));
- Assert.IsFalse(result);
+ Assert.AreEqual(ValueSetValidationResult.Failed, result);
result = validator.Validate(new ValueSet("555", IndexTypes.Content,
new Dictionary
@@ -224,7 +224,7 @@ namespace Umbraco.Tests.UmbracoExamine
["path"] = "-1,555",
[UmbracoExamineIndexer.PublishedFieldName] = 1
}));
- Assert.IsTrue(result);
+ Assert.AreEqual(ValueSetValidationResult.Valid, result);
}
[Test]
@@ -240,7 +240,7 @@ namespace Umbraco.Tests.UmbracoExamine
[UmbracoContentIndexer.VariesByCultureFieldName] = 1,
[UmbracoExamineIndexer.PublishedFieldName] = 0
}));
- Assert.IsFalse(result);
+ Assert.AreEqual(ValueSetValidationResult.Failed, result);
result = validator.Validate(new ValueSet("555", IndexTypes.Content,
new Dictionary
@@ -250,7 +250,7 @@ namespace Umbraco.Tests.UmbracoExamine
[UmbracoContentIndexer.VariesByCultureFieldName] = 1,
[UmbracoExamineIndexer.PublishedFieldName] = 1
}));
- Assert.IsTrue(result);
+ Assert.AreEqual(ValueSetValidationResult.Valid, result);
var valueSet = new ValueSet("555", IndexTypes.Content,
new Dictionary
@@ -272,7 +272,7 @@ namespace Umbraco.Tests.UmbracoExamine
Assert.IsTrue(valueSet.Values.ContainsKey("title_es-ES"));
result = validator.Validate(valueSet);
- Assert.IsTrue(result);
+ Assert.AreEqual(ValueSetValidationResult.Filtered, result);
Assert.AreEqual(7, valueSet.Values.Count()); //filtered to 7 values (removes es-es values)
Assert.IsFalse(valueSet.Values.ContainsKey($"{UmbracoExamineIndexer.PublishedFieldName}_es-es"));
@@ -290,11 +290,11 @@ namespace Umbraco.Tests.UmbracoExamine
.Returns(Attempt.Fail());
var validator = new ContentValueSetValidator(true, false, publicAccessService.Object);
- var result = validator.Validate(new ValueSet("555", IndexTypes.Content, new { hello = "world", path = "-1,555" }));
- Assert.IsFalse(result);
+ var result = validator.Validate(ValueSet.FromObject("555", IndexTypes.Content, new { hello = "world", path = "-1,555" }));
+ Assert.AreEqual(ValueSetValidationResult.Filtered, result);
- result = validator.Validate(new ValueSet("777", IndexTypes.Content, new { hello = "world", path = "-1,777" }));
- Assert.IsTrue(result);
+ result = validator.Validate(ValueSet.FromObject("777", IndexTypes.Content, new { hello = "world", path = "-1,777" }));
+ Assert.AreEqual(ValueSetValidationResult.Valid, result);
}
}
}
diff --git a/src/Umbraco.Web.UI/Umbraco.Web.UI.csproj b/src/Umbraco.Web.UI/Umbraco.Web.UI.csproj
index 5f3b95844c..8278dac171 100644
--- a/src/Umbraco.Web.UI/Umbraco.Web.UI.csproj
+++ b/src/Umbraco.Web.UI/Umbraco.Web.UI.csproj
@@ -88,10 +88,9 @@
-
+
-
diff --git a/src/Umbraco.Web/Editors/EntityController.cs b/src/Umbraco.Web/Editors/EntityController.cs
index bf5181ba5e..31109485f6 100644
--- a/src/Umbraco.Web/Editors/EntityController.cs
+++ b/src/Umbraco.Web/Editors/EntityController.cs
@@ -15,6 +15,7 @@ using Umbraco.Core.Models;
using Constants = Umbraco.Core.Constants;
using Umbraco.Core.Persistence.DatabaseModelDefinitions;
using System.Web.Http.Controllers;
+using Examine;
using Umbraco.Core.Models.Entities;
using Umbraco.Core.Xml;
using Umbraco.Web.Models.Mapping;
@@ -53,12 +54,13 @@ namespace Umbraco.Web.Editors
}
}
- private readonly UmbracoTreeSearcher _treeSearcher = new UmbracoTreeSearcher();
+ private readonly UmbracoTreeSearcher _treeSearcher;
private readonly SearchableTreeCollection _searchableTreeCollection;
- public EntityController(SearchableTreeCollection searchableTreeCollection)
+ public EntityController(SearchableTreeCollection searchableTreeCollection, UmbracoTreeSearcher treeSearcher)
{
_searchableTreeCollection = searchableTreeCollection;
+ _treeSearcher = treeSearcher;
}
///
@@ -410,22 +412,18 @@ namespace Umbraco.Web.Editors
Direction orderDirection = Direction.Ascending,
string filter = "")
{
- int intId;
-
- if (int.TryParse(id, out intId))
+ if (int.TryParse(id, out var intId))
{
return GetPagedChildren(intId, type, pageNumber, pageSize, orderBy, orderDirection, filter);
}
- Guid guidId;
- if (Guid.TryParse(id, out guidId))
+ if (Guid.TryParse(id, out _))
{
//Not supported currently
throw new HttpResponseException(HttpStatusCode.NotFound);
}
- Udi udiId;
- if (Udi.TryParse(id, out udiId))
+ if (Udi.TryParse(id, out _))
{
//Not supported currently
throw new HttpResponseException(HttpStatusCode.NotFound);
@@ -443,8 +441,7 @@ namespace Umbraco.Web.Editors
//the EntityService cannot search members of a certain type, this is currently not supported and would require
//quite a bit of plumbing to do in the Services/Repository, we'll revert to a paged search
- long total;
- var searchResult = _treeSearcher.ExamineSearch(Umbraco, filter ?? "", type, pageSize, pageNumber - 1, out total, id);
+ var searchResult = _treeSearcher.ExamineSearch(filter ?? "", type, pageSize, pageNumber - 1, out long total, id);
return new PagedResult(total, pageNumber, pageSize)
{
@@ -480,8 +477,7 @@ namespace Umbraco.Web.Editors
var objectType = ConvertToObjectType(type);
if (objectType.HasValue)
{
- long totalRecords;
- var entities = Services.EntityService.GetPagedChildren(id, objectType.Value, pageNumber - 1, pageSize, out totalRecords, orderBy, orderDirection, filter);
+ var entities = Services.EntityService.GetPagedChildren(id, objectType.Value, pageNumber - 1, pageSize, out var totalRecords, orderBy, orderDirection, filter);
if (totalRecords == 0)
{
@@ -596,13 +592,9 @@ namespace Umbraco.Web.Editors
///
private IEnumerable ExamineSearch(string query, UmbracoEntityTypes entityType, string searchFrom = null)
{
- long total;
- return _treeSearcher.ExamineSearch(Umbraco, query, entityType, 200, 0, out total, searchFrom);
+ return _treeSearcher.ExamineSearch(query, entityType, 200, 0, out _, searchFrom);
}
-
-
-
private IEnumerable GetResultForChildren(int id, UmbracoEntityTypes entityType)
{
var objectType = ConvertToObjectType(entityType);
diff --git a/src/Umbraco.Web/Editors/ExamineManagementController.cs b/src/Umbraco.Web/Editors/ExamineManagementController.cs
index 999b5bd41e..c166162930 100644
--- a/src/Umbraco.Web/Editors/ExamineManagementController.cs
+++ b/src/Umbraco.Web/Editors/ExamineManagementController.cs
@@ -43,7 +43,7 @@ namespace Umbraco.Web.Editors
///
public IEnumerable GetIndexerDetails()
{
- return _examineManager.IndexProviders.Select(CreateModel).OrderBy(x => x.Name.TrimEnd("Indexer"));
+ return _examineManager.Indexes.Select(CreateModel).OrderBy(x => x.Name.TrimEnd("Indexer"));
}
///
@@ -53,32 +53,8 @@ namespace Umbraco.Web.Editors
public IEnumerable GetSearcherDetails()
{
var model = new List(
- _examineManager.IndexProviders.Select(indexer =>
- {
- var searcher = indexer.Value.GetSearcher();
- var searcherName = (searcher as BaseLuceneSearcher)?.Name ?? string.Concat(indexer.Key, "Searcher");
-
- var indexerModel = new ExamineSearcherModel
- {
- Name = searcherName
- };
- var props = TypeHelper.CachedDiscoverableProperties(searcher.GetType(), mustWrite: false)
- //ignore these properties
- .Where(x => new[] { "Description" }.InvariantContains(x.Name) == false)
- .Where(x => x.GetCustomAttribute()
- ?.State != EditorBrowsableState.Never)
- .OrderBy(x => x.Name);
- foreach (var p in props)
- {
- indexerModel.ProviderProperties.Add(p.Name, p.GetValue(searcher, null)?.ToString());
- }
-
- return indexerModel;
- }).OrderBy(x =>
- {
- //order by name , but strip the "Searcher" from the end if it exists
- return x.Name.TrimEnd("Searcher");
- }));
+ _examineManager.RegisteredSearchers.Select(searcher => new ExamineSearcherModel{Name = searcher.Name})
+ .OrderBy(x => x.Name.TrimEnd("Searcher"))); //order by name , but strip the "Searcher" from the end if it exists
return model;
}
@@ -138,7 +114,7 @@ namespace Umbraco.Web.Editors
//if its still there then it's not done
return found != null
? null
- : CreateModel(new KeyValuePair(indexName, index));
+ : CreateModel(index);
}
@@ -197,13 +173,12 @@ namespace Umbraco.Web.Editors
- private ExamineIndexModel CreateModel(KeyValuePair indexerKeyVal)
+ private ExamineIndexModel CreateModel(IIndex index)
{
- var indexer = indexerKeyVal.Value;
- var indexName = indexerKeyVal.Key;
+ var indexName = index.Name;
- if (!(indexer is IIndexDiagnostics indexDiag))
- indexDiag = new GenericIndexDiagnostics(indexer);
+ if (!(index is IIndexDiagnostics indexDiag))
+ indexDiag = new GenericIndexDiagnostics(index);
var isHealth = indexDiag.IsHealthy();
@@ -229,10 +204,10 @@ namespace Umbraco.Web.Editors
private HttpResponseMessage ValidateLuceneSearcher(string searcherName, out LuceneSearcher searcher)
{
- foreach (var indexer in _examineManager.IndexProviders)
+ foreach (var indexer in _examineManager.Indexes)
{
- var s = indexer.Value.GetSearcher();
- var sName = (s as BaseLuceneSearcher)?.Name ?? string.Concat(indexer.Key, "Searcher");
+ var s = indexer.GetSearcher();
+ var sName = (s as BaseLuceneSearcher)?.Name ?? string.Concat(indexer.Name, "Searcher");
if (sName != searcherName)
{
continue;
@@ -277,10 +252,9 @@ namespace Umbraco.Web.Editors
{
index = null;
- if (_examineManager.IndexProviders.ContainsKey(indexName))
+ if (_examineManager.TryGetIndex(indexName, out index))
{
//return Ok!
- index = _examineManager.GetIndex(indexName);
return Request.CreateResponse(HttpStatusCode.OK);
}
diff --git a/src/Umbraco.Web/IPublishedContentQuery.cs b/src/Umbraco.Web/IPublishedContentQuery.cs
index 055dcbe181..80af19c941 100644
--- a/src/Umbraco.Web/IPublishedContentQuery.cs
+++ b/src/Umbraco.Web/IPublishedContentQuery.cs
@@ -49,6 +49,6 @@ namespace Umbraco.Web
///
/// Searches content.
///
- IEnumerable Search(int skip, int take, out int totalRecords, Examine.SearchCriteria.ISearchCriteria criteria, Examine.ISearcher searchProvider = null);
+ IEnumerable Search(int skip, int take, out int totalRecords, Examine.SearchCriteria.ISearchCriteria criteria, Examine.ISearcher searcher = null);
}
}
diff --git a/src/Umbraco.Web/PublishedCache/XmlPublishedCache/PublishedMediaCache.cs b/src/Umbraco.Web/PublishedCache/XmlPublishedCache/PublishedMediaCache.cs
index 45f32353da..ccfe947515 100644
--- a/src/Umbraco.Web/PublishedCache/XmlPublishedCache/PublishedMediaCache.cs
+++ b/src/Umbraco.Web/PublishedCache/XmlPublishedCache/PublishedMediaCache.cs
@@ -240,8 +240,9 @@ namespace Umbraco.Web.PublishedCache.XmlPublishedCache
try
{
- //by default use the internal index
- return eMgr.GetSearcher(Constants.Examine.InternalIndexer);
+ if (eMgr.TryGetIndex(Constants.Examine.InternalIndexer, out var index))
+ return index.GetSearcher();
+ throw new InvalidOperationException($"No index found by name {Constants.Examine.InternalIndexer}");
}
catch (FileNotFoundException)
{
diff --git a/src/Umbraco.Web/PublishedContentExtensions.cs b/src/Umbraco.Web/PublishedContentExtensions.cs
index f0ddf62074..2bc0d7be3f 100644
--- a/src/Umbraco.Web/PublishedContentExtensions.cs
+++ b/src/Umbraco.Web/PublishedContentExtensions.cs
@@ -282,16 +282,15 @@ namespace Umbraco.Web
#region Search
- public static IEnumerable Search(this IPublishedContent content, string term, bool useWildCards = true, string indexName = null)
+ public static IEnumerable SearchDescendants(this IPublishedContent content, string term, bool useWildCards = true, string indexName = null)
{
- //TODO: we should pass in the IExamineManager?
+ //fixme: pass in the IExamineManager
- var searcher = string.IsNullOrEmpty(indexName)
- ? ExamineManager.Instance.GetSearcher(Constants.Examine.ExternalIndexer)
- : ExamineManager.Instance.GetSearcher(indexName);
+ indexName = string.IsNullOrEmpty(indexName) ? Constants.Examine.ExternalIndexer : indexName;
+ if (!ExamineManager.Instance.TryGetIndex(indexName, out var index))
+ throw new InvalidOperationException("No index found with name " + indexName);
- if (searcher == null)
- throw new InvalidOperationException("No searcher found for index " + indexName);
+ var searcher = index.GetSearcher();
var t = term.Escape().Value;
if (useWildCards)
@@ -303,21 +302,15 @@ namespace Umbraco.Web
return content.Search(crit, searcher);
}
- public static IEnumerable SearchDescendants(this IPublishedContent content, string term, bool useWildCards = true, string indexName = null)
- {
- return content.Search(term, useWildCards, indexName);
- }
-
public static IEnumerable SearchChildren(this IPublishedContent content, string term, bool useWildCards = true, string indexName = null)
{
- //TODO: we should pass in the IExamineManager?
+ //fixme: pass in the IExamineManager
- var searcher = string.IsNullOrEmpty(indexName)
- ? ExamineManager.Instance.GetSearcher(Constants.Examine.ExternalIndexer)
- : ExamineManager.Instance.GetSearcher(indexName);
+ indexName = string.IsNullOrEmpty(indexName) ? Constants.Examine.ExternalIndexer : indexName;
+ if (!ExamineManager.Instance.TryGetIndex(indexName, out var index))
+ throw new InvalidOperationException("No index found with name " + indexName);
- if (searcher == null)
- throw new InvalidOperationException("No searcher found for index " + indexName);
+ var searcher = index.GetSearcher();
var t = term.Escape().Value;
if (useWildCards)
@@ -329,13 +322,17 @@ namespace Umbraco.Web
return content.Search(crit, searcher);
}
- public static IEnumerable Search(this IPublishedContent content, Examine.SearchCriteria.ISearchCriteria criteria, Examine.ISearcher searchProvider = null)
+ public static IEnumerable Search(this IPublishedContent content, Examine.SearchCriteria.ISearchCriteria criteria, ISearcher searchProvider = null)
{
- //TODO: we should pass in the IExamineManager?
+ //fixme: pass in the IExamineManager
- var s = searchProvider ?? ExamineManager.Instance.GetSearcher(Constants.Examine.ExternalIndexer);
-
- var results = s.Search(criteria);
+ if (searchProvider == null)
+ {
+ if (!ExamineManager.Instance.TryGetIndex(Constants.Examine.ExternalIndexer, out var index))
+ throw new InvalidOperationException("No index found with name " + Constants.Examine.ExternalIndexer);
+ searchProvider = index.GetSearcher();
+ }
+ var results = searchProvider.Search(criteria);
return results.ToPublishedSearchResults(UmbracoContext.Current.ContentCache);
}
diff --git a/src/Umbraco.Web/PublishedContentQuery.cs b/src/Umbraco.Web/PublishedContentQuery.cs
index 8ad40887cc..ed42181234 100644
--- a/src/Umbraco.Web/PublishedContentQuery.cs
+++ b/src/Umbraco.Web/PublishedContentQuery.cs
@@ -229,17 +229,18 @@ namespace Umbraco.Web
///
public IEnumerable Search(int skip, int take, out int totalRecords, string term, bool useWildCards = true, string indexName = null)
{
- //TODO: Can we inject IExamineManager?
+ //fixme: inject IExamineManager
if (_query != null) return _query.Search(skip, take, out totalRecords, term, useWildCards, indexName);
- var indexer = string.IsNullOrEmpty(indexName)
- ? Examine.ExamineManager.Instance.GetIndex(Constants.Examine.ExternalIndexer)
- : Examine.ExamineManager.Instance.GetIndex(indexName);
+ indexName = string.IsNullOrEmpty(indexName)
+ ? Constants.Examine.ExternalIndexer
+ : indexName;
- if (indexer == null) throw new InvalidOperationException("No index found by name " + indexName);
+ if (!ExamineManager.Instance.TryGetIndex(indexName, out var index))
+ throw new InvalidOperationException($"No index found by name {indexName}");
- var searcher = indexer.GetSearcher();
+ var searcher = index.GetSearcher();
if (skip == 0 && take == 0)
{
@@ -248,24 +249,28 @@ namespace Umbraco.Web
return results.ToPublishedSearchResults(_contentCache);
}
- var criteria = SearchAllFields(term, useWildCards, searcher, indexer);
+ var criteria = SearchAllFields(term, useWildCards, searcher, index);
return Search(skip, take, out totalRecords, criteria, searcher);
}
///
- public IEnumerable Search(ISearchCriteria criteria, Examine.ISearcher searchProvider = null)
+ public IEnumerable Search(ISearchCriteria criteria, ISearcher searchProvider = null)
{
return Search(0, 0, out _, criteria, searchProvider);
}
///
- public IEnumerable Search(int skip, int take, out int totalRecords, ISearchCriteria criteria, Examine.ISearcher searchProvider = null)
+ public IEnumerable Search(int skip, int take, out int totalRecords, ISearchCriteria criteria, ISearcher searcher = null)
{
- if (_query != null) return _query.Search(skip, take, out totalRecords, criteria, searchProvider);
+ if (_query != null) return _query.Search(skip, take, out totalRecords, criteria, searcher);
- //TODO: Can we inject IExamineManager?
-
- var searcher = searchProvider ?? Examine.ExamineManager.Instance.GetSearcher(Constants.Examine.ExternalIndexer);
+ //fixme: inject IExamineManager
+ if (searcher == null)
+ {
+ if (!ExamineManager.Instance.TryGetIndex(Constants.Examine.ExternalIndexer, out var index))
+ throw new InvalidOperationException($"No index found by name {Constants.Examine.ExternalIndexer}");
+ searcher = index.GetSearcher();
+ }
var results = skip == 0 && take == 0
? searcher.Search(criteria)
@@ -278,7 +283,7 @@ namespace Umbraco.Web
///
/// Creates an ISearchCriteria for searching all fields in a .
///
- private ISearchCriteria SearchAllFields(string searchText, bool useWildcards, Examine.ISearcher searcher, Examine.IIndex indexer)
+ private ISearchCriteria SearchAllFields(string searchText, bool useWildcards, ISearcher searcher, IIndex indexer)
{
var sc = searcher.CreateCriteria();
diff --git a/src/Umbraco.Web/Runtime/WebRuntimeComponent.cs b/src/Umbraco.Web/Runtime/WebRuntimeComponent.cs
index 1af24db636..1f6210b6a1 100644
--- a/src/Umbraco.Web/Runtime/WebRuntimeComponent.cs
+++ b/src/Umbraco.Web/Runtime/WebRuntimeComponent.cs
@@ -129,6 +129,8 @@ namespace Umbraco.Web.Runtime
composition.Container.RegisterCollectionBuilder()
.Add(() => typeLoader.GetTypes()); // fixme which searchable trees?!
+ composition.Container.Register(new PerRequestLifeTime());
+
composition.Container.RegisterCollectionBuilder()
.Add(() => typeLoader.GetTypes());
diff --git a/src/Umbraco.Web/Search/ExamineComponent.cs b/src/Umbraco.Web/Search/ExamineComponent.cs
index d6d5a5f444..fa22da5ae1 100644
--- a/src/Umbraco.Web/Search/ExamineComponent.cs
+++ b/src/Umbraco.Web/Search/ExamineComponent.cs
@@ -125,13 +125,11 @@ namespace Umbraco.Web.Search
//create the indexes and register them with the manager
foreach(var index in indexCreator.Create())
- {
_examineManager.AddIndex(index);
- }
profilingLogger.Logger.Debug("Examine shutdown registered with MainDom");
- var registeredIndexers = examineManager.IndexProviders.Values.OfType().Count(x => x.EnableDefaultEventHandler);
+ var registeredIndexers = examineManager.Indexes.OfType().Count(x => x.EnableDefaultEventHandler);
profilingLogger.Logger.Info("Adding examine event handlers for {RegisteredIndexers} index providers.", registeredIndexers);
@@ -205,7 +203,7 @@ namespace Umbraco.Web.Search
_isConfigured = true;
- foreach (var luceneIndexer in examineManager.IndexProviders.Values.OfType())
+ foreach (var luceneIndexer in examineManager.Indexes.OfType())
{
//We now need to disable waiting for indexing for Examine so that the appdomain is shutdown immediately and doesn't wait for pending
//indexing operations. We used to wait for indexing operations to complete but this can cause more problems than that is worth because
@@ -377,7 +375,7 @@ namespace Umbraco.Web.Search
//Delete all content of this content/media/member type that is in any content indexer by looking up matched examine docs
foreach (var id in ci.Value.removedIds)
{
- foreach (var index in _examineManager.IndexProviders.Values.OfType())
+ foreach (var index in _examineManager.Indexes.OfType())
{
var searcher = index.GetSearcher();
@@ -707,7 +705,7 @@ namespace Umbraco.Web.Search
{
var valueSet = examineComponent._contentValueSetBuilder.GetValueSets(content).ToList();
- foreach (var index in examineComponent._examineManager.IndexProviders.Values.OfType()
+ foreach (var index in examineComponent._examineManager.Indexes.OfType()
// only for the specified indexers
.Where(x => supportUnpublished.HasValue == false || supportUnpublished.Value == x.SupportSoftDelete)
.Where(x => x.EnableDefaultEventHandler))
@@ -739,7 +737,7 @@ namespace Umbraco.Web.Search
{
var valueSet = examineComponent._mediaValueSetBuilder.GetValueSets(media).ToList();
- foreach (var index in examineComponent._examineManager.IndexProviders.Values.OfType()
+ foreach (var index in examineComponent._examineManager.Indexes.OfType()
// index this item for all indexers if the media is not trashed, otherwise if the item is trashed
// then only index this for indexers supporting unpublished media
.Where(x => isPublished || (x.SupportSoftDelete))
@@ -769,7 +767,7 @@ namespace Umbraco.Web.Search
public static void Execute(ExamineComponent examineComponent, IMember member)
{
var valueSet = examineComponent._memberValueSetBuilder.GetValueSets(member).ToList();
- foreach (var index in examineComponent._examineManager.IndexProviders.Values.OfType()
+ foreach (var index in examineComponent._examineManager.Indexes.OfType()
//ensure that only the providers are flagged to listen execute
.Where(x => x.EnableDefaultEventHandler))
{
@@ -799,7 +797,7 @@ namespace Umbraco.Web.Search
public static void Execute(ExamineComponent examineComponent, int id, bool keepIfUnpublished)
{
var strId = id.ToString(CultureInfo.InvariantCulture);
- foreach (var index in examineComponent._examineManager.IndexProviders.Values.OfType()
+ foreach (var index in examineComponent._examineManager.Indexes.OfType()
// if keepIfUnpublished == true then only delete this item from indexes not supporting unpublished content,
// otherwise if keepIfUnpublished == false then remove from all indexes
.Where(x => keepIfUnpublished == false || x.SupportSoftDelete == false)
diff --git a/src/Umbraco.Web/Search/ExamineSearcherModel.cs b/src/Umbraco.Web/Search/ExamineSearcherModel.cs
index 3ad932efa2..8b9badfcfa 100644
--- a/src/Umbraco.Web/Search/ExamineSearcherModel.cs
+++ b/src/Umbraco.Web/Search/ExamineSearcherModel.cs
@@ -11,26 +11,11 @@ namespace Umbraco.Web.Search
{
public ExamineSearcherModel()
{
- ProviderProperties = new Dictionary();
}
- ///
- /// If the index is not healthy this represents the index error state
- ///
- [DataMember(Name = "error")]
- public string Error { get; set; }
-
- ///
- /// If the index can be open/read
- ///
- [DataMember(Name = "isHealthy")]
- public bool IsHealthy { get; set; }
-
[DataMember(Name = "name")]
public string Name { get; set; }
- [DataMember(Name = "providerProperties")]
- public IDictionary ProviderProperties { get; private set; }
}
}
diff --git a/src/Umbraco.Web/Search/UmbracoIndexesCreator.cs b/src/Umbraco.Web/Search/UmbracoIndexesCreator.cs
index 53bac7769c..dd64d9b142 100644
--- a/src/Umbraco.Web/Search/UmbracoIndexesCreator.cs
+++ b/src/Umbraco.Web/Search/UmbracoIndexesCreator.cs
@@ -110,12 +110,12 @@ namespace Umbraco.Web.Search
return luceneDir;
}
- public virtual IValueSetValidator GetContentValueSetValidator()
+ public virtual IContentValueSetValidator GetContentValueSetValidator()
{
return new ContentValueSetValidator(true, true, PublicAccessService);
}
- public virtual IValueSetValidator GetPublishedContentValueSetValidator()
+ public virtual IContentValueSetValidator GetPublishedContentValueSetValidator()
{
return new ContentValueSetValidator(false, false, PublicAccessService);
}
diff --git a/src/Umbraco.Web/Search/UmbracoTreeSearcher.cs b/src/Umbraco.Web/Search/UmbracoTreeSearcher.cs
index 6290307926..9b98d02a10 100644
--- a/src/Umbraco.Web/Search/UmbracoTreeSearcher.cs
+++ b/src/Umbraco.Web/Search/UmbracoTreeSearcher.cs
@@ -11,15 +11,27 @@ using Umbraco.Core.Composing;
using Umbraco.Core.Models;
using Umbraco.Core.Services;
using Umbraco.Web.Models.ContentEditing;
+using Umbraco.Web.Trees;
namespace Umbraco.Web.Search
{
- internal class UmbracoTreeSearcher
+ ///
+ /// Used for internal Umbraco implementations of
+ ///
+ public class UmbracoTreeSearcher
{
+ private readonly IExamineManager _examineManager;
+ private readonly UmbracoHelper _umbracoHelper;
+
+ public UmbracoTreeSearcher(IExamineManager examineManager, UmbracoHelper umbracoHelper)
+ {
+ _examineManager = examineManager ?? throw new ArgumentNullException(nameof(examineManager));
+ _umbracoHelper = umbracoHelper ?? throw new ArgumentNullException(nameof(umbracoHelper));
+ }
+
///
/// Searches for results based on the entity type
///
- ///
///
///
///
@@ -30,7 +42,6 @@ namespace Umbraco.Web.Search
///
///
public IEnumerable ExamineSearch(
- UmbracoHelper umbracoHelper,
string query,
UmbracoEntityTypes entityType,
int pageSize,
@@ -39,16 +50,16 @@ namespace Umbraco.Web.Search
var sb = new StringBuilder();
string type;
- var indexer = Constants.Examine.InternalIndexer;
+ var indexName = Constants.Examine.InternalIndexer;
var fields = new[] { "id", "__NodeId" };
- var umbracoContext = umbracoHelper.UmbracoContext;
+ var umbracoContext = _umbracoHelper.UmbracoContext;
//TODO: WE should really just allow passing in a lucene raw query
switch (entityType)
{
case UmbracoEntityTypes.Member:
- indexer = Constants.Examine.InternalMemberIndexer;
+ indexName = Constants.Examine.InternalMemberIndexer;
type = "member";
fields = new[] { "id", "__NodeId", "email", "loginName" };
if (searchFrom != null && searchFrom != Constants.Conventions.MemberTypes.AllMembersListId && searchFrom.Trim() != "-1")
@@ -72,7 +83,10 @@ namespace Umbraco.Web.Search
throw new NotSupportedException("The " + typeof(UmbracoTreeSearcher) + " currently does not support searching against object type " + entityType);
}
- var internalSearcher = ExamineManager.Instance.GetSearcher(indexer);
+ if (!_examineManager.TryGetIndex(indexName, out var index))
+ throw new InvalidOperationException("No index found by name " + indexName);
+
+ var internalSearcher = index.GetSearcher();
//build a lucene query:
// the __nodeName will be boosted 10x without wildcards
@@ -197,7 +211,7 @@ namespace Umbraco.Web.Search
case UmbracoEntityTypes.Media:
return MediaFromSearchResults(pagedResult);
case UmbracoEntityTypes.Document:
- return ContentFromSearchResults(umbracoHelper, pagedResult);
+ return ContentFromSearchResults(pagedResult);
default:
throw new NotSupportedException("The " + typeof(UmbracoTreeSearcher) + " currently does not support searching against object type " + entityType);
}
@@ -205,15 +219,13 @@ namespace Umbraco.Web.Search
private void AppendPath(StringBuilder sb, UmbracoObjectTypes objectType, int[] startNodeIds, string searchFrom, IEntityService entityService)
{
- if (sb == null) throw new ArgumentNullException("sb");
- if (entityService == null) throw new ArgumentNullException("entityService");
+ if (sb == null) throw new ArgumentNullException(nameof(sb));
+ if (entityService == null) throw new ArgumentNullException(nameof(entityService));
- Udi udi;
- Udi.TryParse(searchFrom, true, out udi);
+ Udi.TryParse(searchFrom, true, out var udi);
searchFrom = udi == null ? searchFrom : entityService.GetId(udi).Result.ToString();
- int searchFromId;
- var entityPath = int.TryParse(searchFrom, out searchFromId) && searchFromId > 0
+ var entityPath = int.TryParse(searchFrom, out var searchFromId) && searchFromId > 0
? entityService.GetAllPaths(objectType, searchFromId).FirstOrDefault()
: null;
if (entityPath != null)
@@ -284,8 +296,7 @@ namespace Umbraco.Web.Search
}
if (searchResult.Values.ContainsKey("__key") && searchResult.Values["__key"] != null)
{
- Guid key;
- if (Guid.TryParse(searchResult.Values["__key"], out key))
+ if (Guid.TryParse(searchResult.Values["__key"], out var key))
{
m.Key = key;
}
@@ -317,10 +328,9 @@ namespace Umbraco.Web.Search
///
/// Returns a collection of entities for content based on search results
///
- ///
///
///
- private IEnumerable ContentFromSearchResults(UmbracoHelper umbracoHelper, IEnumerable results)
+ private IEnumerable ContentFromSearchResults(IEnumerable results)
{
var mapped = Mapper.Map>(results).ToArray();
//add additional data
@@ -329,7 +339,7 @@ namespace Umbraco.Web.Search
var intId = m.Id.TryConvertTo();
if (intId.Success)
{
- m.AdditionalData["Url"] = umbracoHelper.Url(intId.Result);
+ m.AdditionalData["Url"] = _umbracoHelper.Url(intId.Result);
}
}
return mapped;
diff --git a/src/Umbraco.Web/Trees/ContentTreeController.cs b/src/Umbraco.Web/Trees/ContentTreeController.cs
index c0b2126d5e..35c335f06d 100644
--- a/src/Umbraco.Web/Trees/ContentTreeController.cs
+++ b/src/Umbraco.Web/Trees/ContentTreeController.cs
@@ -35,7 +35,12 @@ namespace Umbraco.Web.Trees
[SearchableTree("searchResultFormatter", "configureContentResult")]
public class ContentTreeController : ContentTreeControllerBase, ISearchableTree
{
- private readonly UmbracoTreeSearcher _treeSearcher = new UmbracoTreeSearcher();
+ private readonly UmbracoTreeSearcher _treeSearcher;
+
+ public ContentTreeController(UmbracoTreeSearcher treeSearcher)
+ {
+ _treeSearcher = treeSearcher;
+ }
protected override int RecycleBinId => Constants.System.RecycleBinContent;
@@ -316,7 +321,7 @@ namespace Umbraco.Web.Trees
public IEnumerable Search(string query, int pageSize, long pageIndex, out long totalFound, string searchFrom = null)
{
- return _treeSearcher.ExamineSearch(Umbraco, query, UmbracoEntityTypes.Document, pageSize, pageIndex, out totalFound, searchFrom);
+ return _treeSearcher.ExamineSearch(query, UmbracoEntityTypes.Document, pageSize, pageIndex, out totalFound, searchFrom);
}
}
}
diff --git a/src/Umbraco.Web/Trees/MediaTreeController.cs b/src/Umbraco.Web/Trees/MediaTreeController.cs
index 20804d4cf8..4efddfb4b3 100644
--- a/src/Umbraco.Web/Trees/MediaTreeController.cs
+++ b/src/Umbraco.Web/Trees/MediaTreeController.cs
@@ -35,7 +35,12 @@ namespace Umbraco.Web.Trees
[SearchableTree("searchResultFormatter", "configureMediaResult")]
public class MediaTreeController : ContentTreeControllerBase, ISearchableTree
{
- private readonly UmbracoTreeSearcher _treeSearcher = new UmbracoTreeSearcher();
+ private readonly UmbracoTreeSearcher _treeSearcher;
+
+ public MediaTreeController(UmbracoTreeSearcher treeSearcher)
+ {
+ _treeSearcher = treeSearcher;
+ }
protected override int RecycleBinId => Constants.System.RecycleBinMedia;
@@ -161,7 +166,7 @@ namespace Umbraco.Web.Trees
public IEnumerable Search(string query, int pageSize, long pageIndex, out long totalFound, string searchFrom = null)
{
- return _treeSearcher.ExamineSearch(Umbraco, query, UmbracoEntityTypes.Media, pageSize, pageIndex, out totalFound, searchFrom);
+ return _treeSearcher.ExamineSearch(query, UmbracoEntityTypes.Media, pageSize, pageIndex, out totalFound, searchFrom);
}
internal override IEnumerable GetChildrenFromEntityService(int entityId)
diff --git a/src/Umbraco.Web/Trees/MemberTreeController.cs b/src/Umbraco.Web/Trees/MemberTreeController.cs
index 68819351c0..3317bfbdf9 100644
--- a/src/Umbraco.Web/Trees/MemberTreeController.cs
+++ b/src/Umbraco.Web/Trees/MemberTreeController.cs
@@ -33,13 +33,14 @@ namespace Umbraco.Web.Trees
[SearchableTree("searchResultFormatter", "configureMemberResult")]
public class MemberTreeController : TreeController, ISearchableTree
{
- public MemberTreeController()
+ public MemberTreeController(UmbracoTreeSearcher treeSearcher)
{
+ _treeSearcher = treeSearcher;
_provider = Core.Security.MembershipProviderExtensions.GetMembersMembershipProvider();
_isUmbracoProvider = _provider.IsUmbracoMembershipProvider();
}
- private readonly UmbracoTreeSearcher _treeSearcher = new UmbracoTreeSearcher();
+ private readonly UmbracoTreeSearcher _treeSearcher;
private readonly MembershipProvider _provider;
private readonly bool _isUmbracoProvider;
@@ -193,7 +194,7 @@ namespace Umbraco.Web.Trees
public IEnumerable Search(string query, int pageSize, long pageIndex, out long totalFound, string searchFrom = null)
{
- return _treeSearcher.ExamineSearch(Umbraco, query, UmbracoEntityTypes.Member, pageSize, pageIndex, out totalFound, searchFrom);
+ return _treeSearcher.ExamineSearch(query, UmbracoEntityTypes.Member, pageSize, pageIndex, out totalFound, searchFrom);
}
}
}
diff --git a/src/Umbraco.Web/Umbraco.Web.csproj b/src/Umbraco.Web/Umbraco.Web.csproj
index 19c1e59bd1..bca87b02ac 100755
--- a/src/Umbraco.Web/Umbraco.Web.csproj
+++ b/src/Umbraco.Web/Umbraco.Web.csproj
@@ -62,7 +62,7 @@
-
+
2.6.2.25