Merge branch 'temp8' into temp8-fs
This commit is contained in:
@@ -25,7 +25,7 @@
|
||||
<dependency id="ClientDependency" version="[1.9.7,1.999999)" />
|
||||
<dependency id="ClientDependency-Mvc5" version="[1.8.0,1.999999)" />
|
||||
<dependency id="CSharpTest.Net.Collections" version="[14.906.1403.1082,14.999999)" />
|
||||
<dependency id="Examine" version="[1.0.0-beta067,1.999999)" />
|
||||
<dependency id="Examine" version="[1.0.0-beta072,1.999999)" />
|
||||
<dependency id="HtmlAgilityPack" version="[1.8.9,1.999999)" />
|
||||
<dependency id="ImageProcessor" version="[2.6.2.25,2.999999)" />
|
||||
<dependency id="LightInject.Mvc" version="[2.0.0,2.999999)" />
|
||||
|
||||
@@ -2744,8 +2744,23 @@ 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;
|
||||
if (!string.IsNullOrEmpty(culture))
|
||||
{
|
||||
content.SetCultureInfo(culture, blueprint.GetCultureName(culture), now);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
return content;
|
||||
}
|
||||
|
||||
@@ -1,36 +0,0 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Examine;
|
||||
|
||||
namespace Umbraco.Examine.Config
|
||||
{
|
||||
/// <summary>
|
||||
/// a data structure for storing indexing/searching instructions based on config based indexers
|
||||
/// </summary>
|
||||
public class ConfigIndexCriteria
|
||||
{
|
||||
///<summary>
|
||||
/// Constructor
|
||||
///</summary>
|
||||
///<param name="standardFields"></param>
|
||||
///<param name="userFields"></param>
|
||||
///<param name="includeNodeTypes"></param>
|
||||
///<param name="excludeNodeTypes"></param>
|
||||
///<param name="parentNodeId"></param>
|
||||
public ConfigIndexCriteria(IEnumerable<FieldDefinition> standardFields, IEnumerable<FieldDefinition> userFields, IEnumerable<string> includeNodeTypes, IEnumerable<string> excludeNodeTypes, int? parentNodeId)
|
||||
{
|
||||
UserFields = userFields.ToList();
|
||||
StandardFields = standardFields.ToList();
|
||||
IncludeItemTypes = includeNodeTypes;
|
||||
ExcludeItemTypes = excludeNodeTypes;
|
||||
ParentNodeId = parentNodeId;
|
||||
}
|
||||
|
||||
public IEnumerable<FieldDefinition> StandardFields { get; internal set; }
|
||||
public IEnumerable<FieldDefinition> UserFields { get; internal set; }
|
||||
|
||||
public IEnumerable<string> IncludeItemTypes { get; internal set; }
|
||||
public IEnumerable<string> ExcludeItemTypes { get; internal set; }
|
||||
public int? ParentNodeId { get; internal set; }
|
||||
}
|
||||
}
|
||||
@@ -1,61 +0,0 @@
|
||||
using System.Configuration;
|
||||
|
||||
namespace Umbraco.Examine.Config
|
||||
{
|
||||
///<summary>
|
||||
/// A configuration item representing a field to index
|
||||
///</summary>
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
|
||||
/// <summary>
|
||||
/// Adds an index field to the collection
|
||||
/// </summary>
|
||||
/// <param name="field"></param>
|
||||
public void Add(ConfigIndexField field)
|
||||
{
|
||||
BaseAdd(field, true);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Default property for accessing an IndexField definition
|
||||
/// </summary>
|
||||
/// <value>Field Name</value>
|
||||
/// <returns></returns>
|
||||
public new ConfigIndexField this[string name]
|
||||
{
|
||||
get
|
||||
{
|
||||
return (ConfigIndexField)this.BaseGet(name);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -1,15 +0,0 @@
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Umbraco.Examine.Config
|
||||
{
|
||||
public static class IndexFieldCollectionExtensions
|
||||
{
|
||||
public static List<ConfigIndexField> ToList(this IndexFieldCollection indexes)
|
||||
{
|
||||
List<ConfigIndexField> fields = new List<ConfigIndexField>();
|
||||
foreach (ConfigIndexField field in indexes)
|
||||
fields.Add(field);
|
||||
return fields;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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"];
|
||||
|
||||
/// <summary>
|
||||
/// When this property is set, the indexing will only index documents that are descendants of this node.
|
||||
/// </summary>
|
||||
[ConfigurationProperty("IndexParentId", IsRequired = false, IsKey = false)]
|
||||
public int? IndexParentId
|
||||
{
|
||||
get
|
||||
{
|
||||
if (this["IndexParentId"] == null)
|
||||
return null;
|
||||
|
||||
return (int)this["IndexParentId"];
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 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).
|
||||
/// </summary>
|
||||
[ConfigurationCollection(typeof(IndexFieldCollection))]
|
||||
[ConfigurationProperty("IncludeNodeTypes", IsDefaultCollection = false, IsRequired = false)]
|
||||
public IndexFieldCollection IncludeNodeTypes => (IndexFieldCollection)base["IncludeNodeTypes"];
|
||||
|
||||
/// <summary>
|
||||
/// The collection of node types to not index. If specified, these node types will not be indexed.
|
||||
/// </summary>
|
||||
[ConfigurationCollection(typeof(IndexFieldCollection))]
|
||||
[ConfigurationProperty("ExcludeNodeTypes", IsDefaultCollection = false, IsRequired = false)]
|
||||
public IndexFieldCollection ExcludeNodeTypes => (IndexFieldCollection)base["ExcludeNodeTypes"];
|
||||
|
||||
/// <summary>
|
||||
/// A collection of user defined umbraco fields to index
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// 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
|
||||
/// </remarks>
|
||||
[ConfigurationCollection(typeof(IndexFieldCollection))]
|
||||
[ConfigurationProperty("IndexUserFields", IsDefaultCollection = false, IsRequired = false)]
|
||||
public IndexFieldCollection IndexUserFields => (IndexFieldCollection)base["IndexUserFields"];
|
||||
|
||||
/// <summary>
|
||||
/// The fields umbraco values that will be indexed. i.e. id, nodeTypeAlias, writer, etc...
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// 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
|
||||
/// </remarks>
|
||||
[ConfigurationCollection(typeof(IndexFieldCollection))]
|
||||
[ConfigurationProperty("IndexAttributeFields", IsDefaultCollection = false, IsRequired = false)]
|
||||
public IndexFieldCollection IndexAttributeFields => (IndexFieldCollection)base["IndexAttributeFields"];
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
|
||||
/// <summary>
|
||||
/// Default property for accessing Image Sets
|
||||
/// </summary>
|
||||
/// <param name="setName"></param>
|
||||
/// <returns></returns>
|
||||
public new IndexSet this[string setName] => (IndexSet)this.BaseGet(setName);
|
||||
}
|
||||
}
|
||||
@@ -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[""];
|
||||
}
|
||||
}
|
||||
@@ -58,8 +58,10 @@ namespace Umbraco.Examine
|
||||
_parentId = parentId;
|
||||
}
|
||||
|
||||
protected override void PopulateIndexes(IEnumerable<IIndex> indexes)
|
||||
protected override void PopulateIndexes(IReadOnlyList<IIndex> indexes)
|
||||
{
|
||||
if (indexes.Count == 0) return;
|
||||
|
||||
const int pageSize = 10000;
|
||||
var pageIndex = 0;
|
||||
|
||||
|
||||
@@ -1,22 +1,20 @@
|
||||
using System.Collections.Generic;
|
||||
using Examine;
|
||||
using Examine;
|
||||
|
||||
namespace Umbraco.Examine
|
||||
{
|
||||
public interface IIndexPopulator
|
||||
{
|
||||
/// <summary>
|
||||
/// If this index is registered with this populatr
|
||||
/// If this index is registered with this populator
|
||||
/// </summary>
|
||||
/// <param name="index"></param>
|
||||
/// <returns></returns>
|
||||
bool IsRegistered(IIndex index);
|
||||
|
||||
/// <summary>
|
||||
/// Populate indexers
|
||||
/// Populate indexers
|
||||
/// </summary>
|
||||
/// <param name="indexes"></param>
|
||||
void Populate(params IIndex[] indexes);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -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<IIndex> indexes);
|
||||
protected abstract void PopulateIndexes(IReadOnlyList<IIndex> indexes);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -39,8 +39,10 @@ namespace Umbraco.Examine
|
||||
_mediaValueSetBuilder = mediaValueSetBuilder;
|
||||
}
|
||||
|
||||
protected override void PopulateIndexes(IEnumerable<IIndex> indexes)
|
||||
protected override void PopulateIndexes(IReadOnlyList<IIndex> indexes)
|
||||
{
|
||||
if (indexes.Count == 0) return;
|
||||
|
||||
const int pageSize = 10000;
|
||||
var pageIndex = 0;
|
||||
|
||||
|
||||
@@ -17,8 +17,10 @@ namespace Umbraco.Examine
|
||||
_memberService = memberService;
|
||||
_valueSetBuilder = valueSetBuilder;
|
||||
}
|
||||
protected override void PopulateIndexes(IEnumerable<IIndex> indexes)
|
||||
protected override void PopulateIndexes(IReadOnlyList<IIndex> indexes)
|
||||
{
|
||||
if (indexes.Count == 0) return;
|
||||
|
||||
const int pageSize = 1000;
|
||||
var pageIndex = 0;
|
||||
|
||||
|
||||
@@ -48,19 +48,12 @@
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<!-- note: NuGet deals with transitive references now -->
|
||||
<PackageReference Include="Examine" Version="1.0.0-beta067" />
|
||||
<PackageReference Include="Examine" Version="1.0.0-beta072" />
|
||||
<PackageReference Include="Newtonsoft.Json" Version="11.0.2" />
|
||||
<PackageReference Include="NPoco" Version="3.9.4" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="BaseValueSetBuilder.cs" />
|
||||
<Compile Include="Config\ConfigIndexCriteria.cs" />
|
||||
<Compile Include="Config\ConfigIndexField.cs" />
|
||||
<Compile Include="Config\IndexFieldCollection.cs" />
|
||||
<Compile Include="Config\IndexFieldCollectionExtensions.cs" />
|
||||
<Compile Include="Config\IndexSet.cs" />
|
||||
<Compile Include="Config\IndexSetCollection.cs" />
|
||||
<Compile Include="Config\IndexSets.cs" />
|
||||
<Compile Include="ContentIndexPopulator.cs" />
|
||||
<Compile Include="ContentValueSetBuilder.cs" />
|
||||
<Compile Include="ExamineExtensions.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
|
||||
|
||||
/// <summary>
|
||||
/// Constructor for configuration providers
|
||||
/// </summary>
|
||||
[EditorBrowsable(EditorBrowsableState.Never)]
|
||||
public UmbracoContentIndex()
|
||||
{
|
||||
LanguageService = Current.Services.LocalizationService;
|
||||
|
||||
//note: The validator for this config based indexer is set in the Initialize method
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Create an index at runtime
|
||||
/// </summary>
|
||||
@@ -52,14 +37,14 @@ namespace Umbraco.Examine
|
||||
/// <param name="indexValueTypes"></param>
|
||||
public UmbracoContentIndex(
|
||||
string name,
|
||||
FieldDefinitionCollection fieldDefinitions,
|
||||
Directory luceneDirectory,
|
||||
FieldDefinitionCollection fieldDefinitions,
|
||||
Analyzer defaultAnalyzer,
|
||||
IProfilingLogger profilingLogger,
|
||||
ILocalizationService languageService,
|
||||
IContentValueSetValidator validator,
|
||||
IReadOnlyDictionary<string, IFieldValueTypeFactory> 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
|
||||
|
||||
/// <summary>
|
||||
/// 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).
|
||||
/// </summary>
|
||||
/// <param name="name">The friendly name of the provider.</param>
|
||||
/// <param name="config">A collection of the name/value pairs representing the provider-specific attributes specified in the configuration for this provider.</param>
|
||||
/// <exception cref="T:System.ArgumentNullException">
|
||||
/// The name of the provider is null.
|
||||
/// </exception>
|
||||
/// <exception cref="T:System.ArgumentException">
|
||||
/// The name of the provider has a length of zero.
|
||||
/// </exception>
|
||||
/// <exception cref="T:System.InvalidOperationException">
|
||||
/// An attempt is made to call <see cref="M:System.Configuration.Provider.ProviderBase.Initialize(System.String,System.Collections.Specialized.NameValueCollection)"/> on a provider after the provider has already been initialized.
|
||||
/// </exception>
|
||||
[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
|
||||
|
||||
/// <summary>
|
||||
/// Special check for invalid paths
|
||||
/// </summary>
|
||||
@@ -166,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
|
||||
{
|
||||
@@ -192,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.
|
||||
/// </remarks>
|
||||
/// <param name="nodeId">ID of the node to delete</param>
|
||||
/// <param name="itemIds">ID of the node to delete</param>
|
||||
/// <param name="onComplete"></param>
|
||||
protected override void PerformDeleteFromIndex(string nodeId, Action<IndexOperationEventArgs> onComplete)
|
||||
protected override void PerformDeleteFromIndex(IEnumerable<string> itemIds, Action<IndexOperationEventArgs> 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);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -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,17 +40,6 @@ namespace Umbraco.Examine
|
||||
/// </summary>
|
||||
public const string RawFieldPrefix = SpecialFieldPrefix + "Raw_";
|
||||
|
||||
/// <summary>
|
||||
/// Constructor for config provider based indexes
|
||||
/// </summary>
|
||||
[EditorBrowsable(EditorBrowsableState.Never)]
|
||||
protected UmbracoExamineIndex()
|
||||
{
|
||||
ProfilingLogger = Current.ProfilingLogger;
|
||||
_configBased = true;
|
||||
_diagnostics = new UmbracoExamineIndexDiagnostics(this, ProfilingLogger);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Create a new <see cref="UmbracoExamineIndex"/>
|
||||
/// </summary>
|
||||
@@ -66,13 +52,13 @@ namespace Umbraco.Examine
|
||||
/// <param name="indexValueTypes"></param>
|
||||
protected UmbracoExamineIndex(
|
||||
string name,
|
||||
FieldDefinitionCollection fieldDefinitions,
|
||||
Directory luceneDirectory,
|
||||
FieldDefinitionCollection fieldDefinitions,
|
||||
Analyzer defaultAnalyzer,
|
||||
IProfilingLogger profilingLogger,
|
||||
IValueSetValidator validator = null,
|
||||
IReadOnlyDictionary<string, IFieldValueTypeFactory> indexValueTypes = null)
|
||||
: base(name, fieldDefinitions, luceneDirectory, defaultAnalyzer, validator, indexValueTypes)
|
||||
: base(name, luceneDirectory, fieldDefinitions, defaultAnalyzer, validator, indexValueTypes)
|
||||
{
|
||||
ProfilingLogger = profilingLogger ?? throw new ArgumentNullException(nameof(profilingLogger));
|
||||
|
||||
@@ -102,106 +88,19 @@ namespace Umbraco.Examine
|
||||
return searcher.GetAllIndexedFields();
|
||||
}
|
||||
|
||||
protected ConfigIndexCriteria ConfigIndexCriteria { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// The index set name which references an Examine <see cref="IndexSet"/>
|
||||
/// </summary>
|
||||
public string IndexSetName { get; private set; }
|
||||
|
||||
#region Initialize
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Setup the properties for the indexer from the provider settings
|
||||
/// </summary>
|
||||
/// <param name="name"></param>
|
||||
/// <param name="config"></param>
|
||||
/// <remarks>
|
||||
/// This is ONLY used for configuration based indexes
|
||||
/// </remarks>
|
||||
public override void Initialize(string name, System.Collections.Specialized.NameValueCollection config)
|
||||
{
|
||||
ProfilingLogger.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<IndexSet>().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
|
||||
|
||||
/// <summary>
|
||||
/// override to check if we can actually initialize.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This check is required since the base examine lib will try to rebuild on startup
|
||||
/// </remarks>
|
||||
protected override void PerformDeleteFromIndex(string nodeId, Action<IndexOperationEventArgs> onComplete)
|
||||
protected override void PerformDeleteFromIndex(IEnumerable<string> itemIds, Action<IndexOperationEventArgs> onComplete)
|
||||
{
|
||||
if (CanInitialize())
|
||||
{
|
||||
using (new SafeCallContext())
|
||||
{
|
||||
base.PerformDeleteFromIndex(nodeId, onComplete);
|
||||
base.PerformDeleteFromIndex(itemIds, onComplete);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -285,17 +184,7 @@ namespace Umbraco.Examine
|
||||
e.ValueSet.Values[IconFieldName] = icon;
|
||||
}
|
||||
}
|
||||
|
||||
private ConfigIndexCriteria CreateFieldDefinitionsFromConfig(IndexSet indexSet)
|
||||
{
|
||||
return new ConfigIndexCriteria(
|
||||
indexSet.IndexAttributeFields.Cast<ConfigIndexField>().Select(x => new FieldDefinition(x.Name, x.Type)).ToArray(),
|
||||
indexSet.IndexUserFields.Cast<ConfigIndexField>().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;
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
/// </summary>
|
||||
public class UmbracoMemberIndex : UmbracoExamineIndex
|
||||
{
|
||||
/// <summary>
|
||||
/// Constructor for config/provider based indexes
|
||||
/// </summary>
|
||||
[EditorBrowsable(EditorBrowsableState.Never)]
|
||||
public UmbracoMemberIndex()
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Constructor to allow for creating an indexer at runtime
|
||||
/// </summary>
|
||||
@@ -48,17 +29,10 @@ namespace Umbraco.Examine
|
||||
Analyzer analyzer,
|
||||
IProfilingLogger 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);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Overridden to ensure that the umbraco system field definitions are in place
|
||||
/// </summary>
|
||||
|
||||
@@ -9,14 +9,16 @@ namespace Umbraco.Tests.TestHelpers.Stubs
|
||||
private readonly ConcurrentDictionary<string, IIndex> _indexers = new ConcurrentDictionary<string, IIndex>();
|
||||
private readonly ConcurrentDictionary<string, ISearcher> _searchers = new ConcurrentDictionary<string, ISearcher>();
|
||||
|
||||
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()
|
||||
|
||||
@@ -77,7 +77,7 @@
|
||||
<ItemGroup>
|
||||
<PackageReference Include="AutoMapper" Version="7.0.1" />
|
||||
<PackageReference Include="Castle.Core" Version="4.2.1" />
|
||||
<PackageReference Include="Examine" Version="1.0.0-beta067" />
|
||||
<PackageReference Include="Examine" Version="1.0.0-beta072" />
|
||||
<PackageReference Include="HtmlAgilityPack">
|
||||
<Version>1.8.9</Version>
|
||||
</PackageReference>
|
||||
|
||||
@@ -164,8 +164,8 @@ namespace Umbraco.Tests.UmbracoExamine
|
||||
|
||||
var i = new UmbracoContentIndex(
|
||||
"testIndexer",
|
||||
new UmbracoFieldDefinitionCollection(),
|
||||
luceneDir,
|
||||
new UmbracoFieldDefinitionCollection(),
|
||||
analyzer,
|
||||
profilingLogger,
|
||||
languageService,
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<div ng-controller="Umbraco.Overlays.PublishController as vm">
|
||||
|
||||
<div style="margin-bottom: 15px;">
|
||||
<p><localize key="content_languagesToPublish"></localize></p>
|
||||
<p>{{vm.headline}}</p>
|
||||
</div>
|
||||
|
||||
<div ng-if="vm.loading" style="min-height: 50px; position: relative;">
|
||||
@@ -65,7 +65,7 @@
|
||||
<div ng-repeat="notification in variant.notifications">
|
||||
<div class="umb-permission__description" style="color: #1FB572;">{{notification.message}}</div>
|
||||
</div>
|
||||
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
})();
|
||||
|
||||
@@ -1,72 +1,120 @@
|
||||
<div ng-controller="Umbraco.Overlays.SaveContentController as vm">
|
||||
|
||||
<div style="margin-bottom: 15px;">
|
||||
<p><localize key="content_languagesToSave"></localize></p>
|
||||
</div>
|
||||
|
||||
|
||||
<div ng-if="vm.loading" style="min-height: 50px; position: relative;">
|
||||
<umb-load-indicator></umb-load-indicator>
|
||||
</div>
|
||||
|
||||
<div class="umb-list umb-list--condensed" ng-if="!vm.loading">
|
||||
|
||||
<div class="umb-list-item" ng-repeat="variant in vm.variants | filter:vm.dirtyVariantFilter track by variant.compositeId">
|
||||
<ng-form name="saveVariantSelectorForm">
|
||||
<div class="flex">
|
||||
<input id="{{variant.htmlId}}"
|
||||
name="saveVariantSelector"
|
||||
type="checkbox"
|
||||
ng-model="variant.save"
|
||||
ng-change="vm.changeSelection(variant)"
|
||||
style="margin-right: 8px;"
|
||||
val-server-field="{{variant.htmlId}}" />
|
||||
<div>
|
||||
<label for="{{variant.htmlId}}" style="margin-bottom: 2px;">
|
||||
<span>{{ variant.language.name }}</span>
|
||||
<strong ng-if="variant.language.isMandatory" class="umb-control-required">*</strong>
|
||||
</label>
|
||||
|
||||
<div ng-if="!saveVariantSelectorForm.$invalid && !(variant.notifications && variant.notifications.length > 0)">
|
||||
<umb-variant-state class="umb-permission__description" variant="variant"></umb-variant-state>
|
||||
</div>
|
||||
|
||||
<div ng-messages="saveVariantSelectorForm.saveVariantSelector.$error" show-validation-on-submit>
|
||||
<div class="umb-permission__description" style="color: #F02E28;" ng-message="valServerField">{{saveVariantSelectorForm.saveVariantSelector.errorMsg}}</div>
|
||||
</div>
|
||||
|
||||
<div ng-repeat="notification in variant.notifications">
|
||||
<div class="umb-permission__description" style="color: #1FB572;">{{notification.message}}</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</ng-form>
|
||||
<div ng-if="vm.isNew && !vm.loading">
|
||||
<div style="margin-bottom: 15px;">
|
||||
<p><localize key="content_languagesToSaveForFirstTime"></localize></p>
|
||||
</div>
|
||||
|
||||
<div class="umb-list umb-list--condensed">
|
||||
|
||||
<div class="umb-list-item" ng-repeat="variant in vm.variants">
|
||||
<ng-form name="saveVariantSelectorForm">
|
||||
<div class="flex">
|
||||
<input id="{{variant.htmlId}}"
|
||||
name="saveVariantSelector"
|
||||
type="checkbox"
|
||||
ng-model="variant.save"
|
||||
ng-disabled="vm.isNew"
|
||||
style="margin-right: 8px;"
|
||||
val-server-field="{{variant.htmlId}}" />
|
||||
<div>
|
||||
<label for="{{variant.htmlId}}" style="margin-bottom: 2px;">
|
||||
<span>{{ variant.language.name }}</span>
|
||||
<strong ng-if="variant.language.isMandatory" class="umb-control-required">*</strong>
|
||||
</label>
|
||||
|
||||
<div ng-if="!saveVariantSelectorForm.$invalid && !(variant.notifications && variant.notifications.length > 0)">
|
||||
<umb-variant-state class="umb-permission__description" variant="variant"></umb-variant-state>
|
||||
</div>
|
||||
|
||||
<div ng-messages="saveVariantSelectorForm.saveVariantSelector.$error" show-validation-on-submit>
|
||||
<div class="umb-permission__description" style="color: #F02E28;" ng-message="valServerField">{{saveVariantSelectorForm.saveVariantSelector.errorMsg}}</div>
|
||||
</div>
|
||||
|
||||
<div ng-repeat="notification in variant.notifications">
|
||||
<div class="umb-permission__description" style="color: #1FB572;">{{notification.message}}</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</ng-form>
|
||||
</div>
|
||||
<br/>
|
||||
</div>
|
||||
<br/>
|
||||
</div>
|
||||
|
||||
<div class="umb-list umb-list--condensed" ng-if="!vm.loading && vm.hasPristineVariants">
|
||||
<div style="margin-bottom: 15px; font-weight: bold;">
|
||||
<p><localize key="content_unmodifiedLanguages"></localize></p>
|
||||
<div ng-if="!vm.isNew && !vm.loading">
|
||||
<div style="margin-bottom: 15px;">
|
||||
<p><localize key="content_languagesToSave"></localize></p>
|
||||
</div>
|
||||
|
||||
<div class="umb-list-item" ng-repeat="variant in vm.variants | filter:vm.pristineVariantFilter">
|
||||
<div>
|
||||
<div style="margin-bottom: 2px;">
|
||||
<span>{{ variant.language.name }}</span>
|
||||
<strong ng-if="variant.language.isMandatory" class="umb-control-required">*</strong>
|
||||
</div>
|
||||
<div class="umb-list umb-list--condensed">
|
||||
|
||||
<div ng-if="!(variant.notifications && variant.notifications.length > 0)">
|
||||
<umb-variant-state class="umb-permission__description" variant="variant"></umb-variant-state>
|
||||
</div>
|
||||
<div class="umb-list-item" ng-repeat="variant in vm.variants | filter:vm.dirtyVariantFilter track by variant.compositeId">
|
||||
<ng-form name="saveVariantSelectorForm">
|
||||
<div class="flex">
|
||||
<input id="{{variant.htmlId}}"
|
||||
name="saveVariantSelector"
|
||||
type="checkbox"
|
||||
ng-model="variant.save"
|
||||
ng-change="vm.changeSelection(variant)"
|
||||
style="margin-right: 8px;"
|
||||
val-server-field="{{variant.htmlId}}" />
|
||||
<div>
|
||||
<label for="{{variant.htmlId}}" style="margin-bottom: 2px;">
|
||||
<span>{{ variant.language.name }}</span>
|
||||
<strong ng-if="variant.language.isMandatory" class="umb-control-required">*</strong>
|
||||
</label>
|
||||
|
||||
<div ng-repeat="notification in variant.notifications">
|
||||
<div class="umb-permission__description" style="color: #1FB572;">{{notification.message}}</div>
|
||||
<div ng-if="!saveVariantSelectorForm.$invalid && !(variant.notifications && variant.notifications.length > 0)">
|
||||
<umb-variant-state class="umb-permission__description" variant="variant"></umb-variant-state>
|
||||
</div>
|
||||
|
||||
<div ng-messages="saveVariantSelectorForm.saveVariantSelector.$error" show-validation-on-submit>
|
||||
<div class="umb-permission__description" style="color: #F02E28;" ng-message="valServerField">{{saveVariantSelectorForm.saveVariantSelector.errorMsg}}</div>
|
||||
</div>
|
||||
|
||||
<div ng-repeat="notification in variant.notifications">
|
||||
<div class="umb-permission__description" style="color: #1FB572;">{{notification.message}}</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</ng-form>
|
||||
</div>
|
||||
<br/>
|
||||
</div>
|
||||
|
||||
<div class="umb-list umb-list--condensed" ng-if="vm.hasPristineVariants">
|
||||
<div style="margin-bottom: 15px; font-weight: bold;">
|
||||
<p><localize key="content_unmodifiedLanguages"></localize></p>
|
||||
</div>
|
||||
|
||||
<div class="umb-list-item" ng-repeat="variant in vm.variants | filter:vm.pristineVariantFilter">
|
||||
<div>
|
||||
<div style="margin-bottom: 2px;">
|
||||
<span>{{ variant.language.name }}</span>
|
||||
<strong ng-if="variant.language.isMandatory" class="umb-control-required">*</strong>
|
||||
</div>
|
||||
|
||||
<div ng-if="!(variant.notifications && variant.notifications.length > 0)">
|
||||
<umb-variant-state class="umb-permission__description" variant="variant"></umb-variant-state>
|
||||
</div>
|
||||
|
||||
<div ng-repeat="notification in variant.notifications">
|
||||
<div class="umb-permission__description" style="color: #1FB572;">{{notification.message}}</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
@@ -88,7 +88,7 @@
|
||||
<PackageReference Include="CSharpTest.Net.Collections" Version="14.906.1403.1082" />
|
||||
<PackageReference Include="ClientDependency" Version="1.9.7" />
|
||||
<PackageReference Include="ClientDependency-Mvc5" Version="1.8.0.0" />
|
||||
<PackageReference Include="Examine" Version="1.0.0-beta067" />
|
||||
<PackageReference Include="Examine" Version="1.0.0-beta072" />
|
||||
<PackageReference Include="ImageProcessor.Web" Version="4.9.3.25" />
|
||||
<PackageReference Include="ImageProcessor.Web.Config" Version="2.4.1.19" />
|
||||
<PackageReference Include="Microsoft.AspNet.Identity.Owin" Version="2.2.2" />
|
||||
@@ -260,16 +260,9 @@
|
||||
<None Include="Config\scripting.Release.config">
|
||||
<DependentUpon>scripting.config</DependentUpon>
|
||||
</None>
|
||||
<None Include="Config\ExamineSettings.Release.config">
|
||||
<DependentUpon>ExamineSettings.config</DependentUpon>
|
||||
</None>
|
||||
<None Include="Config\feedProxy.Release.config">
|
||||
<DependentUpon>feedProxy.config</DependentUpon>
|
||||
</None>
|
||||
<None Include="Config\ExamineIndex.Release.config">
|
||||
<DependentUpon>ExamineIndex.config</DependentUpon>
|
||||
<SubType>Designer</SubType>
|
||||
</None>
|
||||
<None Include="Config\Dashboard.Release.config">
|
||||
<DependentUpon>Dashboard.config</DependentUpon>
|
||||
<SubType>Designer</SubType>
|
||||
@@ -317,10 +310,6 @@
|
||||
<Content Include="Config\ClientDependency.config">
|
||||
<SubType>Designer</SubType>
|
||||
</Content>
|
||||
<Content Include="Config\ExamineSettings.config" />
|
||||
<Content Include="Config\ExamineIndex.config">
|
||||
<SubType>Designer</SubType>
|
||||
</Content>
|
||||
<Content Include="Config\scripting.config" />
|
||||
<Content Include="Config\feedProxy.config" />
|
||||
<Content Include="Config\applications.config" />
|
||||
|
||||
@@ -270,8 +270,10 @@
|
||||
<key alias="includeUnpublished">Include drafts: also publish unpublished content items.</key>
|
||||
<key alias="isSensitiveValue">This value is hidden. If you need access to view this value please contact your website administrator.</key>
|
||||
<key alias="isSensitiveValue_short">This value is hidden.</key>
|
||||
<key alias="languagesToPublishForFirstTime">What languages would you like to publish? All languages with content are saved!</key>
|
||||
<key alias="languagesToPublish">What languages would you like to publish?</key>
|
||||
<key alias="languagesToSave">What languages would you like to save?</key>
|
||||
<key alias="languagesToSaveForFirstTime">All languages with content are saved on creation!</key>
|
||||
<key alias="languagesToSendForApproval">What languages would you like to send for approval?</key>
|
||||
<key alias="languagesToSchedule">What languages would you like to schedule?</key>
|
||||
<key alias="languagesToUnpublish">Select the languages to unpublish. Unpublishing a mandatory language will unpublish all languages.</key>
|
||||
|
||||
@@ -1,10 +0,0 @@
|
||||
<?xml version="1.0"?>
|
||||
<!--
|
||||
Umbraco examine is an extensible indexer and search engine.
|
||||
This configuration file can be extended to create your own index sets.
|
||||
Index/Search providers can be defined in the UmbracoSettings.config
|
||||
|
||||
More information and documentation can be found on GitHub: https://github.com/Shazwazza/Examine/
|
||||
-->
|
||||
<ExamineLuceneIndexSets>
|
||||
</ExamineLuceneIndexSets>
|
||||
@@ -1,14 +0,0 @@
|
||||
<?xml version="1.0"?>
|
||||
<!--
|
||||
Umbraco examine is an extensible indexer and search engine.
|
||||
This configuration file can be extended to create your own index sets.
|
||||
Index/Search providers can be defined in the UmbracoSettings.config
|
||||
|
||||
More information and documentation can be found on Our:
|
||||
https://our.umbraco.com/Documentation/Reference/Searching/Examine/
|
||||
https://our.umbraco.com/Documentation/Reference/Config/ExamineIndex/
|
||||
https://our.umbraco.com/Documentation/Reference/Config/ExamineSettings/
|
||||
|
||||
-->
|
||||
<ExamineLuceneIndexSets>
|
||||
</ExamineLuceneIndexSets>
|
||||
@@ -1,21 +0,0 @@
|
||||
<?xml version="1.0"?>
|
||||
<!--
|
||||
Umbraco examine is an extensible indexer and search engine.
|
||||
This configuration file can be extended to add your own search/index providers.
|
||||
Index sets can be defined in the ExamineIndex.config if you're using the standard provider model.
|
||||
|
||||
More information and documentation can be found on GitHub: https://github.com/Shazwazza/Examine/
|
||||
-->
|
||||
<Examine>
|
||||
|
||||
<ExamineIndexProviders>
|
||||
<providers>
|
||||
</providers>
|
||||
</ExamineIndexProviders>
|
||||
|
||||
<ExamineSearchProviders>
|
||||
<providers>
|
||||
</providers>
|
||||
</ExamineSearchProviders>
|
||||
|
||||
</Examine>
|
||||
@@ -1,23 +0,0 @@
|
||||
<?xml version="1.0"?>
|
||||
<!--
|
||||
Umbraco examine is an extensible indexer and search engine.
|
||||
This configuration file can be extended to add your own search/index providers.
|
||||
Index sets can be defined in the ExamineIndex.config if you're using the standard provider model.
|
||||
|
||||
More information and documentation can be found on Our:
|
||||
https://our.umbraco.com/Documentation/Reference/Searching/Examine/
|
||||
https://our.umbraco.com/Documentation/Reference/Config/ExamineIndex/
|
||||
https://our.umbraco.com/Documentation/Reference/Config/ExamineSettings/
|
||||
-->
|
||||
<Examine>
|
||||
<ExamineIndexProviders>
|
||||
<providers>
|
||||
</providers>
|
||||
</ExamineIndexProviders>
|
||||
|
||||
<ExamineSearchProviders>
|
||||
<providers>
|
||||
</providers>
|
||||
</ExamineSearchProviders>
|
||||
|
||||
</Examine>
|
||||
@@ -1,7 +1,8 @@
|
||||
<?xml version="1.0"?>
|
||||
<configuration xmlns:xdt="http://schemas.microsoft.com/XML-Document-Transform">
|
||||
|
||||
<!--
|
||||
|
||||
<!--
|
||||
Defines transforms that apply to web.Template.config when creating the Debug web.config.
|
||||
|
||||
This file should contain changes that need to go into the Debug config (the one that everybody
|
||||
@@ -11,8 +12,17 @@
|
||||
One can edit web.config, it will not be overritten, but it WILL be altered by this transform
|
||||
file everytime Umbraco builds.
|
||||
-->
|
||||
|
||||
<configSections>
|
||||
<section name="Examine" xdt:Transform="Remove" xdt:Locator="Match(name)" />
|
||||
<section name="ExamineLuceneIndexSets" xdt:Transform="Remove" xdt:Locator="Match(name)" />
|
||||
</configSections>
|
||||
|
||||
<Examine xdt:Transform="Remove" />
|
||||
<ExamineLuceneIndexSets xdt:Transform="Remove" />
|
||||
|
||||
<system.web>
|
||||
<compilation debug="true" xdt:Transform="SetAttributes(debug)" />
|
||||
</system.web>
|
||||
|
||||
|
||||
</configuration>
|
||||
|
||||
@@ -10,8 +10,6 @@
|
||||
<configSections>
|
||||
<section name="microsoft.scripting" type="Microsoft.Scripting.Hosting.Configuration.Section, Microsoft.Scripting, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" requirePermission="false" />
|
||||
<section name="clientDependency" type="ClientDependency.Core.Config.ClientDependencySection, ClientDependency.Core" requirePermission="false" />
|
||||
<section name="Examine" type="Examine.Config.ExamineSettings, Examine" requirePermission="false" />
|
||||
<section name="ExamineLuceneIndexSets" type="Umbraco.Examine.Config.IndexSets, Umbraco.Examine" requirePermission="false" />
|
||||
|
||||
<sectionGroup name="umbracoConfiguration">
|
||||
<section name="settings" type="Umbraco.Core.Configuration.UmbracoSettings.UmbracoSettingsSection, Umbraco.Core" requirePermission="false" />
|
||||
@@ -36,8 +34,6 @@
|
||||
|
||||
<microsoft.scripting configSource="config\scripting.config" />
|
||||
<clientDependency configSource="config\ClientDependency.config" />
|
||||
<Examine configSource="config\ExamineSettings.config" />
|
||||
<ExamineLuceneIndexSets configSource="config\ExamineIndex.config" />
|
||||
|
||||
<appSettings>
|
||||
<add key="umbracoConfigurationStatus" value="" />
|
||||
|
||||
@@ -515,13 +515,14 @@ 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.", 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));
|
||||
|
||||
@@ -612,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);
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
|
||||
@@ -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<IIndexPopulator> and get them all
|
||||
composition.Register<IIndexPopulator, MemberIndexPopulator>(Lifetime.Singleton);
|
||||
composition.Register<IIndexPopulator, ContentIndexPopulator>(Lifetime.Singleton);
|
||||
composition.Register<IIndexPopulator, PublishedContentIndexPopulator>(Lifetime.Singleton);
|
||||
composition.Register<IIndexPopulator, MediaIndexPopulator>(Lifetime.Singleton);
|
||||
composition.Register<MemberIndexPopulator>(Lifetime.Singleton);
|
||||
composition.Register<ContentIndexPopulator>(Lifetime.Singleton);
|
||||
composition.Register<PublishedContentIndexPopulator>(Lifetime.Singleton);
|
||||
composition.Register<MediaIndexPopulator>(Lifetime.Singleton);
|
||||
|
||||
composition.Register<IndexRebuilder>(Lifetime.Singleton);
|
||||
composition.RegisterUnique<IUmbracoIndexesCreator, UmbracoIndexesCreator>();
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -63,7 +63,7 @@
|
||||
<PackageReference Include="AutoMapper" Version="7.0.1" />
|
||||
<PackageReference Include="ClientDependency" Version="1.9.7" />
|
||||
<PackageReference Include="CSharpTest.Net.Collections" Version="14.906.1403.1082" />
|
||||
<PackageReference Include="Examine" Version="1.0.0-beta067" />
|
||||
<PackageReference Include="Examine" Version="1.0.0-beta072" />
|
||||
<PackageReference Include="HtmlAgilityPack" Version="1.8.9" />
|
||||
<PackageReference Include="ImageProcessor">
|
||||
<Version>2.6.2.25</Version>
|
||||
|
||||
Reference in New Issue
Block a user