From 193bc74f2609c785eac1333ac93ba4da5a63bcc3 Mon Sep 17 00:00:00 2001 From: Shannon Date: Tue, 18 Dec 2018 17:55:30 +1100 Subject: [PATCH 01/14] removes configuration based indexes --- .../Config/ConfigIndexCriteria.cs | 36 ------ .../Config/ConfigIndexField.cs | 61 --------- .../Config/IndexFieldCollection.cs | 47 ------- .../Config/IndexFieldCollectionExtensions.cs | 15 --- src/Umbraco.Examine/Config/IndexSet.cs | 80 ------------ .../Config/IndexSetCollection.cs | 29 ----- src/Umbraco.Examine/Config/IndexSets.cs | 21 ---- src/Umbraco.Examine/Umbraco.Examine.csproj | 9 +- src/Umbraco.Examine/UmbracoContentIndex.cs | 80 +----------- src/Umbraco.Examine/UmbracoExamineIndex.cs | 118 +----------------- .../UmbracoExamineIndexDiagnostics.cs | 2 +- src/Umbraco.Examine/UmbracoMemberIndex.cs | 30 +---- .../TestHelpers/Stubs/TestExamineManager.cs | 6 +- src/Umbraco.Tests/Umbraco.Tests.csproj | 2 +- .../UmbracoExamine/IndexInitializer.cs | 2 +- src/Umbraco.Web.UI/Umbraco.Web.UI.csproj | 13 +- .../config/ExamineIndex.Release.config | 10 -- src/Umbraco.Web.UI/config/ExamineIndex.config | 14 --- .../config/ExamineSettings.Release.config | 21 ---- .../config/ExamineSettings.config | 23 ---- src/Umbraco.Web.UI/web.Template.Debug.config | 14 ++- src/Umbraco.Web.UI/web.Template.config | 4 - .../Search/UmbracoIndexesCreator.cs | 13 +- src/Umbraco.Web/Umbraco.Web.csproj | 2 +- 24 files changed, 32 insertions(+), 620 deletions(-) delete mode 100644 src/Umbraco.Examine/Config/ConfigIndexCriteria.cs delete mode 100644 src/Umbraco.Examine/Config/ConfigIndexField.cs delete mode 100644 src/Umbraco.Examine/Config/IndexFieldCollection.cs delete mode 100644 src/Umbraco.Examine/Config/IndexFieldCollectionExtensions.cs delete mode 100644 src/Umbraco.Examine/Config/IndexSet.cs delete mode 100644 src/Umbraco.Examine/Config/IndexSetCollection.cs delete mode 100644 src/Umbraco.Examine/Config/IndexSets.cs delete mode 100644 src/Umbraco.Web.UI/config/ExamineIndex.Release.config delete mode 100644 src/Umbraco.Web.UI/config/ExamineIndex.config delete mode 100644 src/Umbraco.Web.UI/config/ExamineSettings.Release.config delete mode 100644 src/Umbraco.Web.UI/config/ExamineSettings.config diff --git a/src/Umbraco.Examine/Config/ConfigIndexCriteria.cs b/src/Umbraco.Examine/Config/ConfigIndexCriteria.cs deleted file mode 100644 index de2a5ced36..0000000000 --- a/src/Umbraco.Examine/Config/ConfigIndexCriteria.cs +++ /dev/null @@ -1,36 +0,0 @@ -using System.Collections.Generic; -using System.Linq; -using Examine; - -namespace Umbraco.Examine.Config -{ - /// - /// a data structure for storing indexing/searching instructions based on config based indexers - /// - public class ConfigIndexCriteria - { - /// - /// Constructor - /// - /// - /// - /// - /// - /// - public ConfigIndexCriteria(IEnumerable standardFields, IEnumerable userFields, IEnumerable includeNodeTypes, IEnumerable excludeNodeTypes, int? parentNodeId) - { - UserFields = userFields.ToList(); - StandardFields = standardFields.ToList(); - IncludeItemTypes = includeNodeTypes; - ExcludeItemTypes = excludeNodeTypes; - ParentNodeId = parentNodeId; - } - - public IEnumerable StandardFields { get; internal set; } - public IEnumerable UserFields { get; internal set; } - - public IEnumerable IncludeItemTypes { get; internal set; } - public IEnumerable ExcludeItemTypes { get; internal set; } - public int? ParentNodeId { get; internal set; } - } -} \ No newline at end of file diff --git a/src/Umbraco.Examine/Config/ConfigIndexField.cs b/src/Umbraco.Examine/Config/ConfigIndexField.cs deleted file mode 100644 index ec9cbf797e..0000000000 --- a/src/Umbraco.Examine/Config/ConfigIndexField.cs +++ /dev/null @@ -1,61 +0,0 @@ -using System.Configuration; - -namespace Umbraco.Examine.Config -{ - /// - /// A configuration item representing a field to index - /// - public sealed class ConfigIndexField : ConfigurationElement - { - [ConfigurationProperty("Name", IsRequired = true)] - public string Name - { - get => (string)this["Name"]; - set => this["Name"] = value; - } - - [ConfigurationProperty("EnableSorting", IsRequired = false)] - public bool EnableSorting - { - get => (bool)this["EnableSorting"]; - set => this["EnableSorting"] = value; - } - - [ConfigurationProperty("Type", IsRequired = false, DefaultValue = "String")] - public string Type - { - get => (string)this["Type"]; - set => this["Type"] = value; - } - - public bool Equals(ConfigIndexField other) - { - if (ReferenceEquals(null, other)) return false; - if (ReferenceEquals(this, other)) return true; - return string.Equals(Name, other.Name); - } - - public override bool Equals(object obj) - { - if (ReferenceEquals(null, obj)) return false; - if (ReferenceEquals(this, obj)) return true; - if (obj.GetType() != this.GetType()) return false; - return Equals((ConfigIndexField)obj); - } - - public override int GetHashCode() - { - return Name.GetHashCode(); - } - - public static bool operator ==(ConfigIndexField left, ConfigIndexField right) - { - return Equals(left, right); - } - - public static bool operator !=(ConfigIndexField left, ConfigIndexField right) - { - return !Equals(left, right); - } - } -} \ No newline at end of file diff --git a/src/Umbraco.Examine/Config/IndexFieldCollection.cs b/src/Umbraco.Examine/Config/IndexFieldCollection.cs deleted file mode 100644 index 063c157dbe..0000000000 --- a/src/Umbraco.Examine/Config/IndexFieldCollection.cs +++ /dev/null @@ -1,47 +0,0 @@ -using System.Configuration; - -namespace Umbraco.Examine.Config -{ - public sealed class IndexFieldCollection : ConfigurationElementCollection - { - #region Overridden methods to define collection - protected override ConfigurationElement CreateNewElement() - { - return new ConfigIndexField(); - } - protected override object GetElementKey(ConfigurationElement element) - { - ConfigIndexField field = (ConfigIndexField)element; - return field.Name; - } - - public override bool IsReadOnly() - { - return false; - } - #endregion - - /// - /// Adds an index field to the collection - /// - /// - public void Add(ConfigIndexField field) - { - BaseAdd(field, true); - } - - /// - /// Default property for accessing an IndexField definition - /// - /// Field Name - /// - public new ConfigIndexField this[string name] - { - get - { - return (ConfigIndexField)this.BaseGet(name); - } - } - - } -} \ No newline at end of file diff --git a/src/Umbraco.Examine/Config/IndexFieldCollectionExtensions.cs b/src/Umbraco.Examine/Config/IndexFieldCollectionExtensions.cs deleted file mode 100644 index eea117ce05..0000000000 --- a/src/Umbraco.Examine/Config/IndexFieldCollectionExtensions.cs +++ /dev/null @@ -1,15 +0,0 @@ -using System.Collections.Generic; - -namespace Umbraco.Examine.Config -{ - public static class IndexFieldCollectionExtensions - { - public static List ToList(this IndexFieldCollection indexes) - { - List fields = new List(); - foreach (ConfigIndexField field in indexes) - fields.Add(field); - return fields; - } - } -} \ No newline at end of file diff --git a/src/Umbraco.Examine/Config/IndexSet.cs b/src/Umbraco.Examine/Config/IndexSet.cs deleted file mode 100644 index 65b1cd5aec..0000000000 --- a/src/Umbraco.Examine/Config/IndexSet.cs +++ /dev/null @@ -1,80 +0,0 @@ -using System.Configuration; -using System.IO; -using System.Web; -using System.Web.Hosting; - -namespace Umbraco.Examine.Config -{ - public sealed class IndexSet : ConfigurationElement - { - - [ConfigurationProperty("SetName", IsRequired = true, IsKey = true)] - public string SetName => (string)this["SetName"]; - - /// - /// When this property is set, the indexing will only index documents that are descendants of this node. - /// - [ConfigurationProperty("IndexParentId", IsRequired = false, IsKey = false)] - public int? IndexParentId - { - get - { - if (this["IndexParentId"] == null) - return null; - - return (int)this["IndexParentId"]; - } - } - - /// - /// The collection of node types to index, if not specified, all node types will be indexed (apart from the ones specified in the ExcludeNodeTypes collection). - /// - [ConfigurationCollection(typeof(IndexFieldCollection))] - [ConfigurationProperty("IncludeNodeTypes", IsDefaultCollection = false, IsRequired = false)] - public IndexFieldCollection IncludeNodeTypes => (IndexFieldCollection)base["IncludeNodeTypes"]; - - /// - /// The collection of node types to not index. If specified, these node types will not be indexed. - /// - [ConfigurationCollection(typeof(IndexFieldCollection))] - [ConfigurationProperty("ExcludeNodeTypes", IsDefaultCollection = false, IsRequired = false)] - public IndexFieldCollection ExcludeNodeTypes => (IndexFieldCollection)base["ExcludeNodeTypes"]; - - /// - /// A collection of user defined umbraco fields to index - /// - /// - /// If this property is not specified, or if it's an empty collection, the default user fields will be all user fields defined in Umbraco - /// - [ConfigurationCollection(typeof(IndexFieldCollection))] - [ConfigurationProperty("IndexUserFields", IsDefaultCollection = false, IsRequired = false)] - public IndexFieldCollection IndexUserFields => (IndexFieldCollection)base["IndexUserFields"]; - - /// - /// The fields umbraco values that will be indexed. i.e. id, nodeTypeAlias, writer, etc... - /// - /// - /// If this is not specified, or if it's an empty collection, the default optins will be specified: - /// - id - /// - version - /// - parentID - /// - level - /// - writerID - /// - creatorID - /// - nodeType - /// - template - /// - sortOrder - /// - createDate - /// - updateDate - /// - nodeName - /// - urlName - /// - writerName - /// - creatorName - /// - nodeTypeAlias - /// - path - /// - [ConfigurationCollection(typeof(IndexFieldCollection))] - [ConfigurationProperty("IndexAttributeFields", IsDefaultCollection = false, IsRequired = false)] - public IndexFieldCollection IndexAttributeFields => (IndexFieldCollection)base["IndexAttributeFields"]; - } -} diff --git a/src/Umbraco.Examine/Config/IndexSetCollection.cs b/src/Umbraco.Examine/Config/IndexSetCollection.cs deleted file mode 100644 index bfce8e4cce..0000000000 --- a/src/Umbraco.Examine/Config/IndexSetCollection.cs +++ /dev/null @@ -1,29 +0,0 @@ -using System.Configuration; - - -namespace Umbraco.Examine.Config -{ - public sealed class IndexSetCollection : ConfigurationElementCollection - { - #region Overridden methods to define collection - protected override ConfigurationElement CreateNewElement() - { - return new IndexSet(); - } - protected override object GetElementKey(ConfigurationElement element) - { - return ((IndexSet)element).SetName; - } - public override ConfigurationElementCollectionType CollectionType => ConfigurationElementCollectionType.BasicMap; - protected override string ElementName => "IndexSet"; - - #endregion - - /// - /// Default property for accessing Image Sets - /// - /// - /// - public new IndexSet this[string setName] => (IndexSet)this.BaseGet(setName); - } -} \ No newline at end of file diff --git a/src/Umbraco.Examine/Config/IndexSets.cs b/src/Umbraco.Examine/Config/IndexSets.cs deleted file mode 100644 index c6ad1476c3..0000000000 --- a/src/Umbraco.Examine/Config/IndexSets.cs +++ /dev/null @@ -1,21 +0,0 @@ -using System.Configuration; - -namespace Umbraco.Examine.Config -{ - public sealed class IndexSets : ConfigurationSection - { - #region Singleton definition - - private IndexSets() { } - - public static IndexSets Instance { get; } = ConfigurationManager.GetSection(SectionName) as IndexSets; - - #endregion - - private const string SectionName = "ExamineLuceneIndexSets"; - - [ConfigurationCollection(typeof(IndexSetCollection))] - [ConfigurationProperty("", IsDefaultCollection = true, IsRequired = true)] - public IndexSetCollection Sets => (IndexSetCollection)base[""]; - } -} diff --git a/src/Umbraco.Examine/Umbraco.Examine.csproj b/src/Umbraco.Examine/Umbraco.Examine.csproj index 2bdf6f833d..9191f7b38d 100644 --- a/src/Umbraco.Examine/Umbraco.Examine.csproj +++ b/src/Umbraco.Examine/Umbraco.Examine.csproj @@ -48,19 +48,12 @@ - + - - - - - - - diff --git a/src/Umbraco.Examine/UmbracoContentIndex.cs b/src/Umbraco.Examine/UmbracoContentIndex.cs index c584f5bf51..5a01f0f98c 100644 --- a/src/Umbraco.Examine/UmbracoContentIndex.cs +++ b/src/Umbraco.Examine/UmbracoContentIndex.cs @@ -6,14 +6,10 @@ using System.Linq; using Examine; using Umbraco.Core; using Umbraco.Core.Services; -using Umbraco.Core.Strings; -using Examine.LuceneEngine.Indexing; -using Examine.LuceneEngine.Providers; using Lucene.Net.Analysis; using Lucene.Net.Store; using Umbraco.Core.Composing; using Umbraco.Core.Logging; -using Umbraco.Examine.Config; using Examine.LuceneEngine; namespace Umbraco.Examine @@ -27,18 +23,7 @@ namespace Umbraco.Examine protected ILocalizationService LanguageService { get; } #region Constructors - - /// - /// Constructor for configuration providers - /// - [EditorBrowsable(EditorBrowsableState.Never)] - public UmbracoContentIndex() - { - LanguageService = Current.Services.LocalizationService; - - //note: The validator for this config based indexer is set in the Initialize method - } - + /// /// Create an index at runtime /// @@ -52,14 +37,14 @@ namespace Umbraco.Examine /// public UmbracoContentIndex( string name, - FieldDefinitionCollection fieldDefinitions, Directory luceneDirectory, + FieldDefinitionCollection fieldDefinitions, Analyzer defaultAnalyzer, ProfilingLogger profilingLogger, ILocalizationService languageService, IContentValueSetValidator validator, IReadOnlyDictionary indexValueTypes = null) - : base(name, fieldDefinitions, luceneDirectory, defaultAnalyzer, profilingLogger, validator, indexValueTypes) + : base(name, luceneDirectory, fieldDefinitions, defaultAnalyzer, profilingLogger, validator, indexValueTypes) { if (validator == null) throw new ArgumentNullException(nameof(validator)); LanguageService = languageService ?? throw new ArgumentNullException(nameof(languageService)); @@ -70,65 +55,6 @@ namespace Umbraco.Examine #endregion - #region Initialize - - /// - /// Set up all properties for the indexer based on configuration information specified. This will ensure that - /// all of the folders required by the indexer are created and exist. This will also create an instruction - /// file declaring the computer name that is part taking in the indexing. This file will then be used to - /// determine the master indexer machine in a load balanced environment (if one exists). - /// - /// The friendly name of the provider. - /// A collection of the name/value pairs representing the provider-specific attributes specified in the configuration for this provider. - /// - /// The name of the provider is null. - /// - /// - /// The name of the provider has a length of zero. - /// - /// - /// An attempt is made to call on a provider after the provider has already been initialized. - /// - [EditorBrowsable(EditorBrowsableState.Never)] - public override void Initialize(string name, NameValueCollection config) - { - base.Initialize(name, config); - - var supportUnpublished = false; - var supportProtected = false; - - //check if there's a flag specifying to support unpublished content, - //if not, set to false; - if (config["supportUnpublished"] != null) - bool.TryParse(config["supportUnpublished"], out supportUnpublished); - - //check if there's a flag specifying to support protected content, - //if not, set to false; - if (config["supportProtected"] != null) - bool.TryParse(config["supportProtected"], out supportProtected); - - - //now we need to build up the indexer options so we can create our validator - int? parentId = null; - if (IndexSetName.IsNullOrWhiteSpace() == false) - { - var indexSet = IndexSets.Instance.Sets[IndexSetName]; - parentId = indexSet.IndexParentId; - } - - ValueSetValidator = new ContentValueSetValidator( - supportUnpublished, supportProtected, - //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); - - PublishedValuesOnly = supportUnpublished; - } - - #endregion - /// /// Special check for invalid paths /// diff --git a/src/Umbraco.Examine/UmbracoExamineIndex.cs b/src/Umbraco.Examine/UmbracoExamineIndex.cs index fc7f834a29..8cad9308fe 100644 --- a/src/Umbraco.Examine/UmbracoExamineIndex.cs +++ b/src/Umbraco.Examine/UmbracoExamineIndex.cs @@ -1,6 +1,5 @@ using System; using System.Collections.Generic; -using System.ComponentModel; using System.Linq; using Examine.LuceneEngine.Providers; using Lucene.Net.Analysis; @@ -9,11 +8,9 @@ using Lucene.Net.Index; using Umbraco.Core; using Examine; using Examine.LuceneEngine; -using Examine.LuceneEngine.Indexing; using Lucene.Net.Store; using Umbraco.Core.Composing; using Umbraco.Core.Logging; -using Umbraco.Examine.Config; using Directory = Lucene.Net.Store.Directory; namespace Umbraco.Examine @@ -43,18 +40,6 @@ namespace Umbraco.Examine /// public const string RawFieldPrefix = SpecialFieldPrefix + "Raw_"; - /// - /// Constructor for config provider based indexes - /// - [EditorBrowsable(EditorBrowsableState.Never)] - protected UmbracoExamineIndex() - : base() - { - ProfilingLogger = Current.ProfilingLogger; - _configBased = true; - _diagnostics = new UmbracoExamineIndexDiagnostics(this, ProfilingLogger.Logger); - } - /// /// Create a new /// @@ -67,13 +52,13 @@ namespace Umbraco.Examine /// protected UmbracoExamineIndex( string name, - FieldDefinitionCollection fieldDefinitions, Directory luceneDirectory, + FieldDefinitionCollection fieldDefinitions, Analyzer defaultAnalyzer, ProfilingLogger profilingLogger, IValueSetValidator validator = null, IReadOnlyDictionary indexValueTypes = null) - : base(name, fieldDefinitions, luceneDirectory, defaultAnalyzer, validator, indexValueTypes) + : base(name, luceneDirectory, fieldDefinitions, defaultAnalyzer, validator, indexValueTypes) { ProfilingLogger = profilingLogger ?? throw new ArgumentNullException(nameof(profilingLogger)); @@ -105,93 +90,6 @@ namespace Umbraco.Examine return searcher.GetAllIndexedFields(); } - protected ConfigIndexCriteria ConfigIndexCriteria { get; private set; } - - /// - /// The index set name which references an Examine - /// - public string IndexSetName { get; private set; } - - #region Initialize - - - /// - /// Setup the properties for the indexer from the provider settings - /// - /// - /// - /// - /// This is ONLY used for configuration based indexes - /// - public override void Initialize(string name, System.Collections.Specialized.NameValueCollection config) - { - ProfilingLogger.Logger.Debug(GetType(), "{IndexerName} indexer initializing", name); - - if (config["enableDefaultEventHandler"] != null && bool.TryParse(config["enableDefaultEventHandler"], out var enabled)) - { - EnableDefaultEventHandler = enabled; - } - - //this is config based, so add the default definitions - foreach (var field in UmbracoFieldDefinitionCollection.UmbracoIndexFieldDefinitions) - { - 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) - { - if (!name.EndsWith(suffix)) continue; - - var setNameByConvension = name.Remove(name.LastIndexOf(suffix, StringComparison.Ordinal)) + "IndexSet"; - //check if we can assign the index set by naming convention - var set = IndexSets.Instance.Sets.Cast().SingleOrDefault(x => x.SetName == setNameByConvension); - - if (set == null) continue; - - //we've found an index set by naming conventions :) - IndexSetName = set.SetName; - - 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)) - { - //replace any existing or add - FieldDefinitionCollection.AddOrUpdate(fieldDefinition); - } - break; - } - } - 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"); - - 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)) - { - //replace any existing or add - FieldDefinitionCollection.AddOrUpdate(fieldDefinition); - } - } - - base.Initialize(name, config); - } - - #endregion - /// /// override to check if we can actually initialize. /// @@ -288,17 +186,7 @@ namespace Umbraco.Examine e.ValueSet.Values[IconFieldName] = icon; } } - - private ConfigIndexCriteria CreateFieldDefinitionsFromConfig(IndexSet indexSet) - { - return new ConfigIndexCriteria( - indexSet.IndexAttributeFields.Cast().Select(x => new FieldDefinition(x.Name, x.Type)).ToArray(), - indexSet.IndexUserFields.Cast().Select(x => new FieldDefinition(x.Name, x.Type)).ToArray(), - indexSet.IncludeNodeTypes.ToList().Select(x => x.Name).ToArray(), - indexSet.ExcludeNodeTypes.ToList().Select(x => x.Name).ToArray(), - indexSet.IndexParentId); - } - + #region IIndexDiagnostics private readonly UmbracoExamineIndexDiagnostics _diagnostics; diff --git a/src/Umbraco.Examine/UmbracoExamineIndexDiagnostics.cs b/src/Umbraco.Examine/UmbracoExamineIndexDiagnostics.cs index 227b52e085..fed5b9bae7 100644 --- a/src/Umbraco.Examine/UmbracoExamineIndexDiagnostics.cs +++ b/src/Umbraco.Examine/UmbracoExamineIndexDiagnostics.cs @@ -64,7 +64,7 @@ namespace Umbraco.Examine { [nameof(UmbracoExamineIndex.CommitCount)] = _index.CommitCount, [nameof(UmbracoExamineIndex.DefaultAnalyzer)] = _index.DefaultAnalyzer.GetType().Name, - [nameof(UmbracoExamineIndex.DirectoryFactory)] = _index.DirectoryFactory, + ["LuceneDirectory"] = _index.GetLuceneDirectory().GetType().Name, [nameof(UmbracoExamineIndex.EnableDefaultEventHandler)] = _index.EnableDefaultEventHandler, [nameof(UmbracoExamineIndex.LuceneIndexFolder)] = _index.LuceneIndexFolder == null diff --git a/src/Umbraco.Examine/UmbracoMemberIndex.cs b/src/Umbraco.Examine/UmbracoMemberIndex.cs index 27490e0e18..19eca7edc3 100644 --- a/src/Umbraco.Examine/UmbracoMemberIndex.cs +++ b/src/Umbraco.Examine/UmbracoMemberIndex.cs @@ -1,18 +1,7 @@ -using System; -using System.Linq; -using Umbraco.Core; -using Umbraco.Core.Models; -using Umbraco.Core.Persistence.DatabaseModelDefinitions; -using Umbraco.Core.Services; -using System.Collections.Generic; -using System.Collections.Specialized; -using System.ComponentModel; +using System.Collections.Generic; using Examine; using Examine.LuceneEngine; -using Examine.LuceneEngine.Indexing; -using Examine.LuceneEngine.Providers; using Lucene.Net.Analysis; -using Umbraco.Core.Composing; using Umbraco.Core.Logging; using Directory = Lucene.Net.Store.Directory; @@ -24,14 +13,6 @@ namespace Umbraco.Examine /// public class UmbracoMemberIndex : UmbracoExamineIndex { - /// - /// Constructor for config/provider based indexes - /// - [EditorBrowsable(EditorBrowsableState.Never)] - public UmbracoMemberIndex() - { - } - /// /// Constructor to allow for creating an indexer at runtime /// @@ -48,17 +29,10 @@ namespace Umbraco.Examine Analyzer analyzer, ProfilingLogger profilingLogger, IValueSetValidator validator = null) : - base(name, fieldDefinitions, luceneDirectory, analyzer, profilingLogger, validator) + base(name, luceneDirectory, fieldDefinitions, analyzer, profilingLogger, validator) { } - public override void Initialize(string name, NameValueCollection config) - { - base.Initialize(name, config); - - ValueSetValidator = new MemberValueSetValidator(ConfigIndexCriteria.IncludeItemTypes, ConfigIndexCriteria.ExcludeItemTypes); - } - /// /// Overridden to ensure that the umbraco system field definitions are in place /// diff --git a/src/Umbraco.Tests/TestHelpers/Stubs/TestExamineManager.cs b/src/Umbraco.Tests/TestHelpers/Stubs/TestExamineManager.cs index f8d48c5703..7bb3b90d81 100644 --- a/src/Umbraco.Tests/TestHelpers/Stubs/TestExamineManager.cs +++ b/src/Umbraco.Tests/TestHelpers/Stubs/TestExamineManager.cs @@ -9,14 +9,16 @@ namespace Umbraco.Tests.TestHelpers.Stubs private readonly ConcurrentDictionary _indexers = new ConcurrentDictionary(); private readonly ConcurrentDictionary _searchers = new ConcurrentDictionary(); - public void AddIndex(IIndex indexer) + public IIndex AddIndex(IIndex indexer) { _indexers.TryAdd(indexer.Name, indexer); + return indexer; } - public void AddSearcher(ISearcher searcher) + public ISearcher AddSearcher(ISearcher searcher) { _searchers.TryAdd(searcher.Name, searcher); + return searcher; } public void Dispose() diff --git a/src/Umbraco.Tests/Umbraco.Tests.csproj b/src/Umbraco.Tests/Umbraco.Tests.csproj index 35a51e0584..e239ee0d93 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 4435a5e829..ee4b1aadde 100644 --- a/src/Umbraco.Tests/UmbracoExamine/IndexInitializer.cs +++ b/src/Umbraco.Tests/UmbracoExamine/IndexInitializer.cs @@ -164,8 +164,8 @@ namespace Umbraco.Tests.UmbracoExamine var i = new UmbracoContentIndex( "testIndexer", - new UmbracoFieldDefinitionCollection(), luceneDir, + new UmbracoFieldDefinitionCollection(), analyzer, profilingLogger, languageService, diff --git a/src/Umbraco.Web.UI/Umbraco.Web.UI.csproj b/src/Umbraco.Web.UI/Umbraco.Web.UI.csproj index afb3cfa9d7..8e2e6a099f 100644 --- a/src/Umbraco.Web.UI/Umbraco.Web.UI.csproj +++ b/src/Umbraco.Web.UI/Umbraco.Web.UI.csproj @@ -88,7 +88,7 @@ - + @@ -276,16 +276,9 @@ scripting.config - - ExamineSettings.config - feedProxy.config - - ExamineIndex.config - Designer - Dashboard.config Designer @@ -345,10 +338,6 @@ Designer - - - Designer - diff --git a/src/Umbraco.Web.UI/config/ExamineIndex.Release.config b/src/Umbraco.Web.UI/config/ExamineIndex.Release.config deleted file mode 100644 index ec0d18aa2d..0000000000 --- a/src/Umbraco.Web.UI/config/ExamineIndex.Release.config +++ /dev/null @@ -1,10 +0,0 @@ - - - - diff --git a/src/Umbraco.Web.UI/config/ExamineIndex.config b/src/Umbraco.Web.UI/config/ExamineIndex.config deleted file mode 100644 index 833a65c8d1..0000000000 --- a/src/Umbraco.Web.UI/config/ExamineIndex.config +++ /dev/null @@ -1,14 +0,0 @@ - - - - diff --git a/src/Umbraco.Web.UI/config/ExamineSettings.Release.config b/src/Umbraco.Web.UI/config/ExamineSettings.Release.config deleted file mode 100644 index 6b3aaa0372..0000000000 --- a/src/Umbraco.Web.UI/config/ExamineSettings.Release.config +++ /dev/null @@ -1,21 +0,0 @@ - - - - - - - - - - - - - - - diff --git a/src/Umbraco.Web.UI/config/ExamineSettings.config b/src/Umbraco.Web.UI/config/ExamineSettings.config deleted file mode 100644 index f0fd2b69fc..0000000000 --- a/src/Umbraco.Web.UI/config/ExamineSettings.config +++ /dev/null @@ -1,23 +0,0 @@ - - - - - - - - - - - - - - diff --git a/src/Umbraco.Web.UI/web.Template.Debug.config b/src/Umbraco.Web.UI/web.Template.Debug.config index 5a37c4a09b..8c4b3bb299 100644 --- a/src/Umbraco.Web.UI/web.Template.Debug.config +++ b/src/Umbraco.Web.UI/web.Template.Debug.config @@ -1,7 +1,8 @@ - + + +
+
+ + + + + - + diff --git a/src/Umbraco.Web.UI/web.Template.config b/src/Umbraco.Web.UI/web.Template.config index 50319370e9..4e067bc681 100644 --- a/src/Umbraco.Web.UI/web.Template.config +++ b/src/Umbraco.Web.UI/web.Template.config @@ -10,8 +10,6 @@
-
-
@@ -36,8 +34,6 @@ - - diff --git a/src/Umbraco.Web/Search/UmbracoIndexesCreator.cs b/src/Umbraco.Web/Search/UmbracoIndexesCreator.cs index 4296176abf..3e78d2acfa 100644 --- a/src/Umbraco.Web/Search/UmbracoIndexesCreator.cs +++ b/src/Umbraco.Web/Search/UmbracoIndexesCreator.cs @@ -1,20 +1,11 @@ using System.Collections.Generic; using Umbraco.Core.Logging; using Umbraco.Core.Services; -using Umbraco.Core.Strings; using Umbraco.Examine; -using Umbraco.Core.Persistence; -using Umbraco.Core.IO; -using System.IO; -using Lucene.Net.Store; using Lucene.Net.Analysis.Standard; -using Lucene.Net.Analysis; using Examine.LuceneEngine; using Examine; -using Examine.LuceneEngine.Providers; -using System.Linq; using Umbraco.Core; -using Umbraco.Core.Models; namespace Umbraco.Web.Search { @@ -59,8 +50,8 @@ namespace Umbraco.Web.Search { var index = new UmbracoContentIndex( Constants.UmbracoIndexes.InternalIndexName, - new UmbracoFieldDefinitionCollection(), CreateFileSystemLuceneDirectory(Constants.UmbracoIndexes.InternalIndexPath), + new UmbracoFieldDefinitionCollection(), new CultureInvariantWhitespaceAnalyzer(), ProfilingLogger, LanguageService, @@ -72,8 +63,8 @@ namespace Umbraco.Web.Search { var index = new UmbracoContentIndex( Constants.UmbracoIndexes.ExternalIndexName, - new UmbracoFieldDefinitionCollection(), CreateFileSystemLuceneDirectory(Constants.UmbracoIndexes.ExternalIndexPath), + new UmbracoFieldDefinitionCollection(), new StandardAnalyzer(Lucene.Net.Util.Version.LUCENE_30), ProfilingLogger, LanguageService, diff --git a/src/Umbraco.Web/Umbraco.Web.csproj b/src/Umbraco.Web/Umbraco.Web.csproj index 9c44539f92..f718b7e817 100755 --- a/src/Umbraco.Web/Umbraco.Web.csproj +++ b/src/Umbraco.Web/Umbraco.Web.csproj @@ -62,7 +62,7 @@ - + 2.6.2.25 From 70dd85f708dce2996f9cfc0dfedfc7312bf2560e Mon Sep 17 00:00:00 2001 From: Stephan Date: Fri, 21 Dec 2018 10:38:14 +0100 Subject: [PATCH 02/14] Misc fix --- src/Umbraco.Examine/IIndexPopulator.cs | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/src/Umbraco.Examine/IIndexPopulator.cs b/src/Umbraco.Examine/IIndexPopulator.cs index 153e88d46b..97a1216fae 100644 --- a/src/Umbraco.Examine/IIndexPopulator.cs +++ b/src/Umbraco.Examine/IIndexPopulator.cs @@ -1,22 +1,20 @@ -using System.Collections.Generic; -using Examine; +using Examine; namespace Umbraco.Examine { public interface IIndexPopulator { /// - /// If this index is registered with this populatr + /// If this index is registered with this populator /// /// /// bool IsRegistered(IIndex index); /// - /// Populate indexers + /// Populate indexers /// /// void Populate(params IIndex[] indexes); } - } From e20e570dc86511591aa245123e510eb6239b49d8 Mon Sep 17 00:00:00 2001 From: Shannon Date: Mon, 7 Jan 2019 16:15:51 +1100 Subject: [PATCH 03/14] Fixes tests --- .../PublishedCache/XmlPublishedCache/PublishedMediaCache.cs | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/Umbraco.Web/PublishedCache/XmlPublishedCache/PublishedMediaCache.cs b/src/Umbraco.Web/PublishedCache/XmlPublishedCache/PublishedMediaCache.cs index 229a981510..9e45bc17c5 100644 --- a/src/Umbraco.Web/PublishedCache/XmlPublishedCache/PublishedMediaCache.cs +++ b/src/Umbraco.Web/PublishedCache/XmlPublishedCache/PublishedMediaCache.cs @@ -239,9 +239,7 @@ namespace Umbraco.Web.PublishedCache.XmlPublishedCache try { - if (eMgr.TryGetIndex(Constants.UmbracoIndexes.InternalIndexName, out var index)) - return index.GetSearcher(); - throw new InvalidOperationException($"No index found by name {Constants.UmbracoIndexes.InternalIndexName}"); + return eMgr.TryGetIndex(Constants.UmbracoIndexes.InternalIndexName, out var index) ? index.GetSearcher() : null; } catch (FileNotFoundException) { From 0356e5a2247100f0f60bd8b54f21980523720621 Mon Sep 17 00:00:00 2001 From: Shannon Date: Mon, 7 Jan 2019 18:16:06 +1100 Subject: [PATCH 04/14] Updates to latest examine, fixes issue with rebuilding indexes in the back office seeming to timeout but was a problem with the callback registration in examine --- build/NuSpecs/UmbracoCms.Web.nuspec | 2 +- src/Umbraco.Examine/Umbraco.Examine.csproj | 2 +- src/Umbraco.Examine/UmbracoContentIndex.cs | 34 ++++++++++++---------- src/Umbraco.Examine/UmbracoExamineIndex.cs | 4 +-- src/Umbraco.Tests/Umbraco.Tests.csproj | 2 +- src/Umbraco.Web.UI/Umbraco.Web.UI.csproj | 2 +- src/Umbraco.Web/Umbraco.Web.csproj | 2 +- 7 files changed, 26 insertions(+), 22 deletions(-) diff --git a/build/NuSpecs/UmbracoCms.Web.nuspec b/build/NuSpecs/UmbracoCms.Web.nuspec index 51d7e3b8d0..35e79d8127 100644 --- a/build/NuSpecs/UmbracoCms.Web.nuspec +++ b/build/NuSpecs/UmbracoCms.Web.nuspec @@ -25,7 +25,7 @@ - + diff --git a/src/Umbraco.Examine/Umbraco.Examine.csproj b/src/Umbraco.Examine/Umbraco.Examine.csproj index 9191f7b38d..a68131da0d 100644 --- a/src/Umbraco.Examine/Umbraco.Examine.csproj +++ b/src/Umbraco.Examine/Umbraco.Examine.csproj @@ -48,7 +48,7 @@ - + diff --git a/src/Umbraco.Examine/UmbracoContentIndex.cs b/src/Umbraco.Examine/UmbracoContentIndex.cs index ce4b410bb3..a9e2c72cb6 100644 --- a/src/Umbraco.Examine/UmbracoContentIndex.cs +++ b/src/Umbraco.Examine/UmbracoContentIndex.cs @@ -92,8 +92,8 @@ namespace Umbraco.Examine //these are the invalid items so we'll delete them //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. - foreach (var i in group) - base.PerformDeleteFromIndex(i.Id, args => { /*noop*/ }); + + base.PerformDeleteFromIndex(group.Select(x => x.Id), args => { /*noop*/ }); } else { @@ -118,24 +118,28 @@ namespace Umbraco.Examine /// When a content node is deleted, we also need to delete it's children from the index so we need to perform a /// custom Lucene search to find all decendents and create Delete item queues for them too. /// - /// ID of the node to delete + /// ID of the node to delete /// - protected override void PerformDeleteFromIndex(string nodeId, Action onComplete) + protected override void PerformDeleteFromIndex(IEnumerable itemIds, Action onComplete) { - //find all descendants based on path - var descendantPath = $@"\-1\,*{nodeId}\,*"; - var rawQuery = $"{IndexPathFieldName}:{descendantPath}"; - var searcher = GetSearcher(); - var c = searcher.CreateQuery(); - var filtered = c.NativeQuery(rawQuery); - var results = filtered.Execute(); + var idsAsList = itemIds.ToList(); + foreach (var nodeId in idsAsList) + { + //find all descendants based on path + var descendantPath = $@"\-1\,*{nodeId}\,*"; + var rawQuery = $"{IndexPathFieldName}:{descendantPath}"; + var searcher = GetSearcher(); + 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); + ProfilingLogger.Debug(GetType(), "DeleteFromIndex with query: {Query} (found {TotalItems} results)", rawQuery, results.TotalItemCount); - //need to queue a delete item for each one found - QueueIndexOperation(results.Select(r => new IndexOperation(new ValueSet(r.Id), IndexOperationType.Delete))); + //need to queue a delete item for each one found + QueueIndexOperation(results.Select(r => new IndexOperation(new ValueSet(r.Id), IndexOperationType.Delete))); + } - base.PerformDeleteFromIndex(nodeId, onComplete); + base.PerformDeleteFromIndex(idsAsList, onComplete); } } diff --git a/src/Umbraco.Examine/UmbracoExamineIndex.cs b/src/Umbraco.Examine/UmbracoExamineIndex.cs index 6804d199f8..24952050da 100644 --- a/src/Umbraco.Examine/UmbracoExamineIndex.cs +++ b/src/Umbraco.Examine/UmbracoExamineIndex.cs @@ -94,13 +94,13 @@ namespace Umbraco.Examine /// /// This check is required since the base examine lib will try to rebuild on startup /// - protected override void PerformDeleteFromIndex(string nodeId, Action onComplete) + protected override void PerformDeleteFromIndex(IEnumerable itemIds, Action onComplete) { if (CanInitialize()) { using (new SafeCallContext()) { - base.PerformDeleteFromIndex(nodeId, onComplete); + base.PerformDeleteFromIndex(itemIds, onComplete); } } } diff --git a/src/Umbraco.Tests/Umbraco.Tests.csproj b/src/Umbraco.Tests/Umbraco.Tests.csproj index af42e2503f..bed1281bf8 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.Web.UI/Umbraco.Web.UI.csproj b/src/Umbraco.Web.UI/Umbraco.Web.UI.csproj index 61e31d2d3e..2fc199d06a 100644 --- a/src/Umbraco.Web.UI/Umbraco.Web.UI.csproj +++ b/src/Umbraco.Web.UI/Umbraco.Web.UI.csproj @@ -88,7 +88,7 @@ - + diff --git a/src/Umbraco.Web/Umbraco.Web.csproj b/src/Umbraco.Web/Umbraco.Web.csproj index 3ac5ab9f11..7a695ff4ef 100755 --- a/src/Umbraco.Web/Umbraco.Web.csproj +++ b/src/Umbraco.Web/Umbraco.Web.csproj @@ -63,7 +63,7 @@ - + 2.6.2.25 From 4ca95a11ee03dca6a04cc6475c393db82b341783 Mon Sep 17 00:00:00 2001 From: Shannon Date: Mon, 7 Jan 2019 18:49:55 +1100 Subject: [PATCH 05/14] Fixes index populator registration and fixes the populators/rebuilders to not execute any lookups if there are no indexes --- src/Umbraco.Examine/ContentIndexPopulator.cs | 4 +++- src/Umbraco.Examine/IndexPopulator.cs | 4 ++-- src/Umbraco.Examine/IndexRebuilder.cs | 2 ++ src/Umbraco.Examine/MediaIndexPopulator.cs | 4 +++- src/Umbraco.Examine/MemberIndexPopulator.cs | 4 +++- src/Umbraco.Web/Search/ExamineComposer.cs | 10 +++++----- 6 files changed, 18 insertions(+), 10 deletions(-) diff --git a/src/Umbraco.Examine/ContentIndexPopulator.cs b/src/Umbraco.Examine/ContentIndexPopulator.cs index 72615b4b26..51b9de4a0b 100644 --- a/src/Umbraco.Examine/ContentIndexPopulator.cs +++ b/src/Umbraco.Examine/ContentIndexPopulator.cs @@ -58,8 +58,10 @@ namespace Umbraco.Examine _parentId = parentId; } - protected override void PopulateIndexes(IEnumerable indexes) + protected override void PopulateIndexes(IReadOnlyList indexes) { + if (indexes.Count == 0) return; + const int pageSize = 10000; var pageIndex = 0; diff --git a/src/Umbraco.Examine/IndexPopulator.cs b/src/Umbraco.Examine/IndexPopulator.cs index 9cd985df16..f9d4d85dc8 100644 --- a/src/Umbraco.Examine/IndexPopulator.cs +++ b/src/Umbraco.Examine/IndexPopulator.cs @@ -38,9 +38,9 @@ namespace Umbraco.Examine public void Populate(params IIndex[] indexes) { - PopulateIndexes(indexes.Where(IsRegistered)); + PopulateIndexes(indexes.Where(IsRegistered).ToList()); } - protected abstract void PopulateIndexes(IEnumerable indexes); + protected abstract void PopulateIndexes(IReadOnlyList indexes); } } diff --git a/src/Umbraco.Examine/IndexRebuilder.cs b/src/Umbraco.Examine/IndexRebuilder.cs index d946a8f783..43c309b9c5 100644 --- a/src/Umbraco.Examine/IndexRebuilder.cs +++ b/src/Umbraco.Examine/IndexRebuilder.cs @@ -42,6 +42,8 @@ namespace Umbraco.Examine ? ExamineManager.Indexes.Where(x => !x.IndexExists()) : ExamineManager.Indexes).ToArray(); + if (indexes.Length == 0) return; + foreach (var index in indexes) { index.CreateIndex(); // clear the index diff --git a/src/Umbraco.Examine/MediaIndexPopulator.cs b/src/Umbraco.Examine/MediaIndexPopulator.cs index 2232d359e7..6dadcbe4b3 100644 --- a/src/Umbraco.Examine/MediaIndexPopulator.cs +++ b/src/Umbraco.Examine/MediaIndexPopulator.cs @@ -39,8 +39,10 @@ namespace Umbraco.Examine _mediaValueSetBuilder = mediaValueSetBuilder; } - protected override void PopulateIndexes(IEnumerable indexes) + protected override void PopulateIndexes(IReadOnlyList indexes) { + if (indexes.Count == 0) return; + const int pageSize = 10000; var pageIndex = 0; diff --git a/src/Umbraco.Examine/MemberIndexPopulator.cs b/src/Umbraco.Examine/MemberIndexPopulator.cs index 6e97ee9195..e20dab91ca 100644 --- a/src/Umbraco.Examine/MemberIndexPopulator.cs +++ b/src/Umbraco.Examine/MemberIndexPopulator.cs @@ -17,8 +17,10 @@ namespace Umbraco.Examine _memberService = memberService; _valueSetBuilder = valueSetBuilder; } - protected override void PopulateIndexes(IEnumerable indexes) + protected override void PopulateIndexes(IReadOnlyList indexes) { + if (indexes.Count == 0) return; + const int pageSize = 1000; var pageIndex = 0; diff --git a/src/Umbraco.Web/Search/ExamineComposer.cs b/src/Umbraco.Web/Search/ExamineComposer.cs index ced169e6dc..8ee2caedee 100644 --- a/src/Umbraco.Web/Search/ExamineComposer.cs +++ b/src/Umbraco.Web/Search/ExamineComposer.cs @@ -21,12 +21,12 @@ namespace Umbraco.Web.Search { base.Compose(composition); - // populators are not a collection: once cannot remove ours, and can only add more + // populators are not a collection: one cannot remove ours, and can only add more // the container can inject IEnumerable and get them all - composition.Register(Lifetime.Singleton); - composition.Register(Lifetime.Singleton); - composition.Register(Lifetime.Singleton); - composition.Register(Lifetime.Singleton); + composition.Register(Lifetime.Singleton); + composition.Register(Lifetime.Singleton); + composition.Register(Lifetime.Singleton); + composition.Register(Lifetime.Singleton); composition.Register(Lifetime.Singleton); composition.RegisterUnique(); From 33ee239406e182f3303a34baf3392cbca9a0ac02 Mon Sep 17 00:00:00 2001 From: Bjarke Berg Date: Tue, 8 Jan 2019 15:23:05 +0100 Subject: [PATCH 06/14] #3642 - Worked on creating blueprints --- .../Services/Implement/ContentService.cs | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/src/Umbraco.Core/Services/Implement/ContentService.cs b/src/Umbraco.Core/Services/Implement/ContentService.cs index 3464823856..d44ce2a0dc 100644 --- a/src/Umbraco.Core/Services/Implement/ContentService.cs +++ b/src/Umbraco.Core/Services/Implement/ContentService.cs @@ -2744,8 +2744,20 @@ namespace Umbraco.Core.Services.Implement content.CreatorId = userId; content.WriterId = userId; - foreach (var property in blueprint.Properties) - content.SetValue(property.Alias, property.GetValue()); //fixme doesn't take into account variants + var now = DateTime.Now; + var cultures = blueprint.CultureInfos.Any() ? blueprint.CultureInfos.Select(x=>x.Key) : new[] {(string)null}; + foreach (var culture in cultures) + { + foreach (var property in blueprint.Properties) + { + content.SetValue(property.Alias, property.GetValue(culture), culture); + } + + content.Name = blueprint.Name; + content.SetCultureInfo(culture, blueprint.GetCultureName(culture), now); + } + + return content; } From 9bbe743686c14cba801e8e4a4a1f26d10ad49566 Mon Sep 17 00:00:00 2001 From: Bjarke Berg Date: Tue, 8 Jan 2019 22:30:12 +0100 Subject: [PATCH 07/14] syntax --- src/Umbraco.Web/Editors/ContentController.cs | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/Umbraco.Web/Editors/ContentController.cs b/src/Umbraco.Web/Editors/ContentController.cs index 9f0e350e55..c444fd8d39 100644 --- a/src/Umbraco.Web/Editors/ContentController.cs +++ b/src/Umbraco.Web/Editors/ContentController.cs @@ -515,11 +515,16 @@ namespace Umbraco.Web.Editors [HttpPost] public SimpleNotificationModel CreateBlueprintFromContent([FromUri]int contentId, [FromUri]string name) { - if (string.IsNullOrWhiteSpace(name)) throw new ArgumentException("Value cannot be null or whitespace.", "name"); + if (string.IsNullOrWhiteSpace(name)) + { + throw new ArgumentException("Value cannot be null or whitespace.", "name"); + } var content = Services.ContentService.GetById(contentId); if (content == null) + { throw new HttpResponseException(Request.CreateResponse(HttpStatusCode.NotFound)); + } EnsureUniqueName(name, content, "name"); From 28d93175d553f0ceb3f84a3aef9c2a5f85925f15 Mon Sep 17 00:00:00 2001 From: Bjarke Berg Date: Thu, 10 Jan 2019 06:56:56 +0100 Subject: [PATCH 08/14] #3642 - When saving content the first time, we need to save all variants (even when save is not true), otherwise we loose the information when the url are updated. --- src/Umbraco.Web/Editors/ContentController.cs | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/src/Umbraco.Web/Editors/ContentController.cs b/src/Umbraco.Web/Editors/ContentController.cs index c444fd8d39..7189c378d5 100644 --- a/src/Umbraco.Web/Editors/ContentController.cs +++ b/src/Umbraco.Web/Editors/ContentController.cs @@ -1741,12 +1741,18 @@ namespace Umbraco.Web.Editors bool Varies(Property property) => property.PropertyType.VariesByCulture(); var variantIndex = 0; - + var newContent = (contentSave.Action == ContentSaveAction.SaveNew + || contentSave.Action == ContentSaveAction.PublishNew + || contentSave.Action == ContentSaveAction.ScheduleNew + || contentSave.Action == ContentSaveAction.SendPublishNew + || contentSave.Action == ContentSaveAction.PublishWithDescendantsNew + || contentSave.Action == ContentSaveAction.PublishWithDescendantsForceNew + ); //loop through each variant, set the correct name and property values foreach (var variant in contentSave.Variants) { //Don't update anything for this variant if Save is not true - if (!variant.Save) continue; + if (!variant.Save && !newContent) continue; //Don't update the name if it is empty if (!variant.Name.IsNullOrWhiteSpace()) From 8594af3fe3a77747bfc36d962ab858b341da6a82 Mon Sep 17 00:00:00 2001 From: Bjarke Berg Date: Thu, 10 Jan 2019 06:58:12 +0100 Subject: [PATCH 09/14] #3642 - Also do dirty checks if we have changed the culture. --- .../src/common/directives/validation/valformmanager.directive.js | 1 - 1 file changed, 1 deletion(-) diff --git a/src/Umbraco.Web.UI.Client/src/common/directives/validation/valformmanager.directive.js b/src/Umbraco.Web.UI.Client/src/common/directives/validation/valformmanager.directive.js index eaf67bcb91..29920ebf00 100644 --- a/src/Umbraco.Web.UI.Client/src/common/directives/validation/valformmanager.directive.js +++ b/src/Umbraco.Web.UI.Client/src/common/directives/validation/valformmanager.directive.js @@ -146,7 +146,6 @@ function valFormManager(serverValidationManager, $rootScope, $timeout, $location var infiniteEditors = editorService.getEditors(); if (!formCtrl.$dirty && infiniteEditors.length === 0 || isSavingNewItem && infiniteEditors.length === 0) { - confirmed = true; return; } From 74213783309cbbd9eca05b4898d6bedf1a2c2a40 Mon Sep 17 00:00:00 2001 From: Bjarke Berg Date: Thu, 10 Jan 2019 07:03:08 +0100 Subject: [PATCH 10/14] #3642 - use nameof instead of magic strings that has to be equal to variable name --- src/Umbraco.Web/Editors/ContentController.cs | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/src/Umbraco.Web/Editors/ContentController.cs b/src/Umbraco.Web/Editors/ContentController.cs index 7189c378d5..26698b227f 100644 --- a/src/Umbraco.Web/Editors/ContentController.cs +++ b/src/Umbraco.Web/Editors/ContentController.cs @@ -516,17 +516,13 @@ namespace Umbraco.Web.Editors public SimpleNotificationModel CreateBlueprintFromContent([FromUri]int contentId, [FromUri]string name) { if (string.IsNullOrWhiteSpace(name)) - { - throw new ArgumentException("Value cannot be null or whitespace.", "name"); - } + throw new ArgumentException("Value cannot be null or whitespace.", nameof(name)); var content = Services.ContentService.GetById(contentId); if (content == null) - { throw new HttpResponseException(Request.CreateResponse(HttpStatusCode.NotFound)); - } - EnsureUniqueName(name, content, "name"); + EnsureUniqueName(name, content, nameof(name)); var blueprint = Services.ContentService.CreateContentFromBlueprint(content, name, Security.GetUserId().ResultOr(0)); From b0b0477dab7f30c2b482af792038818808f86342 Mon Sep 17 00:00:00 2001 From: Bjarke Berg Date: Thu, 10 Jan 2019 07:34:28 +0100 Subject: [PATCH 11/14] #3642 -bugfix for nonvariant --- src/Umbraco.Core/Services/Implement/ContentService.cs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/Umbraco.Core/Services/Implement/ContentService.cs b/src/Umbraco.Core/Services/Implement/ContentService.cs index d44ce2a0dc..1e89e190c8 100644 --- a/src/Umbraco.Core/Services/Implement/ContentService.cs +++ b/src/Umbraco.Core/Services/Implement/ContentService.cs @@ -2754,7 +2754,10 @@ namespace Umbraco.Core.Services.Implement } content.Name = blueprint.Name; - content.SetCultureInfo(culture, blueprint.GetCultureName(culture), now); + if (!string.IsNullOrEmpty(culture)) + { + content.SetCultureInfo(culture, blueprint.GetCultureName(culture), now); + } } From d672531b0bedf50b072515878b0f479bde3bb567 Mon Sep 17 00:00:00 2001 From: Bjarke Berg Date: Thu, 10 Jan 2019 07:58:45 +0100 Subject: [PATCH 12/14] #3642 - reuse method for determine if the content is new --- src/Umbraco.Web/Editors/ContentController.cs | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/src/Umbraco.Web/Editors/ContentController.cs b/src/Umbraco.Web/Editors/ContentController.cs index 26698b227f..94c040f4d6 100644 --- a/src/Umbraco.Web/Editors/ContentController.cs +++ b/src/Umbraco.Web/Editors/ContentController.cs @@ -1737,18 +1737,12 @@ namespace Umbraco.Web.Editors bool Varies(Property property) => property.PropertyType.VariesByCulture(); var variantIndex = 0; - var newContent = (contentSave.Action == ContentSaveAction.SaveNew - || contentSave.Action == ContentSaveAction.PublishNew - || contentSave.Action == ContentSaveAction.ScheduleNew - || contentSave.Action == ContentSaveAction.SendPublishNew - || contentSave.Action == ContentSaveAction.PublishWithDescendantsNew - || contentSave.Action == ContentSaveAction.PublishWithDescendantsForceNew - ); + //loop through each variant, set the correct name and property values foreach (var variant in contentSave.Variants) { //Don't update anything for this variant if Save is not true - if (!variant.Save && !newContent) continue; + if (!variant.Save && !IsCreatingAction(contentSave.Action)) continue; //Don't update the name if it is empty if (!variant.Name.IsNullOrWhiteSpace()) From 228fca04ecf979b03ec725e64044800fe947b877 Mon Sep 17 00:00:00 2001 From: Bjarke Berg Date: Thu, 10 Jan 2019 10:06:42 +0100 Subject: [PATCH 13/14] #3642 - moved functionality to frontend about saving all variants the first time. --- .../views/content/overlays/save.controller.js | 40 ++++- .../src/views/content/overlays/save.html | 152 ++++++++++++------ .../Umbraco/config/lang/en_us.xml | 1 + src/Umbraco.Web/Editors/ContentController.cs | 4 +- 4 files changed, 139 insertions(+), 58 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/views/content/overlays/save.controller.js b/src/Umbraco.Web.UI.Client/src/views/content/overlays/save.controller.js index a99da13811..8d21234aee 100644 --- a/src/Umbraco.Web.UI.Client/src/views/content/overlays/save.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/content/overlays/save.controller.js @@ -1,16 +1,17 @@ (function () { "use strict"; - + function SaveContentController($scope, localizationService) { var vm = this; vm.loading = true; vm.hasPristineVariants = false; + vm.isNew = true; vm.changeSelection = changeSelection; vm.dirtyVariantFilter = dirtyVariantFilter; vm.pristineVariantFilter = pristineVariantFilter; - + function changeSelection(variant) { var firstSelected = _.find(vm.variants, function (v) { return v.save; @@ -30,8 +31,28 @@ return !(dirtyVariantFilter(variant)); } - function onInit() { + function hasAnyData(variant) { + var result = variant.isDirty != null || (variant.name != null && variant.name.length > 0); + if(result) return true; + + for (var t=0; t < variant.tabs.length; t++){ + for (var p=0; p < variant.tabs[t].properties.length; p++){ + + var property = variant.tabs[t].properties[p]; + + if(property.culture == null) continue; + + result = result || (property.value != null && property.value.length > 0); + + if(result) return true; + } + } + + return result; + } + + function onInit() { vm.variants = $scope.model.variants; if(!$scope.model.title) { @@ -42,6 +63,13 @@ vm.hasPristineVariants = false; + _.each(vm.variants, + function (variant) { + if(variant.state !== "NotCreated"){ + vm.isNew = false; + } + }); + _.each(vm.variants, function (variant) { variant.compositeId = variant.language.culture + "_" + (variant.segment ? variant.segment : ""); @@ -51,6 +79,10 @@ if (!vm.hasPristineVariants) { vm.hasPristineVariants = pristineVariantFilter(variant); } + + if(vm.isNew && hasAnyData(variant)){ + variant.save = true; + } }); if (vm.variants.length !== 0) { @@ -88,5 +120,5 @@ } angular.module("umbraco").controller("Umbraco.Overlays.SaveContentController", SaveContentController); - + })(); diff --git a/src/Umbraco.Web.UI.Client/src/views/content/overlays/save.html b/src/Umbraco.Web.UI.Client/src/views/content/overlays/save.html index 6f4aef4e84..c4dcd5b767 100644 --- a/src/Umbraco.Web.UI.Client/src/views/content/overlays/save.html +++ b/src/Umbraco.Web.UI.Client/src/views/content/overlays/save.html @@ -1,72 +1,120 @@
-
-

-
+
-
-
- -
- -
- - -
- -
- -
-
{{saveVariantSelectorForm.saveVariantSelector.errorMsg}}
-
- -
-
{{notification.message}}
-
- -
-
- -
+
+
+

+
+ +
+ +
+ +
+ +
+ + +
+ +
+ +
+
{{saveVariantSelectorForm.saveVariantSelector.errorMsg}}
+
+ +
+
{{notification.message}}
+
+ +
+
+ +
+
+
-
-
-
-

+
+
+

-
-
-
- {{ variant.language.name }} - * -
+
-
- -
+
+ +
+ +
+ -
-
{{notification.message}}
+
+ +
+ +
+
{{saveVariantSelectorForm.saveVariantSelector.errorMsg}}
+
+ +
+
{{notification.message}}
+
+ +
+
+ + +
+
+
+ +
+
+

+
+ +
+
+
+ {{ variant.language.name }} + * +
+ +
+ +
+ +
+
{{notification.message}}
+
-
diff --git a/src/Umbraco.Web.UI/Umbraco/config/lang/en_us.xml b/src/Umbraco.Web.UI/Umbraco/config/lang/en_us.xml index a96abadbbe..07ec0c9909 100644 --- a/src/Umbraco.Web.UI/Umbraco/config/lang/en_us.xml +++ b/src/Umbraco.Web.UI/Umbraco/config/lang/en_us.xml @@ -272,6 +272,7 @@ This value is hidden. What languages would you like to publish? What languages would you like to save? + All languages with content are saved on creation! What languages would you like to send for approval? What languages would you like to schedule? Select the languages to unpublish. Unpublishing a mandatory language will unpublish all languages. diff --git a/src/Umbraco.Web/Editors/ContentController.cs b/src/Umbraco.Web/Editors/ContentController.cs index 94c040f4d6..80ba00d07a 100644 --- a/src/Umbraco.Web/Editors/ContentController.cs +++ b/src/Umbraco.Web/Editors/ContentController.cs @@ -613,7 +613,7 @@ namespace Umbraco.Web.Editors var msKey = $"Variants[{variantCount}].Name"; if (ModelState.ContainsKey(msKey)) { - if (!variant.Save) + if (!variant.Save || IsCreatingAction(contentItem.Action)) ModelState.Remove(msKey); else variantNameErrors.Add(variant.Culture); @@ -1742,7 +1742,7 @@ namespace Umbraco.Web.Editors foreach (var variant in contentSave.Variants) { //Don't update anything for this variant if Save is not true - if (!variant.Save && !IsCreatingAction(contentSave.Action)) continue; + if (!variant.Save) continue; //Don't update the name if it is empty if (!variant.Name.IsNullOrWhiteSpace()) From 10d0c79c1ddc78ccab9bef919488f71bcf93fd9d Mon Sep 17 00:00:00 2001 From: Bjarke Berg Date: Thu, 10 Jan 2019 14:28:22 +0100 Subject: [PATCH 14/14] #3642 - also save all languages with content on publish --- .../content/overlays/publish.controller.js | 51 +++++++++++++++++-- .../src/views/content/overlays/publish.html | 4 +- .../Umbraco/config/lang/en_us.xml | 1 + 3 files changed, 50 insertions(+), 6 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/views/content/overlays/publish.controller.js b/src/Umbraco.Web.UI.Client/src/views/content/overlays/publish.controller.js index 9fcd81b2ed..9074834ee6 100644 --- a/src/Umbraco.Web.UI.Client/src/views/content/overlays/publish.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/content/overlays/publish.controller.js @@ -6,11 +6,12 @@ var vm = this; vm.loading = true; vm.hasPristineVariants = false; + vm.isNew = true; vm.changeSelection = changeSelection; vm.dirtyVariantFilter = dirtyVariantFilter; vm.pristineVariantFilter = pristineVariantFilter; - + /** Returns true if publishing is possible based on if there are un-published mandatory languages */ function canPublish() { var selected = []; @@ -22,7 +23,7 @@ var published = !(variant.state === "NotCreated" || variant.state === "Draft"); if ((variant.language.isMandatory && !published) && (!publishable || !variant.publish)) { - //if a mandatory variant isn't published + //if a mandatory variant isn't published //and it's not publishable or not selected to be published //then we cannot continue @@ -53,12 +54,35 @@ return (variant.active || variant.isDirty || variant.state === "Draft" || variant.state === "PublishedPendingChanges" || variant.state === "NotCreated"); } + function hasAnyData(variant) { + var result = variant.isDirty != null || (variant.name != null && variant.name.length > 0); + + if(result) return true; + + for (var t=0; t < variant.tabs.length; t++){ + for (var p=0; p < variant.tabs[t].properties.length; p++){ + + var property = variant.tabs[t].properties[p]; + + if(property.culture == null) continue; + + result = result || (property.value != null && property.value.length > 0); + + if(result) return true; + } + } + + return result; + } + function pristineVariantFilter(variant) { return !(dirtyVariantFilter(variant)); } function onInit() { + + vm.variants = $scope.model.variants; if (!$scope.model.title) { @@ -69,6 +93,13 @@ vm.hasPristineVariants = false; + _.each(vm.variants, + function (variant) { + if(variant.state !== "NotCreated"){ + vm.isNew = false; + } + }); + _.each(vm.variants, function (variant) { variant.compositeId = variant.language.culture + "_" + (variant.segment ? variant.segment : ""); @@ -78,6 +109,10 @@ if (!vm.hasPristineVariants) { vm.hasPristineVariants = pristineVariantFilter(variant); } + + if(vm.isNew && hasAnyData(variant)){ + variant.save = true; + } }); if (vm.variants.length !== 0) { @@ -103,8 +138,16 @@ $scope.model.disableSubmitButton = true; } - vm.loading = false; - + var labelKey = vm.isNew ? "content_languagesToPublishForFirstTime" : "content_languagesToPublish"; + + localizationService.localize(labelKey).then(function (value) { + vm.headline = value; + + vm.loading = false; + }); + + + } onInit(); diff --git a/src/Umbraco.Web.UI.Client/src/views/content/overlays/publish.html b/src/Umbraco.Web.UI.Client/src/views/content/overlays/publish.html index 8ca8b78b23..b33b7ccbfc 100644 --- a/src/Umbraco.Web.UI.Client/src/views/content/overlays/publish.html +++ b/src/Umbraco.Web.UI.Client/src/views/content/overlays/publish.html @@ -1,7 +1,7 @@
-

+

{{vm.headline}}

@@ -65,7 +65,7 @@
{{notification.message}}
- +
diff --git a/src/Umbraco.Web.UI/Umbraco/config/lang/en_us.xml b/src/Umbraco.Web.UI/Umbraco/config/lang/en_us.xml index 07ec0c9909..eaa1c6c39e 100644 --- a/src/Umbraco.Web.UI/Umbraco/config/lang/en_us.xml +++ b/src/Umbraco.Web.UI/Umbraco/config/lang/en_us.xml @@ -270,6 +270,7 @@ Include drafts: also publish unpublished content items. This value is hidden. If you need access to view this value please contact your website administrator. This value is hidden. + What languages would you like to publish? All languages with content are saved! What languages would you like to publish? What languages would you like to save? All languages with content are saved on creation!