diff --git a/.editorconfig b/.editorconfig
index 29e21d01ed..c63ef39430 100644
--- a/.editorconfig
+++ b/.editorconfig
@@ -33,4 +33,5 @@ dotnet_naming_style.prefix_underscore.required_prefix = _
[*.cs]
csharp_style_var_for_built_in_types = true:suggestion
csharp_style_var_when_type_is_apparent = true:suggestion
-csharp_style_var_elsewhere = true:suggestion
\ No newline at end of file
+csharp_style_var_elsewhere = true:suggestion
+csharp_prefer_braces = false : none
diff --git a/.github/CONTRIBUTING.md b/.github/CONTRIBUTING.md
index 96014f65b7..6caeadd0e5 100644
--- a/.github/CONTRIBUTING.md
+++ b/.github/CONTRIBUTING.md
@@ -82,7 +82,6 @@ You can get in touch with [the PR team](#the-pr-team) in multiple ways, we love
- If there's an existing issue on the issue tracker then that's a good place to leave questions and discuss how to start or move forward
- Unsure where to start? Did something not work as expected? Try leaving a note in the ["Contributing to Umbraco"](https://our.umbraco.com/forum/contributing-to-umbraco-cms/) forum, the team monitors that one closely
-- We're also [active in the Gitter chatroom](https://gitter.im/umbraco/Umbraco-CMS)
## Code of Conduct
diff --git a/.gitignore b/.gitignore
index 529adef976..279bdb39dd 100644
--- a/.gitignore
+++ b/.gitignore
@@ -107,6 +107,7 @@ src/Umbraco.Web.UI.Client/[Bb]uild/[Bb]elle/
src/Umbraco.Web.UI/[Uu]ser[Cc]ontrols/
src/Umbraco.Web.UI.Client/src/[Ll]ess/*.css
+src/Umbraco.Web.UI.Client/vwd.webinfo
src/Umbraco.Web.UI/App_Plugins/*
src/*.psess
diff --git a/build/NuSpecs/UmbracoCms.Web.nuspec b/build/NuSpecs/UmbracoCms.Web.nuspec
index adf090c69b..51d7e3b8d0 100644
--- a/build/NuSpecs/UmbracoCms.Web.nuspec
+++ b/build/NuSpecs/UmbracoCms.Web.nuspec
@@ -14,7 +14,7 @@
Contains the core assemblies needed to run Umbraco Cmsen-USumbraco
-
+
-
+
@@ -72,7 +72,7 @@
-
+
@@ -88,8 +88,8 @@
-
+
Properties\SolutionInfo.cs
diff --git a/src/Umbraco.Examine/UmbracoContentIndex.cs b/src/Umbraco.Examine/UmbracoContentIndex.cs
index 822117de46..e16015e192 100644
--- a/src/Umbraco.Examine/UmbracoContentIndex.cs
+++ b/src/Umbraco.Examine/UmbracoContentIndex.cs
@@ -52,13 +52,13 @@ namespace Umbraco.Examine
///
public UmbracoContentIndex(
string name,
- IEnumerable fieldDefinitions,
+ FieldDefinitionCollection fieldDefinitions,
Directory luceneDirectory,
Analyzer defaultAnalyzer,
IProfilingLogger profilingLogger,
ILocalizationService languageService,
IContentValueSetValidator validator,
- IReadOnlyDictionary> indexValueTypes = null)
+ IReadOnlyDictionary indexValueTypes = null)
: base(name, fieldDefinitions, luceneDirectory, defaultAnalyzer, profilingLogger, validator, indexValueTypes)
{
if (validator == null) throw new ArgumentNullException(nameof(validator));
@@ -122,7 +122,7 @@ namespace Umbraco.Examine
//anywhere else in this class
Current.Services.PublicAccessService,
parentId,
- ConfigIndexCriteria.IncludeItemTypes, ConfigIndexCriteria.ExcludeItemTypes);
+ ConfigIndexCriteria?.IncludeItemTypes, ConfigIndexCriteria?.ExcludeItemTypes);
PublishedValuesOnly = supportUnpublished;
}
@@ -200,41 +200,17 @@ namespace Umbraco.Examine
var descendantPath = $@"\-1\,*{nodeId}\,*";
var rawQuery = $"{IndexPathFieldName}:{descendantPath}";
var searcher = GetSearcher();
- var c = searcher.CreateCriteria();
- var filtered = c.RawQuery(rawQuery);
- var results = searcher.Search(filtered);
+ var c = searcher.CreateQuery();
+ var filtered = c.NativeQuery(rawQuery);
+ var results = filtered.Execute();
ProfilingLogger.Debug(GetType(), "DeleteFromIndex with query: {Query} (found {TotalItems} results)", rawQuery, results.TotalItemCount);
//need to queue a delete item for each one found
- foreach (var r in results)
- {
- QueueIndexOperation(new IndexOperation(new ValueSet(r.Id), IndexOperationType.Delete));
- }
+ QueueIndexOperation(results.Select(r => new IndexOperation(new ValueSet(r.Id), IndexOperationType.Delete)));
base.PerformDeleteFromIndex(nodeId, onComplete);
}
-
- ///
- /// Overridden to ensure that the variant system fields have the right value types
- ///
- ///
- ///
- ///
- protected override FieldValueTypeCollection CreateFieldValueTypes(IReadOnlyDictionary> indexValueTypesFactory = null)
- {
- //fixme: languages are dynamic so although this will work on startup it wont work when languages are edited
- foreach(var lang in LanguageService.GetAllLanguages())
- {
- foreach (var field in UmbracoIndexFieldDefinitions)
- {
- var def = new FieldDefinition($"{field.Name}_{lang.IsoCode.ToLowerInvariant()}", field.Type);
- FieldDefinitionCollection.TryAdd(def.Name, def);
- }
- }
-
- return base.CreateFieldValueTypes(indexValueTypesFactory);
- }
}
}
diff --git a/src/Umbraco.Examine/UmbracoExamineExtensions.cs b/src/Umbraco.Examine/UmbracoExamineExtensions.cs
index 8be5a6c1e3..f33b7587e0 100644
--- a/src/Umbraco.Examine/UmbracoExamineExtensions.cs
+++ b/src/Umbraco.Examine/UmbracoExamineExtensions.cs
@@ -1,10 +1,6 @@
-using System;
-using System.ComponentModel;
-using System.Web;
-using Examine.LuceneEngine.SearchCriteria;
-using Examine.SearchCriteria;
+using Examine.LuceneEngine.Search;
+using Examine.Search;
using Umbraco.Core;
-using Umbraco.Examine.Config;
namespace Umbraco.Examine
{
diff --git a/src/Umbraco.Examine/UmbracoExamineIndex.cs b/src/Umbraco.Examine/UmbracoExamineIndex.cs
index 591ca1c3c8..47712ee755 100644
--- a/src/Umbraco.Examine/UmbracoExamineIndex.cs
+++ b/src/Umbraco.Examine/UmbracoExamineIndex.cs
@@ -20,10 +20,9 @@ namespace Umbraco.Examine
{
///
- /// An abstract provider containing the basic functionality to be able to query against
- /// Umbraco data.
+ /// An abstract provider containing the basic functionality to be able to query against Umbraco data.
///
- public abstract class UmbracoExamineIndex : LuceneIndex, IUmbracoIndexer, IIndexDiagnostics
+ public abstract class UmbracoExamineIndex : LuceneIndex, IUmbracoIndex, IIndexDiagnostics
{
// note
// wrapping all operations that end up calling base.SafelyProcessQueueItems in a safe call
@@ -53,6 +52,7 @@ namespace Umbraco.Examine
{
ProfilingLogger = Current.ProfilingLogger;
_configBased = true;
+ _diagnostics = new UmbracoExamineIndexDiagnostics(this, ProfilingLogger.Logger);
}
///
@@ -67,12 +67,12 @@ namespace Umbraco.Examine
///
protected UmbracoExamineIndex(
string name,
- IEnumerable fieldDefinitions,
+ FieldDefinitionCollection fieldDefinitions,
Directory luceneDirectory,
Analyzer defaultAnalyzer,
IProfilingLogger profilingLogger,
IValueSetValidator validator = null,
- IReadOnlyDictionary> indexValueTypes = null)
+ IReadOnlyDictionary indexValueTypes = null)
: base(name, fieldDefinitions, luceneDirectory, defaultAnalyzer, validator, indexValueTypes)
{
ProfilingLogger = profilingLogger ?? throw new ArgumentNullException(nameof(profilingLogger));
@@ -86,60 +86,8 @@ namespace Umbraco.Examine
private readonly bool _configBased = false;
- ///
- /// 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
- /// for retreival after searching.
- ///
- public static readonly FieldDefinition[] UmbracoIndexFieldDefinitions =
- {
- new FieldDefinition("parentID", FieldDefinitionTypes.Integer),
- new FieldDefinition("level", FieldDefinitionTypes.Integer),
- new FieldDefinition("writerID", FieldDefinitionTypes.Integer),
- new FieldDefinition("creatorID", FieldDefinitionTypes.Integer),
- new FieldDefinition("sortOrder", FieldDefinitionTypes.Integer),
- new FieldDefinition("template", FieldDefinitionTypes.Integer),
-
- new FieldDefinition("createDate", FieldDefinitionTypes.DateTime),
- new FieldDefinition("updateDate", FieldDefinitionTypes.DateTime),
-
- new FieldDefinition("key", FieldDefinitionTypes.InvariantCultureIgnoreCase),
- new FieldDefinition("version", FieldDefinitionTypes.Raw),
- new FieldDefinition("nodeType", FieldDefinitionTypes.InvariantCultureIgnoreCase),
- new FieldDefinition("template", FieldDefinitionTypes.Raw),
- new FieldDefinition("urlName", FieldDefinitionTypes.InvariantCultureIgnoreCase),
- new FieldDefinition("path", FieldDefinitionTypes.Raw),
-
- new FieldDefinition("email", FieldDefinitionTypes.EmailAddress),
-
- new FieldDefinition(PublishedFieldName, FieldDefinitionTypes.Raw),
- new FieldDefinition(NodeKeyFieldName, FieldDefinitionTypes.Raw),
- new FieldDefinition(IndexPathFieldName, FieldDefinitionTypes.Raw),
- new FieldDefinition(IconFieldName, FieldDefinitionTypes.Raw)
- };
-
protected IProfilingLogger ProfilingLogger { get; }
- ///
- /// Overridden to ensure that the umbraco system field definitions are in place
- ///
- ///
- ///
- protected override FieldValueTypeCollection CreateFieldValueTypes(IReadOnlyDictionary> indexValueTypesFactory = null)
- {
- //if config based then ensure the value types else it's assumed these were passed in via ctor
- if (_configBased)
- {
- foreach (var field in UmbracoIndexFieldDefinitions)
- {
- FieldDefinitionCollection.TryAdd(field.Name, field);
- }
- }
-
-
- return base.CreateFieldValueTypes(indexValueTypesFactory);
- }
-
///
/// When set to true Umbraco will keep the index in sync with Umbraco data automatically
///
@@ -147,6 +95,14 @@ namespace Umbraco.Examine
public bool PublishedValuesOnly { get; protected set; } = false;
+ ///
+ public IEnumerable GetFields()
+ {
+ //we know this is a LuceneSearcher
+ var searcher = (LuceneSearcher) GetSearcher();
+ return searcher.GetAllIndexedFields();
+ }
+
protected ConfigIndexCriteria ConfigIndexCriteria { get; private set; }
///
@@ -174,12 +130,15 @@ namespace Umbraco.Examine
EnableDefaultEventHandler = enabled;
}
- //Need to check if the index set or IndexerData is specified...
- if (config["indexSet"] == null && FieldDefinitionCollection.Count == 0)
+ //this is config based, so add the default definitions
+ foreach (var field in UmbracoFieldDefinitionCollection.UmbracoIndexFieldDefinitions)
{
- //if we don't have either, then we'll try to set the index set by naming conventions
- var found = false;
+ FieldDefinitionCollection.TryAdd(field);
+ }
+ //Need to check if the index set is specified...
+ if (config["indexSet"] == null)
+ {
var possibleSuffixes = new[] {"Index", "Indexer"};
foreach (var suffix in possibleSuffixes)
{
@@ -200,36 +159,29 @@ namespace Umbraco.Examine
ConfigIndexCriteria = CreateFieldDefinitionsFromConfig(indexSet);
foreach (var fieldDefinition in ConfigIndexCriteria.StandardFields.Union(ConfigIndexCriteria.UserFields))
{
- FieldDefinitionCollection.TryAdd(fieldDefinition.Name, fieldDefinition);
+ //replace any existing or add
+ FieldDefinitionCollection.AddOrUpdate(fieldDefinition);
}
- found = true;
break;
}
-
- if (!found)
- throw new ArgumentNullException("indexSet on LuceneExamineIndexer provider has not been set in configuration and/or the IndexerData property has not been explicitly set");
-
}
- else if (config["indexSet"] != null)
+ else
{
//if an index set is specified, ensure it exists and initialize the indexer based on the set
if (IndexSets.Instance.Sets[config["indexSet"]] == null)
- {
throw new ArgumentException("The indexSet specified for the LuceneExamineIndexer provider does not exist");
- }
- else
+
+ IndexSetName = config["indexSet"];
+
+ var indexSet = IndexSets.Instance.Sets[IndexSetName];
+
+ //get the index criteria and ensure folder
+ ConfigIndexCriteria = CreateFieldDefinitionsFromConfig(indexSet);
+ foreach (var fieldDefinition in ConfigIndexCriteria.StandardFields.Union(ConfigIndexCriteria.UserFields))
{
- IndexSetName = config["indexSet"];
-
- var indexSet = IndexSets.Instance.Sets[IndexSetName];
-
- //get the index criteria and ensure folder
- ConfigIndexCriteria = CreateFieldDefinitionsFromConfig(indexSet);
- foreach (var fieldDefinition in ConfigIndexCriteria.StandardFields.Union(ConfigIndexCriteria.UserFields))
- {
- FieldDefinitionCollection.TryAdd(fieldDefinition.Name, fieldDefinition);
- }
+ //replace any existing or add
+ FieldDefinitionCollection.AddOrUpdate(fieldDefinition);
}
}
diff --git a/src/Umbraco.Examine/UmbracoExamineSearcher.cs b/src/Umbraco.Examine/UmbracoExamineSearcher.cs
deleted file mode 100644
index 50c6c21e37..0000000000
--- a/src/Umbraco.Examine/UmbracoExamineSearcher.cs
+++ /dev/null
@@ -1,52 +0,0 @@
-//using System;
-//using System.ComponentModel;
-//using System.IO;
-//using System.Linq;
-//using Umbraco.Core;
-//using Examine.LuceneEngine.Providers;
-//using Lucene.Net.Analysis;
-//using Lucene.Net.Index;
-//using Umbraco.Core.Composing;
-//using Umbraco.Examine.Config;
-//using Directory = Lucene.Net.Store.Directory;
-//using Examine.LuceneEngine;
-
-//namespace Umbraco.Examine
-//{
-// ///
-// /// An Examine searcher which uses Lucene.Net as the
-// ///
-// public class UmbracoExamineSearcher : LuceneSearcher
-// {
-// ///
-// /// Constructor to allow for creating an indexer at runtime
-// ///
-// ///
-// ///
-// ///
-// public UmbracoExamineSearcher(string name, Directory luceneDirectory, Analyzer analyzer, FieldValueTypeCollection fieldValueTypeCollection)
-// : base(name, luceneDirectory, analyzer, fieldValueTypeCollection)
-// {
-// }
-
-// ///
-// public UmbracoExamineSearcher(string name, IndexWriter writer, Analyzer analyzer, FieldValueTypeCollection fieldValueTypeCollection)
-// : base(name, writer, analyzer, fieldValueTypeCollection)
-// {
-// }
-
-// ///
-// /// Returns a list of fields to search on, this will also exclude the IndexPathFieldName and node type alias
-// ///
-// ///
-// public override string[] GetAllIndexedFields()
-// {
-// var fields = base.GetAllIndexedFields();
-// return fields
-// .Where(x => x != UmbracoExamineIndexer.IndexPathFieldName)
-// .Where(x => x != LuceneIndex.ItemTypeFieldName)
-// .ToArray();
-// }
-
-// }
-//}
diff --git a/src/Umbraco.Examine/UmbracoFieldDefinitionCollection.cs b/src/Umbraco.Examine/UmbracoFieldDefinitionCollection.cs
new file mode 100644
index 0000000000..97d1f68727
--- /dev/null
+++ b/src/Umbraco.Examine/UmbracoFieldDefinitionCollection.cs
@@ -0,0 +1,75 @@
+using Examine;
+
+namespace Umbraco.Examine
+{
+ ///
+ /// Custom allowing dynamic creation of
+ ///
+ public class UmbracoFieldDefinitionCollection : FieldDefinitionCollection
+ {
+
+ public UmbracoFieldDefinitionCollection()
+ : base(UmbracoIndexFieldDefinitions)
+ {
+ }
+
+ ///
+ /// 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
+ /// for retreival after searching.
+ ///
+ public static readonly FieldDefinition[] UmbracoIndexFieldDefinitions =
+ {
+ new FieldDefinition("parentID", FieldDefinitionTypes.Integer),
+ new FieldDefinition("level", FieldDefinitionTypes.Integer),
+ new FieldDefinition("writerID", FieldDefinitionTypes.Integer),
+ new FieldDefinition("creatorID", FieldDefinitionTypes.Integer),
+ new FieldDefinition("sortOrder", FieldDefinitionTypes.Integer),
+ new FieldDefinition("template", FieldDefinitionTypes.Integer),
+
+ new FieldDefinition("createDate", FieldDefinitionTypes.DateTime),
+ new FieldDefinition("updateDate", FieldDefinitionTypes.DateTime),
+
+ new FieldDefinition("key", FieldDefinitionTypes.InvariantCultureIgnoreCase),
+ new FieldDefinition("version", FieldDefinitionTypes.Raw),
+ new FieldDefinition("nodeType", FieldDefinitionTypes.InvariantCultureIgnoreCase),
+ new FieldDefinition("template", FieldDefinitionTypes.Raw),
+ new FieldDefinition("urlName", FieldDefinitionTypes.InvariantCultureIgnoreCase),
+ new FieldDefinition("path", FieldDefinitionTypes.Raw),
+
+ new FieldDefinition("email", FieldDefinitionTypes.EmailAddress),
+
+ new FieldDefinition(UmbracoExamineIndex.PublishedFieldName, FieldDefinitionTypes.Raw),
+ new FieldDefinition(UmbracoExamineIndex.NodeKeyFieldName, FieldDefinitionTypes.Raw),
+ new FieldDefinition(UmbracoExamineIndex.IndexPathFieldName, FieldDefinitionTypes.Raw),
+ new FieldDefinition(UmbracoExamineIndex.IconFieldName, FieldDefinitionTypes.Raw)
+ };
+
+ /////
+ ///// Overridden to dynamically add field definitions for culture variations
+ /////
+ /////
+ /////
+ /////
+ //public override bool TryGetValue(string fieldName, out FieldDefinition fieldDefinition)
+ //{
+ // var result = base.TryGetValue(fieldName, out fieldDefinition);
+ // if (result) return true;
+
+ // //if the fieldName is not suffixed with _iso-Code
+ // var underscoreIndex = fieldName.LastIndexOf('_');
+ // if (underscoreIndex == -1) return false;
+
+
+
+ // var isoCode = fieldName.Substring(underscoreIndex);
+ // if (isoCode.Length < 6) return false; //invalid isoCode
+
+ // var hyphenIndex = isoCode.IndexOf('-');
+ // if (hyphenIndex != 3) return false; //invalid isoCode
+
+ // //we'll assume this is a valid isoCode
+
+ //}
+ }
+}
diff --git a/src/Umbraco.Examine/UmbracoMemberIndex.cs b/src/Umbraco.Examine/UmbracoMemberIndex.cs
index 451bfbbcb7..fae818a4a5 100644
--- a/src/Umbraco.Examine/UmbracoMemberIndex.cs
+++ b/src/Umbraco.Examine/UmbracoMemberIndex.cs
@@ -42,8 +42,8 @@ namespace Umbraco.Examine
///
///
public UmbracoMemberIndex(
- string name,
- IEnumerable fieldDefinitions,
+ string name,
+ FieldDefinitionCollection fieldDefinitions,
Directory luceneDirectory,
Analyzer analyzer,
IProfilingLogger profilingLogger,
@@ -64,10 +64,10 @@ namespace Umbraco.Examine
///
///
///
- protected override FieldValueTypeCollection CreateFieldValueTypes(IReadOnlyDictionary> indexValueTypesFactory = null)
+ protected override FieldValueTypeCollection CreateFieldValueTypes(IReadOnlyDictionary indexValueTypesFactory = null)
{
var keyDef = new FieldDefinition("__key", FieldDefinitionTypes.Raw);
- FieldDefinitionCollection.TryAdd(keyDef.Name, keyDef);
+ FieldDefinitionCollection.TryAdd(keyDef);
return base.CreateFieldValueTypes(indexValueTypesFactory);
}
diff --git a/src/Umbraco.Tests/PublishedContent/PublishedMediaTests.cs b/src/Umbraco.Tests/PublishedContent/PublishedMediaTests.cs
index c736b47e53..d88df766e3 100644
--- a/src/Umbraco.Tests/PublishedContent/PublishedMediaTests.cs
+++ b/src/Umbraco.Tests/PublishedContent/PublishedMediaTests.cs
@@ -171,9 +171,9 @@ namespace Umbraco.Tests.PublishedContent
//ensure it still exists in the index (raw examine search)
- var criteria = searcher.CreateCriteria();
+ var criteria = searcher.CreateQuery();
var filter = criteria.Id(3113);
- var found = searcher.Search(filter.Compile());
+ var found = filter.Execute();
Assert.IsNotNull(found);
Assert.AreEqual(1, found.TotalItemCount);
diff --git a/src/Umbraco.Tests/Services/EntityServiceTests.cs b/src/Umbraco.Tests/Services/EntityServiceTests.cs
index 1db653f4ab..2425f8b74a 100644
--- a/src/Umbraco.Tests/Services/EntityServiceTests.cs
+++ b/src/Umbraco.Tests/Services/EntityServiceTests.cs
@@ -6,6 +6,7 @@ using NUnit.Framework;
using Umbraco.Core;
using Umbraco.Core.Models;
using Umbraco.Core.Models.Entities;
+using Umbraco.Core.Persistence.DatabaseModelDefinitions;
using Umbraco.Core.Services;
using Umbraco.Tests.TestHelpers;
using Umbraco.Tests.TestHelpers.Entities;
@@ -37,6 +38,53 @@ namespace Umbraco.Tests.Services
}
}
+ [Test]
+ public void EntityService_Can_Get_Paged_Descendants_Ordering_Path()
+ {
+
+ var contentType = ServiceContext.ContentTypeService.Get("umbTextpage");
+
+ var root = MockedContent.CreateSimpleContent(contentType);
+ ServiceContext.ContentService.Save(root);
+ var rootId = root.Id;
+ var ids = new List();
+ for (int i = 0; i < 10; i++)
+ {
+ var c1 = MockedContent.CreateSimpleContent(contentType, Guid.NewGuid().ToString(), root);
+ ServiceContext.ContentService.Save(c1);
+ ids.Add(c1.Id);
+ root = c1; // make a hierarchy
+ }
+
+ var service = ServiceContext.EntityService;
+
+ long total;
+
+ var entities = service.GetPagedDescendants(rootId, UmbracoObjectTypes.Document, 0, 6, out total).ToArray();
+ Assert.That(entities.Length, Is.EqualTo(6));
+ Assert.That(total, Is.EqualTo(10));
+ Assert.AreEqual(ids[0], entities[0].Id);
+
+ entities = service.GetPagedDescendants(rootId, UmbracoObjectTypes.Document, 1, 6, out total).ToArray();
+ Assert.That(entities.Length, Is.EqualTo(4));
+ Assert.That(total, Is.EqualTo(10));
+ Assert.AreEqual(ids[6], entities[0].Id);
+
+ //Test ordering direction
+
+ entities = service.GetPagedDescendants(rootId, UmbracoObjectTypes.Document, 0, 6, out total,
+ ordering: Ordering.By("Path", Direction.Descending)).ToArray();
+ Assert.That(entities.Length, Is.EqualTo(6));
+ Assert.That(total, Is.EqualTo(10));
+ Assert.AreEqual(ids[ids.Count - 1], entities[0].Id);
+
+ entities = service.GetPagedDescendants(rootId, UmbracoObjectTypes.Document, 1, 6, out total,
+ ordering: Ordering.By("Path", Direction.Descending)).ToArray();
+ Assert.That(entities.Length, Is.EqualTo(4));
+ Assert.That(total, Is.EqualTo(10));
+ Assert.AreEqual(ids[ids.Count - 1 - 6], entities[0].Id);
+ }
+
[Test]
public void EntityService_Can_Get_Paged_Content_Children()
{
@@ -45,21 +93,41 @@ namespace Umbraco.Tests.Services
var root = MockedContent.CreateSimpleContent(contentType);
ServiceContext.ContentService.Save(root);
+ var ids = new List();
for (int i = 0; i < 10; i++)
{
var c1 = MockedContent.CreateSimpleContent(contentType, Guid.NewGuid().ToString(), root);
ServiceContext.ContentService.Save(c1);
+ ids.Add(c1.Id);
}
var service = ServiceContext.EntityService;
long total;
+
var entities = service.GetPagedChildren(root.Id, UmbracoObjectTypes.Document, 0, 6, out total).ToArray();
Assert.That(entities.Length, Is.EqualTo(6));
Assert.That(total, Is.EqualTo(10));
+ Assert.AreEqual(ids[0], entities[0].Id);
+
entities = service.GetPagedChildren(root.Id, UmbracoObjectTypes.Document, 1, 6, out total).ToArray();
Assert.That(entities.Length, Is.EqualTo(4));
Assert.That(total, Is.EqualTo(10));
+ Assert.AreEqual(ids[6], entities[0].Id);
+
+ //Test ordering direction
+
+ entities = service.GetPagedChildren(root.Id, UmbracoObjectTypes.Document, 0, 6, out total,
+ ordering: Ordering.By("SortOrder", Direction.Descending)).ToArray();
+ Assert.That(entities.Length, Is.EqualTo(6));
+ Assert.That(total, Is.EqualTo(10));
+ Assert.AreEqual(ids[ids.Count - 1], entities[0].Id);
+
+ entities = service.GetPagedChildren(root.Id, UmbracoObjectTypes.Document, 1, 6, out total,
+ ordering: Ordering.By("SortOrder", Direction.Descending)).ToArray();
+ Assert.That(entities.Length, Is.EqualTo(4));
+ Assert.That(total, Is.EqualTo(10));
+ Assert.AreEqual(ids[ids.Count - 1 - 6], entities[0].Id);
}
[Test]
@@ -206,10 +274,12 @@ namespace Umbraco.Tests.Services
var service = ServiceContext.EntityService;
long total;
- var entities = service.GetPagedDescendants(root.Id, UmbracoObjectTypes.Document, 0, 10, out total, filter: "ssss").ToArray();
+ var entities = service.GetPagedDescendants(root.Id, UmbracoObjectTypes.Document, 0, 10, out total,
+ filter: SqlContext.Query().Where(x => x.Name.Contains("ssss"))).ToArray();
Assert.That(entities.Length, Is.EqualTo(10));
Assert.That(total, Is.EqualTo(10));
- entities = service.GetPagedDescendants(root.Id, UmbracoObjectTypes.Document, 0, 50, out total, filter: "tttt").ToArray();
+ entities = service.GetPagedDescendants(root.Id, UmbracoObjectTypes.Document, 0, 50, out total,
+ filter: SqlContext.Query().Where(x => x.Name.Contains("tttt"))).ToArray();
Assert.That(entities.Length, Is.EqualTo(50));
Assert.That(total, Is.EqualTo(50));
}
@@ -389,10 +459,12 @@ namespace Umbraco.Tests.Services
var service = ServiceContext.EntityService;
long total;
- var entities = service.GetPagedDescendants(root.Id, UmbracoObjectTypes.Media, 0, 10, out total, filter: "ssss").ToArray();
+ var entities = service.GetPagedDescendants(root.Id, UmbracoObjectTypes.Media, 0, 10, out total,
+ filter: SqlContext.Query().Where(x => x.Name.Contains("ssss"))).ToArray();
Assert.That(entities.Length, Is.EqualTo(10));
Assert.That(total, Is.EqualTo(10));
- entities = service.GetPagedDescendants(root.Id, UmbracoObjectTypes.Media, 0, 50, out total, filter: "tttt").ToArray();
+ entities = service.GetPagedDescendants(root.Id, UmbracoObjectTypes.Media, 0, 50, out total,
+ filter: SqlContext.Query().Where(x => x.Name.Contains("tttt"))).ToArray();
Assert.That(entities.Length, Is.EqualTo(50));
Assert.That(total, Is.EqualTo(50));
}
diff --git a/src/Umbraco.Tests/Umbraco.Tests.csproj b/src/Umbraco.Tests/Umbraco.Tests.csproj
index 99d67c31e2..ea8f1fd13c 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/EventsTest.cs b/src/Umbraco.Tests/UmbracoExamine/EventsTest.cs
index 47fa32cbaa..ed5ae07fc0 100644
--- a/src/Umbraco.Tests/UmbracoExamine/EventsTest.cs
+++ b/src/Umbraco.Tests/UmbracoExamine/EventsTest.cs
@@ -36,7 +36,7 @@ namespace Umbraco.Tests.UmbracoExamine
var valueSet = node.ConvertToValueSet(IndexTypes.Content);
indexer.IndexItems(new[] { valueSet });
- var found = searcher.Search(searcher.CreateCriteria().Id((string)node.Attribute("id")).Compile());
+ var found = searcher.CreateQuery().Id((string)node.Attribute("id")).Execute();
Assert.AreEqual(0, found.TotalItemCount);
}
diff --git a/src/Umbraco.Tests/UmbracoExamine/IndexInitializer.cs b/src/Umbraco.Tests/UmbracoExamine/IndexInitializer.cs
index 09ad340e2b..fbbf2042ca 100644
--- a/src/Umbraco.Tests/UmbracoExamine/IndexInitializer.cs
+++ b/src/Umbraco.Tests/UmbracoExamine/IndexInitializer.cs
@@ -164,7 +164,7 @@ namespace Umbraco.Tests.UmbracoExamine
var i = new UmbracoContentIndex(
"testIndexer",
- UmbracoExamineIndex.UmbracoIndexFieldDefinitions,
+ new UmbracoFieldDefinitionCollection(),
luceneDir,
analyzer,
profilingLogger,
diff --git a/src/Umbraco.Tests/UmbracoExamine/IndexTest.cs b/src/Umbraco.Tests/UmbracoExamine/IndexTest.cs
index f45761dd54..ba6a83adff 100644
--- a/src/Umbraco.Tests/UmbracoExamine/IndexTest.cs
+++ b/src/Umbraco.Tests/UmbracoExamine/IndexTest.cs
@@ -103,7 +103,7 @@ namespace Umbraco.Tests.UmbracoExamine
var searcher = indexer.GetSearcher();
- var results = searcher.Search(searcher.CreateCriteria().Id(555).Compile());
+ var results = searcher.CreateQuery().Id(555).Execute();
Assert.AreEqual(1, results.TotalItemCount);
var result = results.First();
@@ -128,8 +128,6 @@ namespace Umbraco.Tests.UmbracoExamine
validator: new ContentValueSetValidator(false)))
using (indexer.ProcessNonAsync())
{
- contentRebuilder.RegisterIndex(indexer.Name);
- mediaRebuilder.RegisterIndex(indexer.Name);
var searcher = indexer.GetSearcher();
@@ -137,7 +135,7 @@ namespace Umbraco.Tests.UmbracoExamine
contentRebuilder.Populate(indexer);
mediaRebuilder.Populate(indexer);
- var result = searcher.Search(searcher.CreateCriteria().All().Compile());
+ var result = searcher.CreateQuery().All().Execute();
Assert.AreEqual(29, result.TotalItemCount);
}
@@ -208,7 +206,7 @@ namespace Umbraco.Tests.UmbracoExamine
indexer.IndexItem(node.ConvertToValueSet(IndexTypes.Media));
//it will not exist because it exists under 2222
- var results = searcher.Search(searcher.CreateCriteria().Id(2112).Compile());
+ var results = searcher.CreateQuery().Id(2112).Execute();
Assert.AreEqual(0, results.Count());
//now mimic moving 2112 to 1116
@@ -220,7 +218,7 @@ namespace Umbraco.Tests.UmbracoExamine
indexer.IndexItems(new[] { node.ConvertToValueSet(IndexTypes.Media) });
//now ensure it exists
- results = searcher.Search(searcher.CreateCriteria().Id(2112).Compile());
+ results = searcher.CreateQuery().Id(2112).Execute();
Assert.AreEqual(1, results.Count());
}
}
@@ -251,7 +249,7 @@ namespace Umbraco.Tests.UmbracoExamine
indexer1.IndexItem(node.ConvertToValueSet(IndexTypes.Media));
//it will exist because it exists under 2222
- var results = searcher.Search(searcher.CreateCriteria().Id(2112).Compile());
+ var results = searcher.CreateQuery().Id(2112).Execute();
Assert.AreEqual(1, results.Count());
//now mimic moving the node underneath 1116 instead of 2222
@@ -262,7 +260,7 @@ namespace Umbraco.Tests.UmbracoExamine
indexer1.IndexItems(new[] { node.ConvertToValueSet(IndexTypes.Media) });
//now ensure it's deleted
- results = searcher.Search(searcher.CreateCriteria().Id(2112).Compile());
+ results = searcher.CreateQuery().Id(2112).Execute();
Assert.AreEqual(0, results.Count());
}
}
@@ -281,14 +279,13 @@ namespace Umbraco.Tests.UmbracoExamine
validator: new ContentValueSetValidator(false)))
using (indexer.ProcessNonAsync())
{
- rebuilder.RegisterIndex(indexer.Name);
var searcher = indexer.GetSearcher();
//create the whole thing
rebuilder.Populate(indexer);
- var result = searcher.Search(searcher.CreateCriteria().Field(LuceneIndex.CategoryFieldName, IndexTypes.Content).Compile());
+ var result = searcher.CreateQuery().Field(LuceneIndex.CategoryFieldName, IndexTypes.Content).Execute();
Assert.AreEqual(21, result.TotalItemCount);
//delete all content
@@ -299,13 +296,13 @@ namespace Umbraco.Tests.UmbracoExamine
//ensure it's all gone
- result = searcher.Search(searcher.CreateCriteria().Field(LuceneIndex.CategoryFieldName, IndexTypes.Content).Compile());
+ result = searcher.CreateQuery().Field(LuceneIndex.CategoryFieldName, IndexTypes.Content).Execute();
Assert.AreEqual(0, result.TotalItemCount);
//call our indexing methods
rebuilder.Populate(indexer);
- result = searcher.Search(searcher.CreateCriteria().Field(LuceneIndex.CategoryFieldName, IndexTypes.Content).Compile());
+ result = searcher.CreateQuery().Field(LuceneIndex.CategoryFieldName, IndexTypes.Content).Execute();
Assert.AreEqual(21, result.TotalItemCount);
}
}
@@ -333,10 +330,10 @@ namespace Umbraco.Tests.UmbracoExamine
indexer.DeleteFromIndex(1140.ToString());
//this node had children: 1141 & 1142, let's ensure they are also removed
- var results = searcher.Search(searcher.CreateCriteria().Id(1141).Compile());
+ var results = searcher.CreateQuery().Id(1141).Execute();
Assert.AreEqual(0, results.Count());
- results = searcher.Search(searcher.CreateCriteria().Id(1142).Compile());
+ results = searcher.CreateQuery().Id(1142).Execute();
Assert.AreEqual(0, results.Count());
}
diff --git a/src/Umbraco.Tests/UmbracoExamine/SearchTests.cs b/src/Umbraco.Tests/UmbracoExamine/SearchTests.cs
index fbfb2f90c0..7aa36f16e3 100644
--- a/src/Umbraco.Tests/UmbracoExamine/SearchTests.cs
+++ b/src/Umbraco.Tests/UmbracoExamine/SearchTests.cs
@@ -2,16 +2,16 @@
using System.Collections.Generic;
using System.Linq;
using Examine;
+using Examine.Search;
using NUnit.Framework;
-using Examine.LuceneEngine.SearchCriteria;
using Moq;
using Umbraco.Core.Models;
using Umbraco.Core.Persistence.Querying;
using Umbraco.Core.Services;
-using Umbraco.Examine;
using Umbraco.Tests.Testing;
using Umbraco.Core.PropertyEditors;
using Umbraco.Core.Composing;
+using Umbraco.Examine;
namespace Umbraco.Tests.UmbracoExamine
{
@@ -60,21 +60,20 @@ namespace Umbraco.Tests.UmbracoExamine
using (var indexer = IndexInitializer.GetUmbracoIndexer(ProfilingLogger, luceneDir))
using (indexer.ProcessNonAsync())
{
- rebuilder.RegisterIndex(indexer.Name);
indexer.CreateIndex();
rebuilder.Populate(indexer);
var searcher = indexer.GetSearcher();
- var numberSortedCriteria = searcher.CreateCriteria()
- .ParentId(1148).And()
+ var numberSortedCriteria = searcher.CreateQuery()
+ .ParentId(1148)
.OrderBy(new SortableField("sortOrder", SortType.Int));
- var numberSortedResult = searcher.Search(numberSortedCriteria.Compile());
+ var numberSortedResult = numberSortedCriteria.Execute();
- var stringSortedCriteria = searcher.CreateCriteria()
- .ParentId(1148).And()
- .OrderBy("sortOrder"); //will default to string
- var stringSortedResult = searcher.Search(stringSortedCriteria.Compile());
+ var stringSortedCriteria = searcher.CreateQuery()
+ .ParentId(1148)
+ .OrderBy(new SortableField("sortOrder"));//will default to string
+ var stringSortedResult = stringSortedCriteria.Execute();
Assert.AreEqual(12, numberSortedResult.TotalItemCount);
Assert.AreEqual(12, stringSortedResult.TotalItemCount);
diff --git a/src/Umbraco.Web.UI.Client/src/common/directives/components/editor/umbeditorheader.directive.js b/src/Umbraco.Web.UI.Client/src/common/directives/components/editor/umbeditorheader.directive.js
index deb9f4c1ac..f01083d725 100644
--- a/src/Umbraco.Web.UI.Client/src/common/directives/components/editor/umbeditorheader.directive.js
+++ b/src/Umbraco.Web.UI.Client/src/common/directives/components/editor/umbeditorheader.directive.js
@@ -262,7 +262,7 @@ Use this directive to construct a header inside the main editor window.
icon: "=",
hideIcon: "@",
alias: "=",
- hideAlias: "@",
+ hideAlias: "=",
description: "=",
hideDescription: "@",
descriptionLocked: "@",
diff --git a/src/Umbraco.Web.UI.Client/src/common/services/navigation.service.js b/src/Umbraco.Web.UI.Client/src/common/services/navigation.service.js
index 23f3fb6d58..ecc92263bc 100644
--- a/src/Umbraco.Web.UI.Client/src/common/services/navigation.service.js
+++ b/src/Umbraco.Web.UI.Client/src/common/services/navigation.service.js
@@ -30,12 +30,6 @@ function navigationService($routeParams, $location, $q, $timeout, $injector, eve
var nonRoutingQueryStrings = ["mculture", "cculture"];
var retainedQueryStrings = ['mculture'];
- //used to track the current dialog object
- var currentDialog = null;
-
- //tracks the user profile dialog
- var userDialog = null;
-
function setMode(mode) {
switch (mode) {
case 'tree':
@@ -287,7 +281,7 @@ function navigationService($routeParams, $location, $q, $timeout, $injector, eve
appState.setGlobalState("showTray", false);
},
- /**
+ /**
* @ngdoc method
* @name umbraco.services.navigationService#syncTree
* @methodOf umbraco.services.navigationService
diff --git a/src/Umbraco.Web.UI.Client/src/less/healthcheck.less b/src/Umbraco.Web.UI.Client/src/less/healthcheck.less
index d40b59cf81..9e1362d50a 100644
--- a/src/Umbraco.Web.UI.Client/src/less/healthcheck.less
+++ b/src/Umbraco.Web.UI.Client/src/less/healthcheck.less
@@ -242,4 +242,5 @@
.umb-healthcheck-group__details-status-action-description {
margin-top: 5px;
font-size: 12px;
+ padding-left: 165px;
}
diff --git a/src/Umbraco.Web.UI.Client/src/views/common/infiniteeditors/compositions/compositions.controller.js b/src/Umbraco.Web.UI.Client/src/views/common/infiniteeditors/compositions/compositions.controller.js
index 54d5da29a8..75bf414099 100644
--- a/src/Umbraco.Web.UI.Client/src/views/common/infiniteeditors/compositions/compositions.controller.js
+++ b/src/Umbraco.Web.UI.Client/src/views/common/infiniteeditors/compositions/compositions.controller.js
@@ -1,7 +1,7 @@
- (function() {
- "use strict";
+(function () {
+ "use strict";
- function CompositionsController($scope,$location) {
+ function CompositionsController($scope, $location, $filter) {
var vm = this;
var oldModel = null;
@@ -19,18 +19,34 @@
back the changes on cancel */
oldModel = angular.copy($scope.model);
- if(!$scope.model.title) {
+ if (!$scope.model.title) {
$scope.model.title = "Compositions";
}
+ // group the content types by their container paths
+ vm.availableGroups = $filter("orderBy")(
+ _.map(
+ _.groupBy($scope.model.availableCompositeContentTypes, function (compositeContentType) {
+ return compositeContentType.contentType.metaData.containerPath;
+ }), function (group) {
+ return {
+ containerPath: group[0].contentType.metaData.containerPath,
+ compositeContentTypes: group
+ };
+ }
+ ), function (group) {
+ return group.containerPath.replace(/\//g, " ");
+ });
}
+
+
function isSelected(alias) {
- if($scope.model.contentType.compositeContentTypes.indexOf(alias) !== -1) {
+ if ($scope.model.contentType.compositeContentTypes.indexOf(alias) !== -1) {
return true;
}
}
-
+
function openContentType(contentType, section) {
var url = (section === "documentType" ? "/settings/documenttypes/edit/" : "/settings/mediaTypes/edit/") + contentType.id;
$location.path(url);
@@ -38,19 +54,19 @@
function submit() {
if ($scope.model && $scope.model.submit) {
-
+
// check if any compositions has been removed
vm.compositionRemoved = false;
- for(var i = 0; oldModel.compositeContentTypes.length > i; i++) {
+ for (var i = 0; oldModel.compositeContentTypes.length > i; i++) {
var oldComposition = oldModel.compositeContentTypes[i];
- if(_.contains($scope.model.compositeContentTypes, oldComposition) === false) {
+ if (_.contains($scope.model.compositeContentTypes, oldComposition) === false) {
vm.compositionRemoved = true;
}
}
/* submit the form if there havne't been removed any composition
or the confirm checkbox has been checked */
- if(!vm.compositionRemoved || vm.allowSubmit) {
+ if (!vm.compositionRemoved || vm.allowSubmit) {
$scope.model.submit($scope.model);
}
}
@@ -63,8 +79,8 @@
}
onInit();
- }
+ }
- angular.module("umbraco").controller("Umbraco.Editors.CompositionsController", CompositionsController);
+ angular.module("umbraco").controller("Umbraco.Editors.CompositionsController", CompositionsController);
})();
diff --git a/src/Umbraco.Web.UI.Client/src/views/common/infiniteeditors/compositions/compositions.html b/src/Umbraco.Web.UI.Client/src/views/common/infiniteeditors/compositions/compositions.html
index 5d7a5420db..84fbab7cb2 100644
--- a/src/Umbraco.Web.UI.Client/src/views/common/infiniteeditors/compositions/compositions.html
+++ b/src/Umbraco.Web.UI.Client/src/views/common/infiniteeditors/compositions/compositions.html
@@ -60,29 +60,35 @@
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+ {{group.containerPath}}
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/Umbraco.Web.UI.Client/src/views/components/application/umb-login.html b/src/Umbraco.Web.UI.Client/src/views/components/application/umb-login.html
index 7d8ce3e13e..2ce49880d7 100644
--- a/src/Umbraco.Web.UI.Client/src/views/components/application/umb-login.html
+++ b/src/Umbraco.Web.UI.Client/src/views/components/application/umb-login.html
@@ -97,14 +97,7 @@
-
-
@@ -268,4 +261,4 @@
-
\ No newline at end of file
+
diff --git a/src/Umbraco.Web.UI.Client/src/views/content/content.delete.controller.js b/src/Umbraco.Web.UI.Client/src/views/content/content.delete.controller.js
index d4be18cf05..92e02d0d14 100644
--- a/src/Umbraco.Web.UI.Client/src/views/content/content.delete.controller.js
+++ b/src/Umbraco.Web.UI.Client/src/views/content/content.delete.controller.js
@@ -34,22 +34,25 @@ function ContentDeleteController($scope, $timeout, contentResource, treeService,
toggleDeleting(false);
if (rootNode) {
- $timeout(function () {
- //ensure the recycle bin has child nodes now
- var recycleBin = treeService.getDescendantNode(rootNode, -20);
- if (recycleBin) {
- //TODO: This seems to return a rejection and we end up with "Possibly unhanded rejection"
- treeService.syncTree({ node: recycleBin, path: treeService.getPath(recycleBin), forceReload: true });
+ //ensure the recycle bin has child nodes now
+ var recycleBin = treeService.getDescendantNode(rootNode, -20);
+ if (recycleBin) {
+ recycleBin.hasChildren = true;
+ //reload the recycle bin if it's already expanded so the deleted item is shown
+ if (recycleBin.expanded) {
+ treeService.loadNodeChildren({ node: recycleBin, section: "content" });
}
- }, 500);
+ }
}
-
+
//if the current edited item is the same one as we're deleting, we need to navigate elsewhere
if (editorState.current && editorState.current.id == $scope.currentNode.id) {
//If the deleted item lived at the root then just redirect back to the root, otherwise redirect to the item's parent
var location = "/content";
- if ($scope.currentNode.parentId.toString() !== "-1")
+ if ($scope.currentNode.parentId.toString() === "-20")
+ location = "/content/content/recyclebin";
+ else if ($scope.currentNode.parentId.toString() !== "-1")
location = "/content/content/edit/" + $scope.currentNode.parentId;
$location.path(location);
diff --git a/src/Umbraco.Web.UI.Client/src/views/content/notify.html b/src/Umbraco.Web.UI.Client/src/views/content/notify.html
index cb12d92f08..e7c4d4d785 100644
--- a/src/Umbraco.Web.UI.Client/src/views/content/notify.html
+++ b/src/Umbraco.Web.UI.Client/src/views/content/notify.html
@@ -15,10 +15,11 @@