Compare commits
69 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| f2c7c1e2c6 | |||
| 9f2c428a7c | |||
| a958f946ef | |||
| 688652fb91 | |||
| d6bc0934ff | |||
| 759c6dfef2 | |||
| 218f523022 | |||
| 50c6fb036a | |||
| bc2115ff0a | |||
| 9eee5c2bc0 | |||
| ed3096642d | |||
| 95508c4fb7 | |||
| 4677faff38 | |||
| 725b3c5eca | |||
| 25f5179b29 | |||
| bf6d084f82 | |||
| 1a03bd9624 | |||
| 6a1d60c5a7 | |||
| 4fef17190f | |||
| 08ca75bb35 | |||
| 0512eaa7fd | |||
| e8df5f9eb4 | |||
| c46678c766 | |||
| 7cdb48b6c9 | |||
| 4ffa6bb41b | |||
| 77af16db55 | |||
| 85d85fa587 | |||
| 7ade64f855 | |||
| 346e8dcaf0 | |||
| ddfd07bf4a | |||
| a9fe46da0c | |||
| aca1f0d186 | |||
| 9eb415d398 | |||
| 8f6b728534 | |||
| 2e0c09ab39 | |||
| f211344786 | |||
| 68702b98f5 | |||
| f93caf277b | |||
| e0a7698780 | |||
| 783c74d3ba | |||
| 21963c03a2 | |||
| 879a132077 | |||
| 606ebcae92 | |||
| af10ae9e34 | |||
| a23c150738 | |||
| 085a678266 | |||
| cf7cafeb4c | |||
| 870657affa | |||
| fe11d4770d | |||
| c8fe9030c7 | |||
| 3d81c73495 | |||
| e7a540e717 | |||
| bb886c237e | |||
| 6c1e271fa8 | |||
| 4c1b807e4f | |||
| 3b22c0cdd7 | |||
| 631404743f | |||
| d5c9639170 | |||
| 94b7c36d62 | |||
| 532b177d2e | |||
| 4093fd9b79 | |||
| 3d6f91cbef | |||
| fffd508bb2 | |||
| 333b35d8b9 | |||
| 890673a197 | |||
| 27539d4aad | |||
| f7f23015d0 | |||
| e432b7061d | |||
| fc92d40b3a |
@@ -32,7 +32,7 @@
|
||||
<!-- AutoMapper can not be updated due to: https://github.com/AutoMapper/AutoMapper/issues/373#issuecomment-127644405 -->
|
||||
<dependency id="AutoMapper" version="[3.3.1, 4.0.0)" />
|
||||
<dependency id="Newtonsoft.Json" version="[6.0.8, 10.0.0)" />
|
||||
<dependency id="Examine" version="[0.1.81, 1.0.0)" />
|
||||
<dependency id="Examine" version="[0.1.82, 1.0.0)" />
|
||||
<dependency id="ImageProcessor" version="[2.5.2, 3.0.0)" />
|
||||
<dependency id="ImageProcessor.Web" version="[4.8.2, 5.0.0)" />
|
||||
<dependency id="semver" version="[1.1.2, 2.0.0)" />
|
||||
|
||||
@@ -17,8 +17,8 @@
|
||||
<dependencies>
|
||||
<dependency id="UmbracoCms.Core" version="[$version$]" />
|
||||
<dependency id="Newtonsoft.Json" version="[6.0.8, 10.0.0)" />
|
||||
<dependency id="Umbraco.ModelsBuilder" version="[3.0.5, 4.0.0)" />
|
||||
<dependency id="ImageProcessor.Web.Config" version="[2.3.0, 3.0.0)" />
|
||||
<dependency id="Umbraco.ModelsBuilder" version="[3.0.7, 4.0.0)" />
|
||||
<dependency id="ImageProcessor.Web.Config" version="[2.3.0, 3.0.0)" />
|
||||
</dependencies>
|
||||
</metadata>
|
||||
<files>
|
||||
|
||||
@@ -1,2 +1,2 @@
|
||||
# Usage: on line 2 put the release version, on line 3 put the version comment (example: beta)
|
||||
7.5.11
|
||||
7.5.13
|
||||
+2
-2
@@ -11,5 +11,5 @@ using System.Resources;
|
||||
|
||||
[assembly: AssemblyVersion("1.0.*")]
|
||||
|
||||
[assembly: AssemblyFileVersion("7.5.11")]
|
||||
[assembly: AssemblyInformationalVersion("7.5.11")]
|
||||
[assembly: AssemblyFileVersion("7.5.13")]
|
||||
[assembly: AssemblyInformationalVersion("7.5.13")]
|
||||
@@ -26,6 +26,9 @@ namespace Umbraco.Core.Cache
|
||||
|
||||
public DeepCloneRuntimeCacheProvider(IRuntimeCacheProvider innerProvider)
|
||||
{
|
||||
if (innerProvider.GetType() == typeof(DeepCloneRuntimeCacheProvider))
|
||||
throw new InvalidOperationException("A " + typeof(DeepCloneRuntimeCacheProvider) + " cannot wrap another instance of " + typeof(DeepCloneRuntimeCacheProvider));
|
||||
|
||||
InnerProvider = innerProvider;
|
||||
}
|
||||
|
||||
@@ -105,9 +108,11 @@ namespace Umbraco.Core.Cache
|
||||
var value = result.Value; // force evaluation now - this may throw if cacheItem throws, and then nothing goes into cache
|
||||
if (value == null) return null; // do not store null values (backward compat)
|
||||
|
||||
//Clone/reset to go into the cache
|
||||
return CheckCloneableAndTracksChanges(value);
|
||||
}, timeout, isSliding, priority, removedCallback, dependentFiles);
|
||||
|
||||
//Clone/reset to go out of the cache
|
||||
return CheckCloneableAndTracksChanges(cached);
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,27 @@
|
||||
using System;
|
||||
|
||||
namespace Umbraco.Core.Configuration
|
||||
{
|
||||
internal static class CoreDebugExtensions
|
||||
{
|
||||
private static CoreDebug _coreDebug;
|
||||
|
||||
public static CoreDebug CoreDebug(this UmbracoConfig config)
|
||||
{
|
||||
return _coreDebug ?? (_coreDebug = new CoreDebug());
|
||||
}
|
||||
}
|
||||
|
||||
internal class CoreDebug
|
||||
{
|
||||
public CoreDebug()
|
||||
{
|
||||
var appSettings = System.Configuration.ConfigurationManager.AppSettings;
|
||||
DumpOnTimeoutThreadAbort = string.Equals("true", appSettings["Umbraco.CoreDebug.DumpOnTimeoutThreadAbort"], StringComparison.OrdinalIgnoreCase);
|
||||
}
|
||||
|
||||
// when true, the Logger creates a minidump of w3wp in ~/App_Data/MiniDump whenever it logs
|
||||
// an error due to a ThreadAbortException that is due to a timeout.
|
||||
public bool DumpOnTimeoutThreadAbort { get; private set; }
|
||||
}
|
||||
}
|
||||
@@ -6,7 +6,7 @@ namespace Umbraco.Core.Configuration
|
||||
{
|
||||
public class UmbracoVersion
|
||||
{
|
||||
private static readonly Version Version = new Version("7.5.11");
|
||||
private static readonly Version Version = new Version("7.5.13");
|
||||
|
||||
/// <summary>
|
||||
/// Gets the current version of Umbraco.
|
||||
|
||||
@@ -0,0 +1,135 @@
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.Runtime.InteropServices;
|
||||
using Umbraco.Core.IO;
|
||||
|
||||
namespace Umbraco.Core.Diagnostics
|
||||
{
|
||||
// taken from https://blogs.msdn.microsoft.com/dondu/2010/10/24/writing-minidumps-in-c/
|
||||
// and https://blogs.msdn.microsoft.com/dondu/2010/10/31/writing-minidumps-from-exceptions-in-c/
|
||||
// which itself got it from http://blog.kalmbach-software.de/2008/12/13/writing-minidumps-in-c/
|
||||
|
||||
internal static class MiniDump
|
||||
{
|
||||
private static readonly object LockO = new object();
|
||||
|
||||
[Flags]
|
||||
public enum Option : uint
|
||||
{
|
||||
// From dbghelp.h:
|
||||
Normal = 0x00000000,
|
||||
WithDataSegs = 0x00000001,
|
||||
WithFullMemory = 0x00000002,
|
||||
WithHandleData = 0x00000004,
|
||||
FilterMemory = 0x00000008,
|
||||
ScanMemory = 0x00000010,
|
||||
WithUnloadedModules = 0x00000020,
|
||||
WithIndirectlyReferencedMemory = 0x00000040,
|
||||
FilterModulePaths = 0x00000080,
|
||||
WithProcessThreadData = 0x00000100,
|
||||
WithPrivateReadWriteMemory = 0x00000200,
|
||||
WithoutOptionalData = 0x00000400,
|
||||
WithFullMemoryInfo = 0x00000800,
|
||||
WithThreadInfo = 0x00001000,
|
||||
WithCodeSegs = 0x00002000,
|
||||
WithoutAuxiliaryState = 0x00004000,
|
||||
WithFullAuxiliaryState = 0x00008000,
|
||||
WithPrivateWriteCopyMemory = 0x00010000,
|
||||
IgnoreInaccessibleMemory = 0x00020000,
|
||||
ValidTypeFlags = 0x0003ffff,
|
||||
}
|
||||
|
||||
//typedef struct _MINIDUMP_EXCEPTION_INFORMATION {
|
||||
// DWORD ThreadId;
|
||||
// PEXCEPTION_POINTERS ExceptionPointers;
|
||||
// BOOL ClientPointers;
|
||||
//} MINIDUMP_EXCEPTION_INFORMATION, *PMINIDUMP_EXCEPTION_INFORMATION;
|
||||
[StructLayout(LayoutKind.Sequential, Pack = 4)] // Pack=4 is important! So it works also for x64!
|
||||
public struct MiniDumpExceptionInformation
|
||||
{
|
||||
public uint ThreadId;
|
||||
public IntPtr ExceptionPointers;
|
||||
[MarshalAs(UnmanagedType.Bool)]
|
||||
public bool ClientPointers;
|
||||
}
|
||||
|
||||
//BOOL
|
||||
//WINAPI
|
||||
//MiniDumpWriteDump(
|
||||
// __in HANDLE hProcess,
|
||||
// __in DWORD ProcessId,
|
||||
// __in HANDLE hFile,
|
||||
// __in MINIDUMP_TYPE DumpType,
|
||||
// __in_opt PMINIDUMP_EXCEPTION_INFORMATION ExceptionParam,
|
||||
// __in_opt PMINIDUMP_USER_STREAM_INFORMATION UserStreamParam,
|
||||
// __in_opt PMINIDUMP_CALLBACK_INFORMATION CallbackParam
|
||||
// );
|
||||
|
||||
// Overload requiring MiniDumpExceptionInformation
|
||||
[DllImport("dbghelp.dll", EntryPoint = "MiniDumpWriteDump", CallingConvention = CallingConvention.StdCall, CharSet = CharSet.Unicode, ExactSpelling = true, SetLastError = true)]
|
||||
private static extern bool MiniDumpWriteDump(IntPtr hProcess, uint processId, SafeHandle hFile, uint dumpType, ref MiniDumpExceptionInformation expParam, IntPtr userStreamParam, IntPtr callbackParam);
|
||||
|
||||
// Overload supporting MiniDumpExceptionInformation == NULL
|
||||
[DllImport("dbghelp.dll", EntryPoint = "MiniDumpWriteDump", CallingConvention = CallingConvention.StdCall, CharSet = CharSet.Unicode, ExactSpelling = true, SetLastError = true)]
|
||||
private static extern bool MiniDumpWriteDump(IntPtr hProcess, uint processId, SafeHandle hFile, uint dumpType, IntPtr expParam, IntPtr userStreamParam, IntPtr callbackParam);
|
||||
|
||||
[DllImport("kernel32.dll", EntryPoint = "GetCurrentThreadId", ExactSpelling = true)]
|
||||
private static extern uint GetCurrentThreadId();
|
||||
|
||||
private static bool Write(SafeHandle fileHandle, Option options, bool withException = false)
|
||||
{
|
||||
var currentProcess = Process.GetCurrentProcess();
|
||||
var currentProcessHandle = currentProcess.Handle;
|
||||
var currentProcessId = (uint)currentProcess.Id;
|
||||
|
||||
MiniDumpExceptionInformation exp;
|
||||
|
||||
exp.ThreadId = GetCurrentThreadId();
|
||||
exp.ClientPointers = false;
|
||||
exp.ExceptionPointers = IntPtr.Zero;
|
||||
|
||||
if (withException)
|
||||
exp.ExceptionPointers = Marshal.GetExceptionPointers();
|
||||
|
||||
var bRet = exp.ExceptionPointers == IntPtr.Zero
|
||||
? MiniDumpWriteDump(currentProcessHandle, currentProcessId, fileHandle, (uint) options, IntPtr.Zero, IntPtr.Zero, IntPtr.Zero)
|
||||
: MiniDumpWriteDump(currentProcessHandle, currentProcessId, fileHandle, (uint) options, ref exp, IntPtr.Zero, IntPtr.Zero);
|
||||
|
||||
return bRet;
|
||||
}
|
||||
|
||||
public static bool Dump(Option options = Option.WithFullMemory, bool withException = false)
|
||||
{
|
||||
lock (LockO)
|
||||
{
|
||||
// work around "stack trace is not available while minidump debugging",
|
||||
// by making sure a local var (that we can inspect) contains the stack trace.
|
||||
// getting the call stack before it is unwound would require a special exception
|
||||
// filter everywhere in our code = not!
|
||||
var stacktrace = withException ? Environment.StackTrace : string.Empty;
|
||||
|
||||
var filepath = IOHelper.MapPath("~/App_Data/MiniDump");
|
||||
if (Directory.Exists(filepath) == false)
|
||||
Directory.CreateDirectory(filepath);
|
||||
|
||||
var filename = Path.Combine(filepath, string.Format("{0:yyyyMMddTHHmmss}.{1}.dmp", DateTime.UtcNow, Guid.NewGuid().ToString("N").Substring(0, 4)));
|
||||
using (var stream = new FileStream(filename, FileMode.Create, FileAccess.ReadWrite, FileShare.Write))
|
||||
{
|
||||
return Write(stream.SafeFileHandle, options, withException);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static bool OkToDump()
|
||||
{
|
||||
lock (LockO)
|
||||
{
|
||||
var filepath = IOHelper.MapPath("~/App_Data/MiniDump");
|
||||
if (Directory.Exists(filepath) == false) return true;
|
||||
var count = Directory.GetFiles(filepath, "*.dmp").Length;
|
||||
return count < 8;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -7,6 +7,8 @@ using System.Threading;
|
||||
using System.Web;
|
||||
using log4net;
|
||||
using log4net.Config;
|
||||
using Umbraco.Core.Configuration;
|
||||
using Umbraco.Core.Diagnostics;
|
||||
|
||||
namespace Umbraco.Core.Logging
|
||||
{
|
||||
@@ -57,23 +59,55 @@ namespace Umbraco.Core.Logging
|
||||
internal ILog LoggerFor(object getTypeFromInstance)
|
||||
{
|
||||
if (getTypeFromInstance == null) throw new ArgumentNullException("getTypeFromInstance");
|
||||
|
||||
|
||||
return LogManager.GetLogger(getTypeFromInstance.GetType());
|
||||
}
|
||||
|
||||
|
||||
public void Error(Type callingType, string message, Exception exception)
|
||||
{
|
||||
var logger = LogManager.GetLogger(callingType);
|
||||
if (logger == null) return;
|
||||
|
||||
var dump = false;
|
||||
|
||||
if (IsTimeoutThreadAbortException(exception))
|
||||
{
|
||||
message += "\r\nThe thread has been aborted, because the request has timed out.";
|
||||
|
||||
// dump if configured, or if stacktrace contains Monitor.ReliableEnter
|
||||
dump = UmbracoConfig.For.CoreDebug().DumpOnTimeoutThreadAbort || IsMonitorEnterThreadAbortException(exception);
|
||||
|
||||
// dump if it is ok to dump (might have a cap on number of dump...)
|
||||
dump &= MiniDump.OkToDump();
|
||||
}
|
||||
|
||||
logger.Error(message, exception);
|
||||
if (dump)
|
||||
{
|
||||
try
|
||||
{
|
||||
var dumped = MiniDump.Dump(withException: true);
|
||||
message += dumped
|
||||
? "\r\nA minidump was created in App_Data/MiniDump"
|
||||
: "\r\nFailed to create a minidump";
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
message += string.Format("\r\nFailed to create a minidump ({0}: {1})", e.GetType().FullName, e.Message);
|
||||
}
|
||||
}
|
||||
|
||||
logger.Error(message, exception);
|
||||
}
|
||||
|
||||
private static bool IsMonitorEnterThreadAbortException(Exception exception)
|
||||
{
|
||||
var abort = exception as ThreadAbortException;
|
||||
if (abort == null) return false;
|
||||
|
||||
var stacktrace = abort.StackTrace;
|
||||
return stacktrace.Contains("System.Threading.Monitor.ReliableEnter");
|
||||
}
|
||||
|
||||
private static bool IsTimeoutThreadAbortException(Exception exception)
|
||||
{
|
||||
var abort = exception as ThreadAbortException;
|
||||
@@ -105,7 +139,7 @@ namespace Umbraco.Core.Logging
|
||||
if (showHttpTrace && HttpContext.Current != null)
|
||||
{
|
||||
HttpContext.Current.Trace.Warn(callingType.Name, string.Format(message, formatItems.Select(x => x.Invoke()).ToArray()));
|
||||
}
|
||||
}
|
||||
|
||||
var logger = LogManager.GetLogger(callingType);
|
||||
if (logger == null || logger.IsWarnEnabled == false) return;
|
||||
@@ -122,7 +156,7 @@ namespace Umbraco.Core.Logging
|
||||
var logger = LogManager.GetLogger(callingType);
|
||||
if (logger == null || logger.IsWarnEnabled == false) return;
|
||||
var executedParams = formatItems.Select(x => x.Invoke()).ToArray();
|
||||
logger.WarnFormat((message) + ". Exception: " + e, executedParams);
|
||||
logger.WarnFormat((message) + ". Exception: " + e, executedParams);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -274,6 +274,9 @@ namespace Umbraco.Core.Models
|
||||
/// </summary>
|
||||
public bool HasPublishedVersion { get { return PublishedVersionGuid != default(Guid); } }
|
||||
|
||||
[IgnoreDataMember]
|
||||
internal DateTime PublishedDate { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Changes the Trashed state of the content object
|
||||
/// </summary>
|
||||
|
||||
@@ -179,7 +179,7 @@ namespace Umbraco.Core.Models.PublishedContent
|
||||
}
|
||||
|
||||
if (contentType == null)
|
||||
throw new Exception(string.Format("ContentTypeService failed to find a {0} type with alias \"{1}\".",
|
||||
throw new InvalidOperationException(string.Format("ContentTypeService failed to find a {0} type with alias \"{1}\".",
|
||||
itemType.ToString().ToLower(), alias));
|
||||
|
||||
return new PublishedContentType(contentType);
|
||||
|
||||
@@ -19,5 +19,8 @@ namespace Umbraco.Core.Models.Rdbms
|
||||
|
||||
[Column("newest")]
|
||||
public bool Newest { get; set; }
|
||||
|
||||
[Column("updateDate")]
|
||||
public DateTime VersionDate { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -22,6 +22,7 @@ namespace Umbraco.Core.ObjectResolution
|
||||
private readonly string _httpContextKey;
|
||||
private readonly List<Type> _instanceTypes = new List<Type>();
|
||||
private IEnumerable<TResolved> _sortedValues;
|
||||
private readonly Func<HttpContextBase> _httpContextGetter;
|
||||
|
||||
private int _defaultPluginWeight = 100;
|
||||
|
||||
@@ -42,12 +43,7 @@ namespace Umbraco.Core.ObjectResolution
|
||||
if (logger == null) throw new ArgumentNullException("logger");
|
||||
CanResolveBeforeFrozen = false;
|
||||
if (scope == ObjectLifetimeScope.HttpRequest)
|
||||
{
|
||||
if (HttpContext.Current == null)
|
||||
throw new InvalidOperationException("Use alternative constructor accepting a HttpContextBase object in order to set the lifetime scope to HttpRequest when HttpContext.Current is null");
|
||||
|
||||
CurrentHttpContext = new HttpContextWrapper(HttpContext.Current);
|
||||
}
|
||||
_httpContextGetter = () => new HttpContextWrapper(HttpContext.Current);
|
||||
|
||||
ServiceProvider = serviceProvider;
|
||||
Logger = logger;
|
||||
@@ -84,7 +80,7 @@ namespace Umbraco.Core.ObjectResolution
|
||||
LifetimeScope = ObjectLifetimeScope.HttpRequest;
|
||||
_httpContextKey = GetType().FullName;
|
||||
ServiceProvider = serviceProvider;
|
||||
CurrentHttpContext = httpContext;
|
||||
_httpContextGetter = () => httpContext;
|
||||
_instanceTypes = new List<Type>();
|
||||
|
||||
InitializeAppInstances();
|
||||
@@ -160,7 +156,16 @@ namespace Umbraco.Core.ObjectResolution
|
||||
/// Gets or sets the <see cref="HttpContextBase"/> used to initialize this object, if any.
|
||||
/// </summary>
|
||||
/// <remarks>If not null, then <c>LifetimeScope</c> will be <c>ObjectLifetimeScope.HttpRequest</c>.</remarks>
|
||||
protected HttpContextBase CurrentHttpContext { get; private set; }
|
||||
protected HttpContextBase CurrentHttpContext
|
||||
{
|
||||
get
|
||||
{
|
||||
var context = _httpContextGetter == null ? null : _httpContextGetter();
|
||||
if (context == null)
|
||||
throw new InvalidOperationException("Cannot use this resolver with lifetime 'HttpRequest' when there is no current HttpContext. Either use the ctor accepting an HttpContextBase, or use the resolver from within a request exclusively.");
|
||||
return context;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the service provider used to instantiate objects
|
||||
@@ -196,7 +201,7 @@ namespace Umbraco.Core.ObjectResolution
|
||||
/// <summary>
|
||||
/// Gets or sets the default type weight.
|
||||
/// </summary>
|
||||
/// <remarks>Determines the weight of types that do not have a <c>WeightAttribute</c> set on
|
||||
/// <remarks>Determines the weight of types that do not have a <c>WeightAttribute</c> set on
|
||||
/// them, when calling <c>GetSortedValues</c>.</remarks>
|
||||
protected virtual int DefaultPluginWeight
|
||||
{
|
||||
@@ -276,7 +281,7 @@ namespace Umbraco.Core.ObjectResolution
|
||||
/// Removes a type.
|
||||
/// </summary>
|
||||
/// <param name="value">The type to remove.</param>
|
||||
/// <exception cref="InvalidOperationException">the resolver does not support removing types, or
|
||||
/// <exception cref="InvalidOperationException">the resolver does not support removing types, or
|
||||
/// the type is not a valid type for the resolver.</exception>
|
||||
public virtual void RemoveType(Type value)
|
||||
{
|
||||
@@ -296,7 +301,7 @@ namespace Umbraco.Core.ObjectResolution
|
||||
/// Removes a type.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">The type to remove.</typeparam>
|
||||
/// <exception cref="InvalidOperationException">the resolver does not support removing types, or
|
||||
/// <exception cref="InvalidOperationException">the resolver does not support removing types, or
|
||||
/// the type is not a valid type for the resolver.</exception>
|
||||
public void RemoveType<T>()
|
||||
where T : TResolved
|
||||
@@ -309,7 +314,7 @@ namespace Umbraco.Core.ObjectResolution
|
||||
/// </summary>
|
||||
/// <param name="types">The types to add.</param>
|
||||
/// <remarks>The types are appended at the end of the list.</remarks>
|
||||
/// <exception cref="InvalidOperationException">the resolver does not support adding types, or
|
||||
/// <exception cref="InvalidOperationException">the resolver does not support adding types, or
|
||||
/// a type is not a valid type for the resolver, or a type is already in the collection of types.</exception>
|
||||
protected void AddTypes(IEnumerable<Type> types)
|
||||
{
|
||||
@@ -336,7 +341,7 @@ namespace Umbraco.Core.ObjectResolution
|
||||
/// </summary>
|
||||
/// <param name="value">The type to add.</param>
|
||||
/// <remarks>The type is appended at the end of the list.</remarks>
|
||||
/// <exception cref="InvalidOperationException">the resolver does not support adding types, or
|
||||
/// <exception cref="InvalidOperationException">the resolver does not support adding types, or
|
||||
/// the type is not a valid type for the resolver, or the type is already in the collection of types.</exception>
|
||||
public virtual void AddType(Type value)
|
||||
{
|
||||
@@ -362,7 +367,7 @@ namespace Umbraco.Core.ObjectResolution
|
||||
/// </summary>
|
||||
/// <typeparam name="T">The type to add.</typeparam>
|
||||
/// <remarks>The type is appended at the end of the list.</remarks>
|
||||
/// <exception cref="InvalidOperationException">the resolver does not support adding types, or
|
||||
/// <exception cref="InvalidOperationException">the resolver does not support adding types, or
|
||||
/// the type is not a valid type for the resolver, or the type is already in the collection of types.</exception>
|
||||
public void AddType<T>()
|
||||
where T : TResolved
|
||||
@@ -404,7 +409,7 @@ namespace Umbraco.Core.ObjectResolution
|
||||
/// </summary>
|
||||
/// <param name="index">The zero-based index at which the type should be inserted.</param>
|
||||
/// <param name="value">The type to insert.</param>
|
||||
/// <exception cref="InvalidOperationException">the resolver does not support inserting types, or
|
||||
/// <exception cref="InvalidOperationException">the resolver does not support inserting types, or
|
||||
/// the type is not a valid type for the resolver, or the type is already in the collection of types.</exception>
|
||||
/// <exception cref="ArgumentOutOfRangeException"><paramref name="index"/> is out of range.</exception>
|
||||
public virtual void InsertType(int index, Type value)
|
||||
@@ -430,7 +435,7 @@ namespace Umbraco.Core.ObjectResolution
|
||||
/// Inserts a type at the beginning of the list.
|
||||
/// </summary>
|
||||
/// <param name="value">The type to insert.</param>
|
||||
/// <exception cref="InvalidOperationException">the resolver does not support inserting types, or
|
||||
/// <exception cref="InvalidOperationException">the resolver does not support inserting types, or
|
||||
/// the type is not a valid type for the resolver, or the type is already in the collection of types.</exception>
|
||||
public virtual void InsertType(Type value)
|
||||
{
|
||||
@@ -464,7 +469,7 @@ namespace Umbraco.Core.ObjectResolution
|
||||
/// </summary>
|
||||
/// <param name="existingType">The existing type before which to insert.</param>
|
||||
/// <param name="value">The type to insert.</param>
|
||||
/// <exception cref="InvalidOperationException">the resolver does not support inserting types, or
|
||||
/// <exception cref="InvalidOperationException">the resolver does not support inserting types, or
|
||||
/// one of the types is not a valid type for the resolver, or the existing type is not in the collection,
|
||||
/// or the new type is already in the collection of types.</exception>
|
||||
public virtual void InsertTypeBefore(Type existingType, Type value)
|
||||
@@ -498,7 +503,7 @@ namespace Umbraco.Core.ObjectResolution
|
||||
/// </summary>
|
||||
/// <typeparam name="TExisting">The existing type before which to insert.</typeparam>
|
||||
/// <typeparam name="T">The type to insert.</typeparam>
|
||||
/// <exception cref="InvalidOperationException">the resolver does not support inserting types, or
|
||||
/// <exception cref="InvalidOperationException">the resolver does not support inserting types, or
|
||||
/// one of the types is not a valid type for the resolver, or the existing type is not in the collection,
|
||||
/// or the new type is already in the collection of types.</exception>
|
||||
public void InsertTypeBefore<TExisting, T>()
|
||||
|
||||
@@ -72,6 +72,9 @@ namespace Umbraco.Core.Persistence.Factories
|
||||
content.PublishedVersionGuid = publishedDto == null
|
||||
? (dto.DocumentPublishedReadOnlyDto == null ? default(Guid) : dto.DocumentPublishedReadOnlyDto.VersionId)
|
||||
: publishedDto.VersionId;
|
||||
content.PublishedDate = publishedDto == null
|
||||
? (dto.DocumentPublishedReadOnlyDto == null ? default(DateTime) : dto.DocumentPublishedReadOnlyDto.VersionDate)
|
||||
: publishedDto.VersionDate;
|
||||
|
||||
//on initial construction we don't want to have dirty properties tracked
|
||||
// http://issues.umbraco.org/issue/U4-1946
|
||||
|
||||
@@ -513,11 +513,13 @@ namespace Umbraco.Core.Persistence.Repositories
|
||||
dto.DocumentPublishedReadOnlyDto = new DocumentPublishedReadOnlyDto
|
||||
{
|
||||
VersionId = dto.VersionId,
|
||||
VersionDate = dto.UpdateDate,
|
||||
Newest = true,
|
||||
NodeId = dto.NodeId,
|
||||
Published = true
|
||||
Published = true
|
||||
};
|
||||
((Content)entity).PublishedVersionGuid = dto.VersionId;
|
||||
((Content) entity).PublishedVersionGuid = dto.VersionId;
|
||||
((Content) entity).PublishedDate = dto.UpdateDate;
|
||||
}
|
||||
|
||||
entity.ResetDirtyProperties();
|
||||
@@ -687,22 +689,26 @@ namespace Umbraco.Core.Persistence.Repositories
|
||||
dto.DocumentPublishedReadOnlyDto = new DocumentPublishedReadOnlyDto
|
||||
{
|
||||
VersionId = dto.VersionId,
|
||||
VersionDate = dto.UpdateDate,
|
||||
Newest = true,
|
||||
NodeId = dto.NodeId,
|
||||
Published = true
|
||||
};
|
||||
((Content)entity).PublishedVersionGuid = dto.VersionId;
|
||||
((Content) entity).PublishedVersionGuid = dto.VersionId;
|
||||
((Content) entity).PublishedDate = dto.UpdateDate;
|
||||
}
|
||||
else if (publishedStateChanged)
|
||||
{
|
||||
dto.DocumentPublishedReadOnlyDto = new DocumentPublishedReadOnlyDto
|
||||
{
|
||||
VersionId = default(Guid),
|
||||
VersionId = default (Guid),
|
||||
VersionDate = default (DateTime),
|
||||
Newest = false,
|
||||
NodeId = dto.NodeId,
|
||||
Published = false
|
||||
};
|
||||
((Content)entity).PublishedVersionGuid = default(Guid);
|
||||
((Content) entity).PublishedVersionGuid = default(Guid);
|
||||
((Content) entity).PublishedDate = default (DateTime);
|
||||
}
|
||||
|
||||
entity.ResetDirtyProperties();
|
||||
@@ -974,7 +980,7 @@ order by umbracoNode.{2}, umbracoNode.parentID, umbracoNode.sortOrder",
|
||||
}
|
||||
|
||||
//order by update date DESC, if there is corrupted published flags we only want the latest!
|
||||
var publishedSql = new Sql(@"SELECT cmsDocument.nodeId, cmsDocument.published, cmsDocument.versionId, cmsDocument.newest
|
||||
var publishedSql = new Sql(@"SELECT cmsDocument.nodeId, cmsDocument.published, cmsDocument.versionId, cmsDocument.updateDate, cmsDocument.newest
|
||||
FROM cmsDocument INNER JOIN cmsContentVersion ON cmsContentVersion.VersionId = cmsDocument.versionId
|
||||
WHERE cmsDocument.published = 1 AND cmsDocument.nodeId IN
|
||||
(" + parsedOriginalSql + @")
|
||||
|
||||
@@ -1250,5 +1250,19 @@ WHERE cmsContentType." + aliasColumn + @" LIKE @pattern",
|
||||
while (aliases.Contains(test = alias + i)) i++;
|
||||
return test;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Given the path of a content item, this will return true if the content item exists underneath a list view content item
|
||||
/// </summary>
|
||||
/// <param name="contentPath"></param>
|
||||
/// <returns></returns>
|
||||
public bool HasContainerInPath(string contentPath)
|
||||
{
|
||||
var ids = contentPath.Split(',').Select(int.Parse);
|
||||
var sql = new Sql(@"SELECT COUNT(*) FROM cmsContentType
|
||||
INNER JOIN cmsContent ON cmsContentType.nodeId=cmsContent.contentType
|
||||
WHERE cmsContent.nodeId IN (@ids) AND cmsContentType.isContainer=@isContainer", new { ids, isContainer = true });
|
||||
return Database.ExecuteScalar<int>(sql) > 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -34,7 +34,7 @@ namespace Umbraco.Core.Persistence.Repositories
|
||||
: base(work, cache, logger, sqlSyntax)
|
||||
{
|
||||
_contentTypeRepository = contentTypeRepository;
|
||||
_preValRepository = new DataTypePreValueRepository(work, CacheHelper.CreateDisabledCacheHelper(), logger, sqlSyntax);
|
||||
_preValRepository = new DataTypePreValueRepository(work, CacheHelper.CreateDisabledCacheHelper(), logger, sqlSyntax);
|
||||
}
|
||||
|
||||
#region Overrides of RepositoryBase<int,DataTypeDefinition>
|
||||
@@ -276,47 +276,33 @@ AND umbracoNode.id <> @id",
|
||||
|
||||
public PreValueCollection GetPreValuesCollectionByDataTypeId(int dataTypeId)
|
||||
{
|
||||
var cached = RuntimeCache.GetCacheItemsByKeySearch<PreValueCollection>(GetPrefixedCacheKey(dataTypeId));
|
||||
if (cached != null && cached.Any())
|
||||
{
|
||||
//return from the cache, ensure it's a cloned result
|
||||
return (PreValueCollection)cached.First().DeepClone();
|
||||
}
|
||||
|
||||
return GetAndCachePreValueCollection(dataTypeId);
|
||||
}
|
||||
|
||||
internal static string GetCacheKeyRegex(int preValueId)
|
||||
{
|
||||
return CacheKeys.DataTypePreValuesCacheKey + @"[-\d]+-([\d]*,)*" + preValueId + @"(?!\d)[,\d$]*";
|
||||
var collection = GetCachedPreValueCollection(dataTypeId);
|
||||
return collection;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets a specific PreValue by its Id
|
||||
/// </summary>
|
||||
/// <param name="preValueId">Id of the PreValue to retrieve the value from</param>
|
||||
/// <returns>PreValue as a string</returns>
|
||||
public string GetPreValueAsString(int preValueId)
|
||||
{
|
||||
//We need to see if we can find the cached PreValueCollection based on the cache key above
|
||||
var collections = RuntimeCache.GetCacheItemsByKeySearch<PreValueCollection>(CacheKeys.DataTypePreValuesCacheKey + "_");
|
||||
|
||||
var cached = RuntimeCache.GetCacheItemsByKeyExpression<PreValueCollection>(GetCacheKeyRegex(preValueId));
|
||||
if (cached != null && cached.Any())
|
||||
{
|
||||
//return from the cache
|
||||
var collection = cached.First();
|
||||
var preVal = collection.FormatAsDictionary().Single(x => x.Value.Id == preValueId);
|
||||
return preVal.Value.Value;
|
||||
}
|
||||
var preValue = collections.SelectMany(x => x.FormatAsDictionary().Values).FirstOrDefault(x => x.Id == preValueId);
|
||||
if (preValue != null)
|
||||
return preValue.Value;
|
||||
|
||||
//go and find the data type id for the pre val id passed in
|
||||
|
||||
var dto = Database.FirstOrDefault<DataTypePreValueDto>("WHERE id = @preValueId", new { preValueId = preValueId });
|
||||
var dto = Database.FirstOrDefault<DataTypePreValueDto>("WHERE id = @preValueId", new { preValueId });
|
||||
if (dto == null)
|
||||
{
|
||||
return string.Empty;
|
||||
}
|
||||
// go cache the collection
|
||||
var preVals = GetAndCachePreValueCollection(dto.DataTypeNodeId);
|
||||
|
||||
//return the single value for this id
|
||||
var pv = preVals.FormatAsDictionary().Single(x => x.Value.Id == preValueId);
|
||||
return pv.Value.Value;
|
||||
var collection = GetCachedPreValueCollection(dto.DataTypeNodeId);
|
||||
if (collection == null)
|
||||
return string.Empty;
|
||||
|
||||
preValue = collection.FormatAsDictionary().Values.FirstOrDefault(x => x.Id == preValueId);
|
||||
return preValue == null ? string.Empty : preValue.Value;
|
||||
}
|
||||
|
||||
public void AddOrUpdatePreValues(int dataTypeId, IDictionary<string, PreValue> values)
|
||||
@@ -441,40 +427,28 @@ AND umbracoNode.id <> @id",
|
||||
|
||||
sortOrder++;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private string GetPrefixedCacheKey(int dataTypeId)
|
||||
private static string GetPrefixedCacheKey(int dataTypeId)
|
||||
{
|
||||
return CacheKeys.DataTypePreValuesCacheKey + dataTypeId + "-";
|
||||
return CacheKeys.DataTypePreValuesCacheKey + "_" + dataTypeId;
|
||||
}
|
||||
|
||||
private PreValueCollection GetAndCachePreValueCollection(int dataTypeId)
|
||||
private PreValueCollection GetCachedPreValueCollection(int datetypeId)
|
||||
{
|
||||
//go get the data
|
||||
var dtos = Database.Fetch<DataTypePreValueDto>("WHERE datatypeNodeId = @Id", new { Id = dataTypeId });
|
||||
var list = dtos.Select(x => new Tuple<PreValue, string, int>(new PreValue(x.Id, x.Value, x.SortOrder), x.Alias, x.SortOrder)).ToList();
|
||||
var collection = PreValueConverter.ConvertToPreValuesCollection(list);
|
||||
|
||||
//now create the cache key, this needs to include all pre-value ids so that we can use this cached item in the GetPreValuesAsString method
|
||||
//the key will be: "UmbracoPreValDATATYPEID-CSVOFPREVALIDS
|
||||
|
||||
var key = GetPrefixedCacheKey(dataTypeId)
|
||||
+ string.Join(",", collection.FormatAsDictionary().Select(x => x.Value.Id).ToArray());
|
||||
|
||||
//store into cache
|
||||
RuntimeCache.InsertCacheItem(key, () => collection,
|
||||
//30 mins
|
||||
new TimeSpan(0, 0, 30),
|
||||
//sliding is true
|
||||
true);
|
||||
|
||||
return collection;
|
||||
var key = GetPrefixedCacheKey(datetypeId);
|
||||
return RuntimeCache.GetCacheItem<PreValueCollection>(key, () =>
|
||||
{
|
||||
var dtos = Database.Fetch<DataTypePreValueDto>("WHERE datatypeNodeId = @Id", new { Id = datetypeId });
|
||||
var list = dtos.Select(x => new Tuple<PreValue, string, int>(new PreValue(x.Id, x.Value, x.SortOrder), x.Alias, x.SortOrder)).ToList();
|
||||
var collection = PreValueConverter.ConvertToPreValuesCollection(list);
|
||||
return collection;
|
||||
}, TimeSpan.FromMinutes(20), isSliding: true);
|
||||
}
|
||||
|
||||
private string EnsureUniqueNodeName(string nodeName, int id = 0)
|
||||
{
|
||||
|
||||
|
||||
|
||||
var sql = new Sql();
|
||||
sql.Select("*")
|
||||
@@ -576,7 +550,7 @@ AND umbracoNode.id <> @id",
|
||||
}
|
||||
|
||||
//NOTE: We used to check that the Alias was unique for the given DataTypeNodeId prevalues list, BUT
|
||||
// in reality there is no need to check the uniqueness of this alias because the only way that this code executes is
|
||||
// in reality there is no need to check the uniqueness of this alias because the only way that this code executes is
|
||||
// based on an IDictionary<string, PreValue> dictionary being passed to this repository and a dictionary
|
||||
// must have unique aliases by definition, so there is no need for this additional check
|
||||
|
||||
@@ -596,10 +570,10 @@ AND umbracoNode.id <> @id",
|
||||
{
|
||||
throw new InvalidOperationException("Cannot update a pre value for a data type that has no identity");
|
||||
}
|
||||
|
||||
|
||||
//NOTE: We used to check that the Alias was unique for the given DataTypeNodeId prevalues list, BUT
|
||||
// this causes issues when sorting the pre-values (http://issues.umbraco.org/issue/U4-5670) but in reality
|
||||
// there is no need to check the uniqueness of this alias because the only way that this code executes is
|
||||
// there is no need to check the uniqueness of this alias because the only way that this code executes is
|
||||
// based on an IDictionary<string, PreValue> dictionary being passed to this repository and a dictionary
|
||||
// must have unique aliases by definition, so there is no need for this additional check
|
||||
|
||||
@@ -614,7 +588,7 @@ AND umbracoNode.id <> @id",
|
||||
Database.Update(dto);
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
internal static class PreValueConverter
|
||||
|
||||
@@ -8,6 +8,13 @@ namespace Umbraco.Core.Persistence.Repositories
|
||||
{
|
||||
public interface IContentTypeRepository : IContentTypeCompositionRepository<IContentType>
|
||||
{
|
||||
/// <summary>
|
||||
/// Given the path of a content item, this will return true if the content item exists underneath a list view content item
|
||||
/// </summary>
|
||||
/// <param name="contentPath"></param>
|
||||
/// <returns></returns>
|
||||
bool HasContainerInPath(string contentPath);
|
||||
|
||||
/// <summary>
|
||||
/// Gets all entities of the specified <see cref="PropertyType"/> query
|
||||
/// </summary>
|
||||
|
||||
@@ -48,7 +48,12 @@ namespace Umbraco.Core.Persistence
|
||||
_cacheHelper.IsolatedRuntimeCache.CacheFactory = type =>
|
||||
{
|
||||
var cache = origFactory(type);
|
||||
return new DeepCloneRuntimeCacheProvider(cache);
|
||||
|
||||
//if the result is already a DeepCloneRuntimeCacheProvider then return it, otherwise
|
||||
//wrap the result with a DeepCloneRuntimeCacheProvider
|
||||
return cache is DeepCloneRuntimeCacheProvider
|
||||
? cache
|
||||
: new DeepCloneRuntimeCacheProvider(cache);
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Umbraco.Core.Events;
|
||||
using Umbraco.Core.Models;
|
||||
using Umbraco.Core.Services;
|
||||
@@ -12,7 +13,8 @@ namespace Umbraco.Core.Publishing
|
||||
{
|
||||
public PublishStatus(IContent content, PublishStatusType statusType, EventMessages eventMessages)
|
||||
: base(content, statusType, eventMessages)
|
||||
{
|
||||
{
|
||||
InvalidProperties = Enumerable.Empty<Property>();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -20,8 +22,7 @@ namespace Umbraco.Core.Publishing
|
||||
/// </summary>
|
||||
public PublishStatus(IContent content, EventMessages eventMessages)
|
||||
: this(content, PublishStatusType.Success, eventMessages)
|
||||
{
|
||||
}
|
||||
{ }
|
||||
|
||||
public IContent ContentItem
|
||||
{
|
||||
|
||||
@@ -30,7 +30,7 @@ namespace Umbraco.Core.Publishing
|
||||
/// Publishes a single piece of Content
|
||||
/// </summary>
|
||||
/// <param name="content"><see cref="IContent"/> to publish</param>
|
||||
/// <param name="userId">Id of the User issueing the publish operation</param>
|
||||
/// <param name="userId">Id of the User issueing the publish operation</param>
|
||||
internal Attempt<PublishStatus> PublishInternal(IContent content, int userId)
|
||||
{
|
||||
var evtMsgs = _eventMessagesFactory.Get();
|
||||
@@ -99,26 +99,26 @@ namespace Umbraco.Core.Publishing
|
||||
/// By default this is set to true which means that it will publish any content item in the list that is completely unpublished and
|
||||
/// not visible on the front-end. If set to false, this will only publish content that is live on the front-end but has new versions
|
||||
/// that have yet to be published.
|
||||
/// </param>
|
||||
/// </param>
|
||||
/// <returns></returns>
|
||||
/// <remarks>
|
||||
///
|
||||
///
|
||||
/// This method becomes complex once we start to be able to cancel events or stop publishing a content item in any way because if a
|
||||
/// content item is not published then it's children shouldn't be published either. This rule will apply for the following conditions:
|
||||
/// * If a document fails to be published, do not proceed to publish it's children if:
|
||||
/// ** The document does not have a publish version
|
||||
/// ** The document does have a published version but the includeUnpublishedDocuments = false
|
||||
///
|
||||
///
|
||||
/// In order to do this, we will order the content by level and begin by publishing each item at that level, then proceed to the next
|
||||
/// level and so on. If we detect that the above rule applies when the document publishing is cancelled we'll add it to the list of
|
||||
/// level and so on. If we detect that the above rule applies when the document publishing is cancelled we'll add it to the list of
|
||||
/// parentsIdsCancelled so that it's children don't get published.
|
||||
///
|
||||
///
|
||||
/// Its important to note that all 'root' documents included in the list *will* be published regardless of the rules mentioned
|
||||
/// above (unless it is invalid)!! By 'root' documents we are referring to documents in the list with the minimum value for their 'level'.
|
||||
/// In most cases the 'root' documents will only be one document since under normal circumstance we only publish one document and
|
||||
/// above (unless it is invalid)!! By 'root' documents we are referring to documents in the list with the minimum value for their 'level'.
|
||||
/// In most cases the 'root' documents will only be one document since under normal circumstance we only publish one document and
|
||||
/// its children. The reason we have to do this is because if a user is publishing a document and it's children, it is implied that
|
||||
/// the user definitely wants to publish it even if it has never been published before.
|
||||
///
|
||||
///
|
||||
/// </remarks>
|
||||
internal IEnumerable<Attempt<PublishStatus>> PublishWithChildrenInternal(
|
||||
IEnumerable<IContent> content, int userId, bool includeUnpublishedDocuments = true)
|
||||
@@ -132,7 +132,7 @@ namespace Umbraco.Core.Publishing
|
||||
|
||||
//group by levels and iterate over the sorted ascending level.
|
||||
//TODO: This will cause all queries to execute, they will not be lazy but I'm not really sure being lazy actually made
|
||||
// much difference because we iterate over them all anyways?? Morten?
|
||||
// much difference because we iterate over them all anyways?? Morten?
|
||||
// Because we're grouping I think this will execute all the queries anyways so need to fetch it all first.
|
||||
var fetchedContent = content.ToArray();
|
||||
|
||||
@@ -149,7 +149,7 @@ namespace Umbraco.Core.Publishing
|
||||
var levelGroups = fetchedContent.GroupBy(x => x.Level);
|
||||
foreach (var level in levelGroups.OrderBy(x => x.Key))
|
||||
{
|
||||
//set the first level flag, used to ensure that all documents at the first level will
|
||||
//set the first level flag, used to ensure that all documents at the first level will
|
||||
//be published regardless of the rules mentioned in the remarks.
|
||||
if (!firstLevel.HasValue)
|
||||
{
|
||||
@@ -200,7 +200,10 @@ namespace Umbraco.Core.Publishing
|
||||
_logger.Info<PublishingStrategy>(
|
||||
string.Format("Content '{0}' with Id '{1}' will not be published because some of it's content is not passing validation rules.",
|
||||
item.Name, item.Id));
|
||||
statuses.Add(Attempt.Fail(new PublishStatus(item, PublishStatusType.FailedContentInvalid, evtMsgs)));
|
||||
statuses.Add(Attempt.Fail(new PublishStatus(item, PublishStatusType.FailedContentInvalid, evtMsgs)
|
||||
{
|
||||
InvalidProperties = ((ContentBase)item).LastInvalidProperties
|
||||
}));
|
||||
|
||||
//Does this document apply to our rule to cancel it's children being published?
|
||||
CheckCancellingOfChildPublishing(item, parentsIdsCancelled, includeUnpublishedDocuments);
|
||||
@@ -272,11 +275,11 @@ namespace Umbraco.Core.Publishing
|
||||
/// <param name="includeUnpublishedDocuments"></param>
|
||||
/// <remarks>
|
||||
/// See remarks on method: PublishWithChildrenInternal
|
||||
/// </remarks>
|
||||
/// </remarks>
|
||||
private void CheckCancellingOfChildPublishing(IContent content, List<int> parentsIdsCancelled, bool includeUnpublishedDocuments)
|
||||
{
|
||||
//Does this document apply to our rule to cancel it's children being published?
|
||||
//TODO: We're going back to the service layer here... not sure how to avoid this? And this will add extra overhead to
|
||||
//TODO: We're going back to the service layer here... not sure how to avoid this? And this will add extra overhead to
|
||||
// any document that fails to publish...
|
||||
var hasPublishedVersion = ApplicationContext.Current.Services.ContentService.HasPublishedVersion(content.Id);
|
||||
|
||||
@@ -306,8 +309,8 @@ namespace Umbraco.Core.Publishing
|
||||
//NOTE: This previously always returned true so I've left it that way. It returned true because (from Morten)...
|
||||
// ... if one item couldn't be published it wouldn't be correct to return false.
|
||||
// in retrospect it should have returned a list of with Ids and Publish Status
|
||||
// come to think of it ... the cache would still be updated for a failed item or at least tried updated.
|
||||
// It would call the Published event for the entire list, but if the Published property isn't set to True it
|
||||
// come to think of it ... the cache would still be updated for a failed item or at least tried updated.
|
||||
// It would call the Published event for the entire list, but if the Published property isn't set to True it
|
||||
// wouldn't actually update the cache for that item. But not really ideal nevertheless...
|
||||
return true;
|
||||
}
|
||||
@@ -345,7 +348,7 @@ namespace Umbraco.Core.Publishing
|
||||
var evtMsgs = _eventMessagesFactory.Get();
|
||||
|
||||
//Fire UnPublishing event
|
||||
if (UnPublishing.IsRaisedEventCancelled(
|
||||
if (UnPublishing.IsRaisedEventCancelled(
|
||||
new PublishEventArgs<IContent>(content, evtMsgs), this))
|
||||
{
|
||||
_logger.Info<PublishingStrategy>(
|
||||
@@ -388,8 +391,8 @@ namespace Umbraco.Core.Publishing
|
||||
//NOTE: This previously always returned true so I've left it that way. It returned true because (from Morten)...
|
||||
// ... if one item couldn't be published it wouldn't be correct to return false.
|
||||
// in retrospect it should have returned a list of with Ids and Publish Status
|
||||
// come to think of it ... the cache would still be updated for a failed item or at least tried updated.
|
||||
// It would call the Published event for the entire list, but if the Published property isn't set to True it
|
||||
// come to think of it ... the cache would still be updated for a failed item or at least tried updated.
|
||||
// It would call the Published event for the entire list, but if the Published property isn't set to True it
|
||||
// wouldn't actually update the cache for that item. But not really ideal nevertheless...
|
||||
return true;
|
||||
}
|
||||
@@ -405,7 +408,7 @@ namespace Umbraco.Core.Publishing
|
||||
public override void PublishingFinalized(IContent content)
|
||||
{
|
||||
var evtMsgs = _eventMessagesFactory.Get();
|
||||
Published.RaiseEvent(
|
||||
Published.RaiseEvent(
|
||||
new PublishEventArgs<IContent>(content, false, false, evtMsgs), this);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,22 +1,15 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Data;
|
||||
using System.Diagnostics;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Xml.Linq;
|
||||
using System.Threading;
|
||||
using AutoMapper;
|
||||
using Umbraco.Core.Auditing;
|
||||
using Umbraco.Core.Configuration;
|
||||
using Umbraco.Core.Events;
|
||||
using Umbraco.Core.Exceptions;
|
||||
using Umbraco.Core.Logging;
|
||||
using Umbraco.Core.Models;
|
||||
using Umbraco.Core.Models.Rdbms;
|
||||
using Umbraco.Core.Persistence;
|
||||
using Umbraco.Core.Persistence.Querying;
|
||||
using Umbraco.Core.Persistence.Repositories;
|
||||
using Umbraco.Core.Persistence.UnitOfWork;
|
||||
|
||||
namespace Umbraco.Core.Services
|
||||
@@ -26,14 +19,15 @@ namespace Umbraco.Core.Services
|
||||
/// </summary>
|
||||
public class ContentTypeService : ContentTypeServiceBase, IContentTypeService
|
||||
{
|
||||
private readonly IContentService _contentService;
|
||||
private readonly IContentService _contentService;
|
||||
private readonly IMediaService _mediaService;
|
||||
|
||||
//Support recursive locks because some of the methods that require locking call other methods that require locking.
|
||||
//for example, the Move method needs to be locked but this calls the Save method which also needs to be locked.
|
||||
private static readonly ReaderWriterLockSlim Locker = new ReaderWriterLockSlim(LockRecursionPolicy.SupportsRecursion);
|
||||
|
||||
public ContentTypeService(IDatabaseUnitOfWorkProvider provider, RepositoryFactory repositoryFactory, ILogger logger, IEventMessagesFactory eventMessagesFactory, IContentService contentService, IMediaService mediaService)
|
||||
public ContentTypeService(IDatabaseUnitOfWorkProvider provider, RepositoryFactory repositoryFactory, ILogger logger, IEventMessagesFactory eventMessagesFactory, IContentService contentService,
|
||||
IMediaService mediaService)
|
||||
: base(provider, repositoryFactory, logger, eventMessagesFactory)
|
||||
{
|
||||
if (contentService == null) throw new ArgumentNullException("contentService");
|
||||
@@ -154,8 +148,8 @@ namespace Umbraco.Core.Services
|
||||
}
|
||||
|
||||
if (savingEvent.IsRaisedEventCancelled(
|
||||
new SaveEventArgs<EntityContainer>(container, evtMsgs),
|
||||
this))
|
||||
new SaveEventArgs<EntityContainer>(container, evtMsgs),
|
||||
this))
|
||||
{
|
||||
return OperationStatus.Cancelled(evtMsgs);
|
||||
}
|
||||
@@ -214,7 +208,7 @@ namespace Umbraco.Core.Services
|
||||
|
||||
public IEnumerable<EntityContainer> GetMediaTypeContainers(IMediaType mediaType)
|
||||
{
|
||||
var ancestorIds = mediaType.Path.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries)
|
||||
var ancestorIds = mediaType.Path.Split(new[] {','}, StringSplitOptions.RemoveEmptyEntries)
|
||||
.Select(x =>
|
||||
{
|
||||
var asInt = x.TryConvertTo<int>();
|
||||
@@ -290,8 +284,8 @@ namespace Umbraco.Core.Services
|
||||
if (container == null) return OperationStatus.NoOperation(evtMsgs);
|
||||
|
||||
if (DeletingContentTypeContainer.IsRaisedEventCancelled(
|
||||
new DeleteEventArgs<EntityContainer>(container, evtMsgs),
|
||||
this))
|
||||
new DeleteEventArgs<EntityContainer>(container, evtMsgs),
|
||||
this))
|
||||
{
|
||||
return Attempt.Fail(new OperationStatus(OperationStatusType.FailedCancelledByEvent, evtMsgs));
|
||||
}
|
||||
@@ -316,8 +310,8 @@ namespace Umbraco.Core.Services
|
||||
if (container == null) return OperationStatus.NoOperation(evtMsgs);
|
||||
|
||||
if (DeletingMediaTypeContainer.IsRaisedEventCancelled(
|
||||
new DeleteEventArgs<EntityContainer>(container, evtMsgs),
|
||||
this))
|
||||
new DeleteEventArgs<EntityContainer>(container, evtMsgs),
|
||||
this))
|
||||
{
|
||||
return Attempt.Fail(new OperationStatus(OperationStatusType.FailedCancelledByEvent, evtMsgs));
|
||||
}
|
||||
@@ -421,7 +415,7 @@ namespace Umbraco.Core.Services
|
||||
|
||||
clone.Name = name;
|
||||
|
||||
var compositionAliases = clone.CompositionAliases().Except(new[] { alias }).ToList();
|
||||
var compositionAliases = clone.CompositionAliases().Except(new[] {alias}).ToList();
|
||||
//remove all composition that is not it's current alias
|
||||
foreach (var a in compositionAliases)
|
||||
{
|
||||
@@ -680,7 +674,7 @@ namespace Umbraco.Core.Services
|
||||
var comparer = new DelegateEqualityComparer<IContentTypeComposition>((x, y) => x.Id == y.Id, x => x.Id);
|
||||
var dependencies = new HashSet<IContentTypeComposition>(compositions, comparer);
|
||||
var stack = new Stack<IContentTypeComposition>();
|
||||
indirectReferences.ForEach(stack.Push);//Push indirect references to a stack, so we can add recursively
|
||||
indirectReferences.ForEach(stack.Push); //Push indirect references to a stack, so we can add recursively
|
||||
while (stack.Count > 0)
|
||||
{
|
||||
var indirectReference = stack.Pop();
|
||||
@@ -734,6 +728,8 @@ namespace Umbraco.Core.Services
|
||||
{
|
||||
ValidateLocked(contentType); // throws if invalid
|
||||
contentType.CreatorId = userId;
|
||||
if (contentType.Description == string.Empty)
|
||||
contentType.Description = null;
|
||||
repository.AddOrUpdate(contentType);
|
||||
|
||||
uow.Commit();
|
||||
@@ -742,7 +738,7 @@ namespace Umbraco.Core.Services
|
||||
UpdateContentXmlStructure(contentType);
|
||||
}
|
||||
SavedContentType.RaiseEvent(new SaveEventArgs<IContentType>(contentType, false), this);
|
||||
Audit(AuditType.Save, string.Format("Save ContentType performed by user"), userId, contentType.Id);
|
||||
Audit(AuditType.Save, string.Format("Save ContentType performed by user"), userId, contentType.Id);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -755,7 +751,7 @@ namespace Umbraco.Core.Services
|
||||
var asArray = contentTypes.ToArray();
|
||||
|
||||
if (SavingContentType.IsRaisedEventCancelled(new SaveEventArgs<IContentType>(asArray), this))
|
||||
return;
|
||||
return;
|
||||
|
||||
using (new WriteLock(Locker))
|
||||
{
|
||||
@@ -770,6 +766,8 @@ namespace Umbraco.Core.Services
|
||||
foreach (var contentType in asArray)
|
||||
{
|
||||
contentType.CreatorId = userId;
|
||||
if (contentType.Description == string.Empty)
|
||||
contentType.Description = null;
|
||||
repository.AddOrUpdate(contentType);
|
||||
}
|
||||
|
||||
@@ -780,7 +778,7 @@ namespace Umbraco.Core.Services
|
||||
UpdateContentXmlStructure(asArray.Cast<IContentTypeBase>().ToArray());
|
||||
}
|
||||
SavedContentType.RaiseEvent(new SaveEventArgs<IContentType>(asArray, false), this);
|
||||
Audit(AuditType.Save, string.Format("Save ContentTypes performed by user"), userId, -1);
|
||||
Audit(AuditType.Save, string.Format("Save ContentTypes performed by user"), userId, -1);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -791,8 +789,8 @@ namespace Umbraco.Core.Services
|
||||
/// <remarks>Deleting a <see cref="IContentType"/> will delete all the <see cref="IContent"/> objects based on this <see cref="IContentType"/></remarks>
|
||||
public void Delete(IContentType contentType, int userId = 0)
|
||||
{
|
||||
if (DeletingContentType.IsRaisedEventCancelled(new DeleteEventArgs<IContentType>(contentType), this))
|
||||
return;
|
||||
if (DeletingContentType.IsRaisedEventCancelled(new DeleteEventArgs<IContentType>(contentType), this))
|
||||
return;
|
||||
|
||||
using (new WriteLock(Locker))
|
||||
{
|
||||
@@ -836,7 +834,7 @@ namespace Umbraco.Core.Services
|
||||
var asArray = contentTypes.ToArray();
|
||||
|
||||
if (DeletingContentType.IsRaisedEventCancelled(new DeleteEventArgs<IContentType>(asArray), this))
|
||||
return;
|
||||
return;
|
||||
|
||||
using (new WriteLock(Locker))
|
||||
{
|
||||
@@ -1004,8 +1002,8 @@ namespace Umbraco.Core.Services
|
||||
var evtMsgs = EventMessagesFactory.Get();
|
||||
|
||||
if (MovingMediaType.IsRaisedEventCancelled(
|
||||
new MoveEventArgs<IMediaType>(evtMsgs, new MoveEventInfo<IMediaType>(toMove, toMove.Path, containerId)),
|
||||
this))
|
||||
new MoveEventArgs<IMediaType>(evtMsgs, new MoveEventInfo<IMediaType>(toMove, toMove.Path, containerId)),
|
||||
this))
|
||||
{
|
||||
return Attempt.Fail(
|
||||
new OperationStatus<MoveOperationStatusType>(
|
||||
@@ -1047,8 +1045,8 @@ namespace Umbraco.Core.Services
|
||||
var evtMsgs = EventMessagesFactory.Get();
|
||||
|
||||
if (MovingContentType.IsRaisedEventCancelled(
|
||||
new MoveEventArgs<IContentType>(evtMsgs, new MoveEventInfo<IContentType>(toMove, toMove.Path, containerId)),
|
||||
this))
|
||||
new MoveEventArgs<IContentType>(evtMsgs, new MoveEventInfo<IContentType>(toMove, toMove.Path, containerId)),
|
||||
this))
|
||||
{
|
||||
return Attempt.Fail(
|
||||
new OperationStatus<MoveOperationStatusType>(
|
||||
@@ -1178,8 +1176,8 @@ namespace Umbraco.Core.Services
|
||||
/// <param name="userId">Optional Id of the user saving the MediaType</param>
|
||||
public void Save(IMediaType mediaType, int userId = 0)
|
||||
{
|
||||
if (SavingMediaType.IsRaisedEventCancelled(new SaveEventArgs<IMediaType>(mediaType), this))
|
||||
return;
|
||||
if (SavingMediaType.IsRaisedEventCancelled(new SaveEventArgs<IMediaType>(mediaType), this))
|
||||
return;
|
||||
|
||||
using (new WriteLock(Locker))
|
||||
{
|
||||
@@ -1188,6 +1186,8 @@ namespace Umbraco.Core.Services
|
||||
{
|
||||
ValidateLocked(mediaType); // throws if invalid
|
||||
mediaType.CreatorId = userId;
|
||||
if (mediaType.Description == string.Empty)
|
||||
mediaType.Description = null;
|
||||
repository.AddOrUpdate(mediaType);
|
||||
uow.Commit();
|
||||
|
||||
@@ -1197,7 +1197,7 @@ namespace Umbraco.Core.Services
|
||||
}
|
||||
|
||||
SavedMediaType.RaiseEvent(new SaveEventArgs<IMediaType>(mediaType, false), this);
|
||||
Audit(AuditType.Save, string.Format("Save MediaType performed by user"), userId, mediaType.Id);
|
||||
Audit(AuditType.Save, string.Format("Save MediaType performed by user"), userId, mediaType.Id);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -1210,7 +1210,7 @@ namespace Umbraco.Core.Services
|
||||
var asArray = mediaTypes.ToArray();
|
||||
|
||||
if (SavingMediaType.IsRaisedEventCancelled(new SaveEventArgs<IMediaType>(asArray), this))
|
||||
return;
|
||||
return;
|
||||
|
||||
using (new WriteLock(Locker))
|
||||
{
|
||||
@@ -1225,6 +1225,8 @@ namespace Umbraco.Core.Services
|
||||
foreach (var mediaType in asArray)
|
||||
{
|
||||
mediaType.CreatorId = userId;
|
||||
if (mediaType.Description == string.Empty)
|
||||
mediaType.Description = null;
|
||||
repository.AddOrUpdate(mediaType);
|
||||
}
|
||||
|
||||
@@ -1236,7 +1238,7 @@ namespace Umbraco.Core.Services
|
||||
}
|
||||
|
||||
SavedMediaType.RaiseEvent(new SaveEventArgs<IMediaType>(asArray, false), this);
|
||||
Audit(AuditType.Save, string.Format("Save MediaTypes performed by user"), userId, -1);
|
||||
Audit(AuditType.Save, string.Format("Save MediaTypes performed by user"), userId, -1);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -1247,8 +1249,8 @@ namespace Umbraco.Core.Services
|
||||
/// <remarks>Deleting a <see cref="IMediaType"/> will delete all the <see cref="IMedia"/> objects based on this <see cref="IMediaType"/></remarks>
|
||||
public void Delete(IMediaType mediaType, int userId = 0)
|
||||
{
|
||||
if (DeletingMediaType.IsRaisedEventCancelled(new DeleteEventArgs<IMediaType>(mediaType), this))
|
||||
return;
|
||||
if (DeletingMediaType.IsRaisedEventCancelled(new DeleteEventArgs<IMediaType>(mediaType), this))
|
||||
return;
|
||||
using (new WriteLock(Locker))
|
||||
{
|
||||
_mediaService.DeleteMediaOfType(mediaType.Id, userId);
|
||||
@@ -1280,7 +1282,7 @@ namespace Umbraco.Core.Services
|
||||
var asArray = mediaTypes.ToArray();
|
||||
|
||||
if (DeletingMediaType.IsRaisedEventCancelled(new DeleteEventArgs<IMediaType>(asArray), this))
|
||||
return;
|
||||
return;
|
||||
using (new WriteLock(Locker))
|
||||
{
|
||||
foreach (var mediaType in asArray)
|
||||
@@ -1390,40 +1392,40 @@ namespace Umbraco.Core.Services
|
||||
/// </summary>
|
||||
public static event TypedEventHandler<IContentTypeService, DeleteEventArgs<IContentType>> DeletingContentType;
|
||||
|
||||
/// <summary>
|
||||
/// Occurs after Delete
|
||||
/// </summary>
|
||||
public static event TypedEventHandler<IContentTypeService, DeleteEventArgs<IContentType>> DeletedContentType;
|
||||
/// <summary>
|
||||
/// Occurs after Delete
|
||||
/// </summary>
|
||||
public static event TypedEventHandler<IContentTypeService, DeleteEventArgs<IContentType>> DeletedContentType;
|
||||
|
||||
/// <summary>
|
||||
/// Occurs before Delete
|
||||
/// </summary>
|
||||
public static event TypedEventHandler<IContentTypeService, DeleteEventArgs<IMediaType>> DeletingMediaType;
|
||||
/// <summary>
|
||||
/// Occurs before Delete
|
||||
/// </summary>
|
||||
public static event TypedEventHandler<IContentTypeService, DeleteEventArgs<IMediaType>> DeletingMediaType;
|
||||
|
||||
/// <summary>
|
||||
/// Occurs after Delete
|
||||
/// </summary>
|
||||
public static event TypedEventHandler<IContentTypeService, DeleteEventArgs<IMediaType>> DeletedMediaType;
|
||||
/// <summary>
|
||||
/// Occurs after Delete
|
||||
/// </summary>
|
||||
public static event TypedEventHandler<IContentTypeService, DeleteEventArgs<IMediaType>> DeletedMediaType;
|
||||
|
||||
/// <summary>
|
||||
/// Occurs before Save
|
||||
/// </summary>
|
||||
public static event TypedEventHandler<IContentTypeService, SaveEventArgs<IContentType>> SavingContentType;
|
||||
public static event TypedEventHandler<IContentTypeService, SaveEventArgs<IContentType>> SavingContentType;
|
||||
|
||||
/// <summary>
|
||||
/// Occurs after Save
|
||||
/// </summary>
|
||||
public static event TypedEventHandler<IContentTypeService, SaveEventArgs<IContentType>> SavedContentType;
|
||||
public static event TypedEventHandler<IContentTypeService, SaveEventArgs<IContentType>> SavedContentType;
|
||||
|
||||
/// <summary>
|
||||
/// Occurs before Save
|
||||
/// </summary>
|
||||
public static event TypedEventHandler<IContentTypeService, SaveEventArgs<IMediaType>> SavingMediaType;
|
||||
/// <summary>
|
||||
/// Occurs before Save
|
||||
/// </summary>
|
||||
public static event TypedEventHandler<IContentTypeService, SaveEventArgs<IMediaType>> SavingMediaType;
|
||||
|
||||
/// <summary>
|
||||
/// Occurs after Save
|
||||
/// </summary>
|
||||
public static event TypedEventHandler<IContentTypeService, SaveEventArgs<IMediaType>> SavedMediaType;
|
||||
/// <summary>
|
||||
/// Occurs after Save
|
||||
/// </summary>
|
||||
public static event TypedEventHandler<IContentTypeService, SaveEventArgs<IMediaType>> SavedMediaType;
|
||||
|
||||
/// <summary>
|
||||
/// Occurs before Move
|
||||
|
||||
@@ -5,6 +5,7 @@ using Umbraco.Core.Logging;
|
||||
using Umbraco.Core.Models;
|
||||
using Umbraco.Core.Models.EntityBase;
|
||||
using Umbraco.Core.Persistence;
|
||||
using Umbraco.Core.Persistence.Repositories;
|
||||
using Umbraco.Core.Persistence.UnitOfWork;
|
||||
|
||||
namespace Umbraco.Core.Services
|
||||
@@ -70,5 +71,20 @@ namespace Umbraco.Core.Services
|
||||
return toUpdate;
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Given the path of a content item, this will return true if the content item exists underneath a list view content item
|
||||
/// </summary>
|
||||
/// <param name="contentPath"></param>
|
||||
/// <returns></returns>
|
||||
public bool HasContainerInPath(string contentPath)
|
||||
{
|
||||
using (var uow = UowProvider.GetUnitOfWork())
|
||||
{
|
||||
// can use same repo for both content and media
|
||||
var repository = RepositoryFactory.CreateContentTypeRepository(uow);
|
||||
return repository.HasContainerInPath(contentPath);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -11,6 +11,13 @@ namespace Umbraco.Core.Services
|
||||
/// </summary>
|
||||
public interface IContentTypeService : IService
|
||||
{
|
||||
/// <summary>
|
||||
/// Given the path of a content item, this will return true if the content item exists underneath a list view content item
|
||||
/// </summary>
|
||||
/// <param name="contentPath"></param>
|
||||
/// <returns></returns>
|
||||
bool HasContainerInPath(string contentPath);
|
||||
|
||||
int CountContentTypes();
|
||||
int CountMediaTypes();
|
||||
|
||||
|
||||
@@ -2,12 +2,10 @@ using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading;
|
||||
using Umbraco.Core.Auditing;
|
||||
using Umbraco.Core.Events;
|
||||
using Umbraco.Core.Logging;
|
||||
using Umbraco.Core.Models;
|
||||
using Umbraco.Core.Persistence;
|
||||
using Umbraco.Core.Persistence.Querying;
|
||||
using Umbraco.Core.Persistence.UnitOfWork;
|
||||
|
||||
namespace Umbraco.Core.Services
|
||||
@@ -89,6 +87,8 @@ namespace Umbraco.Core.Services
|
||||
using (var repository = RepositoryFactory.CreateMemberTypeRepository(uow))
|
||||
{
|
||||
memberType.CreatorId = userId;
|
||||
if (memberType.Description == string.Empty)
|
||||
memberType.Description = null;
|
||||
repository.AddOrUpdate(memberType);
|
||||
|
||||
uow.Commit();
|
||||
@@ -114,6 +114,8 @@ namespace Umbraco.Core.Services
|
||||
foreach (var memberType in asArray)
|
||||
{
|
||||
memberType.CreatorId = userId;
|
||||
if (memberType.Description == string.Empty)
|
||||
memberType.Description = null;
|
||||
repository.AddOrUpdate(memberType);
|
||||
}
|
||||
|
||||
|
||||
@@ -180,6 +180,7 @@
|
||||
<Compile Include="Configuration\BaseRest\ExtensionElementCollection.cs" />
|
||||
<Compile Include="Configuration\BaseRest\MethodElement.cs" />
|
||||
<Compile Include="Configuration\ContentXmlStorage.cs" />
|
||||
<Compile Include="Configuration\CoreDebug.cs" />
|
||||
<Compile Include="Configuration\Dashboard\AccessElement.cs" />
|
||||
<Compile Include="Configuration\Dashboard\AccessItem.cs" />
|
||||
<Compile Include="Configuration\Dashboard\AccessType.cs" />
|
||||
@@ -300,6 +301,7 @@
|
||||
<Compile Include="DateTimeExtensions.cs" />
|
||||
<Compile Include="DecimalExtensions.cs" />
|
||||
<Compile Include="DelegateExtensions.cs" />
|
||||
<Compile Include="Diagnostics\MiniDump.cs" />
|
||||
<Compile Include="DictionaryExtensions.cs" />
|
||||
<Compile Include="Dictionary\CultureDictionaryFactoryResolver.cs" />
|
||||
<Compile Include="Dictionary\ICultureDictionaryFactory.cs" />
|
||||
|
||||
@@ -46,23 +46,6 @@ namespace Umbraco.Tests.Persistence.Repositories
|
||||
return new EntityContainerRepository(unitOfWork, CacheHelper.CreateDisabledCacheHelper(), Mock.Of<ILogger>(), SqlSyntax, Constants.ObjectTypes.DataTypeContainerGuid);
|
||||
}
|
||||
|
||||
[TestCase("UmbracoPreVal87-21,3,48", 3, true)]
|
||||
[TestCase("UmbracoPreVal87-21,33,48", 3, false)]
|
||||
[TestCase("UmbracoPreVal87-21,33,48", 33, true)]
|
||||
[TestCase("UmbracoPreVal87-21,3,48", 33, false)]
|
||||
[TestCase("UmbracoPreVal87-21,3,48", 21, true)]
|
||||
[TestCase("UmbracoPreVal87-21,3,48", 48, true)]
|
||||
[TestCase("UmbracoPreVal87-22,33,48", 2, false)]
|
||||
[TestCase("UmbracoPreVal87-22,33,48", 22, true)]
|
||||
[TestCase("UmbracoPreVal87-22,33,44", 4, false)]
|
||||
[TestCase("UmbracoPreVal87-22,33,44", 44, true)]
|
||||
[TestCase("UmbracoPreVal87-22,333,44", 33, false)]
|
||||
[TestCase("UmbracoPreVal87-22,333,44", 333, true)]
|
||||
public void Pre_Value_Cache_Key_Tests(string cacheKey, int preValueId, bool outcome)
|
||||
{
|
||||
Assert.AreEqual(outcome, Regex.IsMatch(cacheKey, DataTypeDefinitionRepository.GetCacheKeyRegex(preValueId)));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Can_Move()
|
||||
{
|
||||
@@ -537,7 +520,7 @@ namespace Umbraco.Tests.Persistence.Repositories
|
||||
}
|
||||
|
||||
var cached = cache.IsolatedRuntimeCache.GetCache<IDataTypeDefinition>().Result
|
||||
.GetCacheItemsByKeySearch<PreValueCollection>(CacheKeys.DataTypePreValuesCacheKey + dtd.Id + "-");
|
||||
.GetCacheItemsByKeySearch<PreValueCollection>(CacheKeys.DataTypePreValuesCacheKey + "_" + dtd.Id);
|
||||
|
||||
Assert.IsNotNull(cached);
|
||||
Assert.AreEqual(1, cached.Count());
|
||||
@@ -581,7 +564,7 @@ namespace Umbraco.Tests.Persistence.Repositories
|
||||
}
|
||||
|
||||
var cached = cache.IsolatedRuntimeCache.GetCache<IDataTypeDefinition>().Result
|
||||
.GetCacheItemsByKeySearch<PreValueCollection>(CacheKeys.DataTypePreValuesCacheKey + dtd.Id + "-");
|
||||
.GetCacheItemsByKeySearch<PreValueCollection>(CacheKeys.DataTypePreValuesCacheKey + "_" + dtd.Id);
|
||||
|
||||
Assert.IsNotNull(cached);
|
||||
Assert.AreEqual(1, cached.Count());
|
||||
|
||||
@@ -25,14 +25,14 @@ namespace Umbraco.Tests.Routing
|
||||
{
|
||||
SiteDomainHelper.AddSite("site1", "domain1.com", "domain1.net", "domain1.org");
|
||||
SiteDomainHelper.AddSite("site2", "domain2.com", "domain2.net", "domain2.org");
|
||||
|
||||
|
||||
var sites = SiteDomainHelper.Sites;
|
||||
|
||||
Assert.AreEqual(2, sites.Count);
|
||||
|
||||
Assert.Contains("site1", sites.Keys);
|
||||
Assert.Contains("site2", sites.Keys);
|
||||
|
||||
|
||||
var domains = sites["site1"];
|
||||
Assert.AreEqual(3, domains.Count());
|
||||
Assert.Contains("domain1.com", domains);
|
||||
@@ -84,7 +84,7 @@ namespace Umbraco.Tests.Routing
|
||||
|
||||
Assert.Contains("site2", sites.Keys);
|
||||
}
|
||||
|
||||
|
||||
[Test]
|
||||
public void AddSiteAgain()
|
||||
{
|
||||
@@ -175,15 +175,15 @@ namespace Umbraco.Tests.Routing
|
||||
|
||||
// map methods are not static because we can override them
|
||||
var helper = new SiteDomainHelper();
|
||||
|
||||
|
||||
// current is a site1 uri, domains contain current
|
||||
// so we'll get current
|
||||
//
|
||||
var current = new Uri("http://domain1.com/foo/bar");
|
||||
var output = helper.MapDomain(current, new[]
|
||||
{
|
||||
new DomainAndUri(new UmbracoDomain("domain1.com"), Uri.UriSchemeHttp),
|
||||
new DomainAndUri(new UmbracoDomain("domain2.com"), Uri.UriSchemeHttp),
|
||||
new DomainAndUri(new UmbracoDomain("domain1.com"), Uri.UriSchemeHttp),
|
||||
new DomainAndUri(new UmbracoDomain("domain2.com"), Uri.UriSchemeHttp),
|
||||
}).Uri.ToString();
|
||||
Assert.AreEqual("http://domain1.com/", output);
|
||||
|
||||
@@ -193,7 +193,7 @@ namespace Umbraco.Tests.Routing
|
||||
current = new Uri("http://domain1.com/foo/bar");
|
||||
output = helper.MapDomain(current, new[]
|
||||
{
|
||||
new DomainAndUri(new UmbracoDomain("domain1.net"), Uri.UriSchemeHttp),
|
||||
new DomainAndUri(new UmbracoDomain("domain1.net"), Uri.UriSchemeHttp),
|
||||
new DomainAndUri(new UmbracoDomain("domain2.net"), Uri.UriSchemeHttp)
|
||||
}).Uri.ToString();
|
||||
Assert.AreEqual("http://domain1.net/", output);
|
||||
@@ -205,12 +205,73 @@ namespace Umbraco.Tests.Routing
|
||||
current = new Uri("http://domain1.com/foo/bar");
|
||||
output = helper.MapDomain(current, new[]
|
||||
{
|
||||
new DomainAndUri(new UmbracoDomain("domain2.net"), Uri.UriSchemeHttp),
|
||||
new DomainAndUri(new UmbracoDomain("domain2.net"), Uri.UriSchemeHttp),
|
||||
new DomainAndUri(new UmbracoDomain("domain1.net"), Uri.UriSchemeHttp)
|
||||
}).Uri.ToString();
|
||||
Assert.AreEqual("http://domain1.net/", output);
|
||||
}
|
||||
|
||||
private DomainAndUri[] DomainAndUris(Uri current, IDomain[] domains)
|
||||
{
|
||||
var scheme = current == null ? Uri.UriSchemeHttp : current.Scheme;
|
||||
return domains
|
||||
.Where(d => d.IsWildcard == false)
|
||||
.Select(d => new DomainAndUri(d, scheme))
|
||||
.OrderByDescending(d => d.Uri.ToString())
|
||||
.ToArray();
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void MapDomainWithScheme()
|
||||
{
|
||||
SiteDomainHelper.AddSite("site1", "domain1.com", "domain1.net", "domain1.org");
|
||||
SiteDomainHelper.AddSite("site2", "domain2.com", "domain2.net", "domain2.org");
|
||||
SiteDomainHelper.AddSite("site3", "domain3.com", "domain3.net", "domain3.org");
|
||||
SiteDomainHelper.AddSite("site4", "https://domain4.com", "https://domain4.net", "https://domain4.org");
|
||||
|
||||
// map methods are not static because we can override them
|
||||
var helper = new SiteDomainHelper();
|
||||
|
||||
// this works, but it's purely by chance / arbitrary
|
||||
// don't use the www in tests here!
|
||||
var current = new Uri("https://www.domain1.com/foo/bar");
|
||||
var domainAndUris = DomainAndUris(current, new []
|
||||
{
|
||||
new UmbracoDomain("domain2.com"),
|
||||
new UmbracoDomain("domain1.com"),
|
||||
});
|
||||
var output = helper.MapDomain(current, domainAndUris).Uri.ToString();
|
||||
Assert.AreEqual("https://domain1.com/", output);
|
||||
|
||||
// will pick it all right
|
||||
current = new Uri("https://domain1.com/foo/bar");
|
||||
domainAndUris = DomainAndUris(current, new[]
|
||||
{
|
||||
new UmbracoDomain("https://domain1.com"),
|
||||
new UmbracoDomain("https://domain2.com")
|
||||
});
|
||||
output = helper.MapDomain(current, domainAndUris).Uri.ToString();
|
||||
Assert.AreEqual("https://domain1.com/", output);
|
||||
|
||||
current = new Uri("https://domain1.com/foo/bar");
|
||||
domainAndUris = DomainAndUris(current, new[]
|
||||
{
|
||||
new UmbracoDomain("https://domain1.com"),
|
||||
new UmbracoDomain("https://domain4.com")
|
||||
});
|
||||
output = helper.MapDomain(current, domainAndUris).Uri.ToString();
|
||||
Assert.AreEqual("https://domain1.com/", output);
|
||||
|
||||
current = new Uri("https://domain4.com/foo/bar");
|
||||
domainAndUris = DomainAndUris(current, new[]
|
||||
{
|
||||
new UmbracoDomain("https://domain1.com"),
|
||||
new UmbracoDomain("https://domain4.com")
|
||||
});
|
||||
output = helper.MapDomain(current, domainAndUris).Uri.ToString();
|
||||
Assert.AreEqual("https://domain4.com/", output);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void MapDomains()
|
||||
{
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
using System.Runtime.Remoting;
|
||||
using NUnit.Framework;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
@@ -8,7 +7,6 @@ using Umbraco.Core.Exceptions;
|
||||
using Umbraco.Core.Models;
|
||||
using Umbraco.Core.Models.Rdbms;
|
||||
using Umbraco.Core.Services;
|
||||
using Umbraco.Tests.CodeFirst.TestModels.Composition;
|
||||
using Umbraco.Tests.TestHelpers;
|
||||
using Umbraco.Tests.TestHelpers.Entities;
|
||||
|
||||
@@ -1420,6 +1418,38 @@ namespace Umbraco.Tests.Services
|
||||
Assert.That(descriptionPropertyTypeReloaded.PropertyGroupId.IsValueCreated, Is.False);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Empty_Description_Is_Always_Null_After_Saving_Content_Type()
|
||||
{
|
||||
var service = ServiceContext.ContentTypeService;
|
||||
var contentType = MockedContentTypes.CreateBasicContentType();
|
||||
contentType.Description = null;
|
||||
service.Save(contentType);
|
||||
|
||||
var contentType2 = MockedContentTypes.CreateBasicContentType("basePage2", "Base Page 2");
|
||||
contentType2.Description = string.Empty;
|
||||
service.Save(contentType2);
|
||||
|
||||
Assert.IsNull(contentType.Description);
|
||||
Assert.IsNull(contentType2.Description);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Empty_Description_Is_Always_Null_After_Saving_Media_Type()
|
||||
{
|
||||
var service = ServiceContext.ContentTypeService;
|
||||
var mediaType = MockedContentTypes.CreateSimpleMediaType("mediaType", "Media Type");
|
||||
mediaType.Description = null;
|
||||
service.Save(mediaType);
|
||||
|
||||
var mediaType2 = MockedContentTypes.CreateSimpleMediaType("mediaType2", "Media Type 2");
|
||||
mediaType2.Description = string.Empty;
|
||||
service.Save(mediaType2);
|
||||
|
||||
Assert.IsNull(mediaType.Description);
|
||||
Assert.IsNull(mediaType2.Description);
|
||||
}
|
||||
|
||||
private ContentType CreateComponent()
|
||||
{
|
||||
var component = new ContentType(-1)
|
||||
|
||||
@@ -1,8 +1,6 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using NUnit.Framework;
|
||||
using umbraco.cms.presentation.create.controls;
|
||||
using Umbraco.Core;
|
||||
using Umbraco.Core.Models;
|
||||
using Umbraco.Core.Models.Rdbms;
|
||||
@@ -183,6 +181,22 @@ namespace Umbraco.Tests.Services
|
||||
Assert.Throws<ArgumentException>(() => ServiceContext.MemberTypeService.Save(memberType));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Empty_Description_Is_Always_Null_After_Saving_Member_Type()
|
||||
{
|
||||
var service = ServiceContext.MemberTypeService;
|
||||
var memberType = MockedContentTypes.CreateSimpleMemberType();
|
||||
memberType.Description = null;
|
||||
service.Save(memberType);
|
||||
|
||||
var memberType2 = MockedContentTypes.CreateSimpleMemberType("memberType2", "Member Type 2");
|
||||
memberType2.Description = string.Empty;
|
||||
service.Save(memberType2);
|
||||
|
||||
Assert.IsNull(memberType.Description);
|
||||
Assert.IsNull(memberType2.Description);
|
||||
}
|
||||
|
||||
//[Test]
|
||||
//public void Can_Save_MemberType_Structure_And_Create_A_Member_Based_On_It()
|
||||
//{
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
using System;
|
||||
using System.Linq;
|
||||
using Umbraco.Core;
|
||||
using Umbraco.Core.Models;
|
||||
|
||||
|
||||
@@ -57,8 +57,8 @@
|
||||
<Reference Include="AutoMapper.Net4, Version=3.3.1.0, Culture=neutral, PublicKeyToken=be96cd2c38ef1005, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\AutoMapper.3.3.1\lib\net40\AutoMapper.Net4.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Examine, Version=0.1.81.0, Culture=neutral, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\Examine.0.1.81\lib\net45\Examine.dll</HintPath>
|
||||
<Reference Include="Examine, Version=0.1.82.0, Culture=neutral, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\Examine.0.1.82\lib\net45\Examine.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="ICSharpCode.SharpZipLib, Version=0.86.0.518, Culture=neutral, PublicKeyToken=1b03e6acf1164f73, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\SharpZipLib.0.86.0\lib\20\ICSharpCode.SharpZipLib.dll</HintPath>
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
<packages>
|
||||
<package id="AspNetWebApi.SelfHost" version="4.0.20710.0" targetFramework="net45" />
|
||||
<package id="AutoMapper" version="3.3.1" targetFramework="net45" />
|
||||
<package id="Examine" version="0.1.81" targetFramework="net45" />
|
||||
<package id="Examine" version="0.1.82" targetFramework="net45" />
|
||||
<package id="log4net-mediumtrust" version="2.0.0" targetFramework="net45" />
|
||||
<package id="Lucene.Net" version="2.9.4.1" targetFramework="net45" />
|
||||
<package id="Microsoft.AspNet.Mvc" version="5.2.3" targetFramework="net45" />
|
||||
|
||||
+2
-2
@@ -163,13 +163,13 @@ angular.module('umbraco.directives')
|
||||
}
|
||||
|
||||
// ignore clicks on dialog from old dialog service
|
||||
var oldDialog = $(el).parents("#old-dialog-service");
|
||||
var oldDialog = $(event.target).parents("#old-dialog-service");
|
||||
if (oldDialog.length === 1) {
|
||||
return;
|
||||
}
|
||||
|
||||
// ignore clicks in tinyMCE dropdown(floatpanel)
|
||||
var floatpanel = $(el).parents(".mce-floatpanel");
|
||||
var floatpanel = $(event.target).closest(".mce-floatpanel");
|
||||
if (floatpanel.length === 1) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -14,6 +14,7 @@ body {
|
||||
overflow: hidden;
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
width: ~"(calc(~'100%' - ~'80px'))"; // 80px is the fixed left menu for toggling the different browser sizes
|
||||
position: absolute;
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
|
||||
@@ -3,232 +3,285 @@
|
||||
<h3>Examine Management</h3>
|
||||
|
||||
<div ng-show="loading">
|
||||
Loading...
|
||||
<div class="umb-healthcheck-group__details-status-overlay"></div>
|
||||
<umb-load-indicator></umb-load-indicator>
|
||||
</div>
|
||||
|
||||
<h4>Indexers</h4>
|
||||
<div ng-hide="loading" class="umb-healthcheck-group__details">
|
||||
|
||||
<ul ng-hide="loading">
|
||||
<li class="provider" ng-repeat="indexer in indexerDetails">
|
||||
<div class="umb-healthcheck-group__details-group-title">
|
||||
<div class="umb-healthcheck-group__details-group-name">Indexers</div>
|
||||
</div>
|
||||
|
||||
<a class="btn-link -underline" href="" ng-click="toggle(indexer, 'showProperties')">
|
||||
{{indexer.name}}
|
||||
</a>
|
||||
<div class="umb-healthcheck-group__details-checks">
|
||||
<div class="umb-healthcheck-group__details-check">
|
||||
<div class="umb-healthcheck-group__details-check-title">
|
||||
<div class="umb-healthcheck-group__details-check-name">Manage Examine's indexes</div>
|
||||
<div class="umb-healthcheck-group__details-check-description">Allows you to view the details of each index and provides some tools for managing the indexes</div>
|
||||
</div>
|
||||
|
||||
<ul ng-show="indexer.showProperties">
|
||||
<div class="umb-healthcheck-group__details-status" ng-repeat="indexer in indexerDetails">
|
||||
|
||||
<li>
|
||||
<div class="umb-healthcheck-group__details-status-icon-container">
|
||||
<i class="umb-healthcheck-status-icon" ng-class="{'icon-check color-green' : indexer.isHealthy, 'icon-delete color-red' : !indexer.isHealthy}"></i>
|
||||
</div>
|
||||
|
||||
<a href="" ng-click="toggle(indexer, 'showTools')">Index info & tools</a>
|
||||
|
||||
<div ng-show="indexer.showTools && indexer.isLuceneIndex">
|
||||
<div>
|
||||
<br />
|
||||
<div ng-show="!indexer.isProcessing && (!indexer.processingAttempts || indexer.processingAttempts < 100)" class="btn-group">
|
||||
|
||||
<button type="button" class="btn btn-warning" ng-click="rebuildIndex(indexer)">Rebuild index</button>
|
||||
<button type="button" class="btn btn-warning" ng-click="optimizeIndex(indexer)" ng-show="indexer.documentCount > 0">Optimize index</button>
|
||||
<div class="umb-healthcheck-group__details-status-content">
|
||||
<div class="umb-healthcheck-group__details-status-text">
|
||||
<div ng-show="!indexer.isHealthy">
|
||||
{{indexer.name}}
|
||||
</div>
|
||||
|
||||
<div ng-show="indexer.isProcessing" class="umb-loader-wrapper" ng-show="actionInProgress">
|
||||
<div class="umb-loader"></div>
|
||||
</div>
|
||||
|
||||
<div class="error" ng-show="indexer.processingAttempts >= 100">
|
||||
The process is taking longer than expected, check the umbraco log to see if there have been any errors during this operation
|
||||
<a class="btn-link -underline" href="" ng-click="toggle(indexer, 'showProperties')" ng-show="indexer.isHealthy">
|
||||
{{indexer.name}}
|
||||
</a>
|
||||
<div ng-if="!indexer.isHealthy" class="text-error">
|
||||
The index cannot be read and will need to be rebuilt
|
||||
</div>
|
||||
</div>
|
||||
<table class="table table-bordered table-condensed">
|
||||
<caption> </caption>
|
||||
<tr>
|
||||
<th>Documents in index</th>
|
||||
<td>{{indexer.documentCount}}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>Fields in index</th>
|
||||
<td>{{indexer.fieldCount}}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>Has deletions?</th>
|
||||
<td>
|
||||
<span>{{indexer.deletionCount > 0}}</span>
|
||||
(<span>{{indexer.deletionCount}}</span>)
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>Optimized?</th>
|
||||
<td>
|
||||
<span>{{indexer.isOptimized}}</span>
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
</table>
|
||||
</div>
|
||||
</li>
|
||||
|
||||
<li ng-show="indexer.indexCriteria.IncludeNodeTypes.length > 0 || indexer.indexCriteria.ExcludeNodeTypes.length > 0 || indexer.indexCriteria.ParentNodeId">
|
||||
<a href="" ng-click="toggle(indexer, 'showNodeTypes')">Node types</a>
|
||||
<table ng-show="indexer.showNodeTypes" class="table table-bordered table-condensed">
|
||||
<tr ng-show="indexer.indexCriteria.IncludeNodeTypes.length > 0">
|
||||
<th>Include node types</th>
|
||||
<td>{{indexer.indexCriteria.IncludeNodeTypes | json}}</td>
|
||||
</tr>
|
||||
<tr ng-show="indexer.indexCriteria.ExcludeNodeTypes.length > 0">
|
||||
<th>Exclude node types</th>
|
||||
<td>{{indexer.indexCriteria.ExcludeNodeTypes | json}}</td>
|
||||
</tr>
|
||||
<tr ng-show="indexer.indexCriteria.ParentNodeId">
|
||||
<th>Parent node id</th>
|
||||
<td>{{indexer.indexCriteria.ParentNodeId}}</td>
|
||||
</tr>
|
||||
</table>
|
||||
</li>
|
||||
|
||||
<li ng-show="indexer.indexCriteria.StandardFields.length > 0">
|
||||
<a href="" ng-click="toggle(indexer, 'showSystemFields')">System fields</a>
|
||||
<table ng-show="indexer.showSystemFields" class="table table-bordered table-condensed">
|
||||
<caption> </caption>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Name</th>
|
||||
<th>Enable sorting</th>
|
||||
<th>Type</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr ng-repeat="field in indexer.indexCriteria.StandardFields">
|
||||
<th>{{field.Name}}</th>
|
||||
<td>{{field.EnableSorting}}</td>
|
||||
<td>{{field.Type}}</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</li>
|
||||
|
||||
<li ng-show="indexer.indexCriteria.UserFields.length > 0">
|
||||
<a href="" ng-click="toggle(indexer, 'showUserFields')">User fields</a>
|
||||
<table ng-show="indexer.showUserFields" class="table table-bordered table-condensed">
|
||||
<caption> </caption>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Name</th>
|
||||
<th>Enable sorting</th>
|
||||
<th>Type</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr ng-repeat="field in indexer.indexCriteria.UserFields">
|
||||
<th>{{field.Name}}</th>
|
||||
<td>{{field.EnableSorting}}</td>
|
||||
<td>{{field.Type}}</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</li>
|
||||
|
||||
<li>
|
||||
<a href="" ng-click="toggle(indexer, 'showProviderProperties')">Provider properties</a>
|
||||
<table ng-show="indexer.showProviderProperties" class="table table-bordered table-condensed">
|
||||
<caption> </caption>
|
||||
<tr ng-repeat="(key, val) in indexer.providerProperties track by $index">
|
||||
<th>{{key}}</th>
|
||||
<td>{{val}}</td>
|
||||
</tr>
|
||||
</table>
|
||||
</li>
|
||||
</ul>
|
||||
</li>
|
||||
|
||||
|
||||
|
||||
</ul>
|
||||
|
||||
<h4>Searchers</h4>
|
||||
|
||||
<ul ng-hide="loading">
|
||||
<li class="provider" ng-repeat="searcher in searcherDetails">
|
||||
<a class="btn-link -underline" href="" ng-click="toggle(searcher, 'showProperties')">
|
||||
{{searcher.name}}
|
||||
</a>
|
||||
|
||||
<ul ng-show="searcher.showProperties">
|
||||
|
||||
<li class="search-tools">
|
||||
|
||||
<a href="" ng-click="toggle(searcher, 'showTools')">Search tools</a>
|
||||
|
||||
<div ng-show="searcher.showTools">
|
||||
<a class="hide" href="" ng-click="closeSearch(searcher)" ng-show="searcher.isSearching">Hide search results</a>
|
||||
|
||||
<br />
|
||||
|
||||
<form>
|
||||
|
||||
<div class="row form-search">
|
||||
<div class="span8 input-append">
|
||||
<input type="text" class="search-query" ng-model="searcher.searchText" no-dirty-check />
|
||||
<button type="button" class="btn btn-info" ng-click="search(searcher)" ng-disabled="searcher.isProcessing">Search</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<label for="{{searcher.name}}-textSearch" class="radio inline">
|
||||
<input type="radio" name="searchType" id="{{searcher.name}}-textSearch" value="text" ng-model="searcher.searchType" no-dirty-check />
|
||||
Text Search
|
||||
</label>
|
||||
<label for="{{searcher.name}}-luceneSearch" class="radio inline">
|
||||
<input type="radio" name="searchType" id="{{searcher.name}}-luceneSearch" value="lucene" ng-model="searcher.searchType" no-dirty-check />
|
||||
Lucene Search
|
||||
</label>
|
||||
<div class="umb-healthcheck-group__details-status-actions" ng-if="!indexer.isHealthy">
|
||||
<div class="umb-healthcheck-group__details-status-action">
|
||||
<button type="button" class="umb-era-button -blue"
|
||||
ng-show="!indexer.isProcessing && (!indexer.processingAttempts || indexer.processingAttempts < 100)"
|
||||
ng-click="rebuildIndex(indexer)">
|
||||
Rebuild index
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="umb-healthcheck-group__details-status-actions" ng-show="indexer.isHealthy && indexer.showProperties">
|
||||
<ul>
|
||||
<li>
|
||||
<a href="" ng-click="toggle(indexer, 'showTools')">Index info & tools</a>
|
||||
|
||||
</form>
|
||||
<div ng-show="indexer.showTools && indexer.isLuceneIndex">
|
||||
<div>
|
||||
<br />
|
||||
|
||||
<div class="search-results" ng-show="searcher.isSearching">
|
||||
<div ng-show="!indexer.isProcessing && (!indexer.processingAttempts || indexer.processingAttempts < 100)"
|
||||
class="umb-healthcheck-group__details-status-action">
|
||||
<button type="button" class="umb-era-button -blue" ng-click="rebuildIndex(indexer)">Rebuild index</button>
|
||||
</div>
|
||||
|
||||
<div ng-show="indexer.isProcessing" class="umb-loader-wrapper" ng-show="indexer.isProcessing">
|
||||
<div class="umb-loader"></div>
|
||||
</div>
|
||||
<div ng-show="indexer.processingAttempts >= 100">
|
||||
The process is taking longer than expected, check the umbraco log to see if there have been any errors during this operation
|
||||
</div>
|
||||
</div>
|
||||
<table class="table table-bordered table-condensed">
|
||||
<caption> </caption>
|
||||
<tr>
|
||||
<th>Documents in index</th>
|
||||
<td>{{indexer.documentCount}}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>Fields in index</th>
|
||||
<td>{{indexer.fieldCount}}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>Has deletions?</th>
|
||||
<td>
|
||||
<span>{{indexer.deletionCount > 0}}</span>
|
||||
(<span>{{indexer.deletionCount}}</span>)
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>Optimized?</th>
|
||||
<td>
|
||||
<span>{{indexer.isOptimized}}</span>
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<table ng-hide="searcher.isProcessing" class="table table-bordered table-condensed">
|
||||
<thead>
|
||||
<tr>
|
||||
<th class="score">Score</th>
|
||||
<th class="id">Id</th>
|
||||
<th>Values</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr ng-repeat="result in searcher.searchResults">
|
||||
<td>{{result.Score}}</td>
|
||||
<td>{{result.Id}}</td>
|
||||
<td>
|
||||
<span ng-repeat="(key,val) in result.Fields track by $index">
|
||||
<span class=""><em>{{key}}</em>:</span>
|
||||
<span class="text-info">{{val}}</span>
|
||||
</span>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</table>
|
||||
</div>
|
||||
</li>
|
||||
<li ng-show="indexer.indexCriteria.IncludeNodeTypes.length > 0 || indexer.indexCriteria.ExcludeNodeTypes.length > 0 || indexer.indexCriteria.ParentNodeId">
|
||||
<a href="" ng-click="toggle(indexer, 'showNodeTypes')">Node types</a>
|
||||
<table ng-show="indexer.showNodeTypes" class="table table-bordered table-condensed">
|
||||
<tr ng-show="indexer.indexCriteria.IncludeNodeTypes.length > 0">
|
||||
<th>Include node types</th>
|
||||
<td>{{indexer.indexCriteria.IncludeNodeTypes | json}}</td>
|
||||
</tr>
|
||||
<tr ng-show="indexer.indexCriteria.ExcludeNodeTypes.length > 0">
|
||||
<th>Exclude node types</th>
|
||||
<td>{{indexer.indexCriteria.ExcludeNodeTypes | json}}</td>
|
||||
</tr>
|
||||
<tr ng-show="indexer.indexCriteria.ParentNodeId">
|
||||
<th>Parent node id</th>
|
||||
<td>{{indexer.indexCriteria.ParentNodeId}}</td>
|
||||
</tr>
|
||||
</table>
|
||||
</li>
|
||||
<li ng-show="indexer.indexCriteria.StandardFields.length > 0">
|
||||
<a href="" ng-click="toggle(indexer, 'showSystemFields')">System fields</a>
|
||||
<table ng-show="indexer.showSystemFields" class="table table-bordered table-condensed">
|
||||
<caption> </caption>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Name</th>
|
||||
<th>Enable sorting</th>
|
||||
<th>Type</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr ng-repeat="field in indexer.indexCriteria.StandardFields">
|
||||
<th>{{field.Name}}</th>
|
||||
<td>{{field.EnableSorting}}</td>
|
||||
<td>{{field.Type}}</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</li>
|
||||
<li ng-show="indexer.indexCriteria.UserFields.length > 0">
|
||||
<a href="" ng-click="toggle(indexer, 'showUserFields')">User fields</a>
|
||||
<table ng-show="indexer.showUserFields" class="table table-bordered table-condensed">
|
||||
<caption> </caption>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Name</th>
|
||||
<th>Enable sorting</th>
|
||||
<th>Type</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr ng-repeat="field in indexer.indexCriteria.UserFields">
|
||||
<th>{{field.Name}}</th>
|
||||
<td>{{field.EnableSorting}}</td>
|
||||
<td>{{field.Type}}</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</li>
|
||||
<li>
|
||||
<a href="" ng-click="toggle(indexer, 'showProviderProperties')">Provider properties</a>
|
||||
<table ng-show="indexer.showProviderProperties" class="table table-bordered table-condensed">
|
||||
<caption> </caption>
|
||||
<tr ng-repeat="(key, val) in indexer.providerProperties track by $index">
|
||||
<th>{{key}}</th>
|
||||
<td>{{val}}</td>
|
||||
</tr>
|
||||
</table>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</li>
|
||||
|
||||
<li>
|
||||
<a href="" ng-click="toggle(searcher, 'showProviderProperties')">Provider properties</a>
|
||||
<table ng-show="searcher.showProviderProperties" class="table table-bordered table-condensed">
|
||||
<caption> </caption>
|
||||
<tr ng-repeat="(key, val) in searcher.providerProperties track by $index">
|
||||
<th>{{key}}</th>
|
||||
<td>{{val}}</td>
|
||||
</tr>
|
||||
</table>
|
||||
</li>
|
||||
<div ng-show="indexer.isProcessing">
|
||||
<div class="umb-healthcheck-group__details-status-overlay"></div>
|
||||
<umb-load-indicator></umb-load-indicator>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<br />
|
||||
|
||||
<div class="umb-healthcheck-group__details-group-title">
|
||||
<div class="umb-healthcheck-group__details-group-name">Searchers</div>
|
||||
</div>
|
||||
|
||||
<div class="umb-healthcheck-group__details-checks">
|
||||
<div class="umb-healthcheck-group__details-check">
|
||||
<div class="umb-healthcheck-group__details-check-title">
|
||||
<div class="umb-healthcheck-group__details-check-name">Search indexes</div>
|
||||
<div class="umb-healthcheck-group__details-check-description">Allows you to search the indexes and view the searcher properties</div>
|
||||
</div>
|
||||
|
||||
<div class="umb-healthcheck-group__details-status" ng-repeat="searcher in searcherDetails">
|
||||
|
||||
<div class="umb-healthcheck-group__details-status-icon-container">
|
||||
<i class="umb-healthcheck-status-icon icon-info"></i>
|
||||
</div>
|
||||
|
||||
<div class="umb-healthcheck-group__details-status-content">
|
||||
<div class="umb-healthcheck-group__details-status-text">
|
||||
<a class="btn-link -underline" href="" ng-click="toggle(searcher, 'showProperties')">
|
||||
{{searcher.name}}
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<div class="umb-healthcheck-group__details-status-actions" ng-show="searcher.showProperties">
|
||||
<ul>
|
||||
<li class="search-tools">
|
||||
|
||||
<a href="" ng-click="toggle(searcher, 'showTools')">Search tools</a>
|
||||
|
||||
<div ng-show="searcher.showTools">
|
||||
<a class="hide" href="" ng-click="closeSearch(searcher)" ng-show="searcher.isSearching">Hide search results</a>
|
||||
|
||||
<br />
|
||||
|
||||
<form>
|
||||
|
||||
<div class="row form-search">
|
||||
<div class="span8 input-append">
|
||||
<input type="text" class="search-query" ng-model="searcher.searchText" no-dirty-check />
|
||||
<button type="button" class="btn btn-info" ng-click="search(searcher)" ng-disabled="searcher.isProcessing">Search</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<label for="{{searcher.name}}-textSearch" class="radio inline">
|
||||
<input type="radio" name="searchType" id="{{searcher.name}}-textSearch" value="text" ng-model="searcher.searchType" no-dirty-check />
|
||||
Text Search
|
||||
</label>
|
||||
<label for="{{searcher.name}}-luceneSearch" class="radio inline">
|
||||
<input type="radio" name="searchType" id="{{searcher.name}}-luceneSearch" value="lucene" ng-model="searcher.searchType" no-dirty-check />
|
||||
Lucene Search
|
||||
</label>
|
||||
</div>
|
||||
|
||||
|
||||
</form>
|
||||
|
||||
<div class="search-results" ng-show="searcher.isSearching">
|
||||
|
||||
<div ng-show="indexer.isProcessing" class="umb-loader-wrapper" ng-show="indexer.isProcessing">
|
||||
<div class="umb-loader"></div>
|
||||
</div>
|
||||
|
||||
<table ng-hide="searcher.isProcessing" class="table table-bordered table-condensed">
|
||||
<thead>
|
||||
<tr>
|
||||
<th class="score">Score</th>
|
||||
<th class="id">Id</th>
|
||||
<th>Values</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr ng-repeat="result in searcher.searchResults">
|
||||
<td>{{result.Score}}</td>
|
||||
<td>{{result.Id}}</td>
|
||||
<td>
|
||||
<span ng-repeat="(key,val) in result.Fields track by $index">
|
||||
<span class=""><em>{{key}}</em>:</span>
|
||||
<span class="text-info">{{val}}</span>
|
||||
</span>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</li>
|
||||
<li>
|
||||
<a href="" ng-click="toggle(searcher, 'showProviderProperties')">Provider properties</a>
|
||||
<table ng-show="searcher.showProviderProperties" class="table table-bordered table-condensed">
|
||||
<caption> </caption>
|
||||
<tr ng-repeat="(key, val) in searcher.providerProperties track by $index">
|
||||
<th>{{key}}</th>
|
||||
<td>{{val}}</td>
|
||||
</tr>
|
||||
</table>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
</ul>
|
||||
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
</div>
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
<span class="caret"></span>
|
||||
</a>
|
||||
<ul class="dropdown-menu">
|
||||
<li ng-repeat="contentType in listViewAllowedTypes">
|
||||
<li ng-repeat="contentType in listViewAllowedTypes | orderBy:'name':false">
|
||||
<a href="#/{{entityType}}/{{entityType}}/edit/{{contentId}}?doctype={{contentType.alias}}&create=true">
|
||||
<i class="icon-{{contentType.cssClass}}"></i>
|
||||
{{contentType.name}}
|
||||
|
||||
@@ -127,8 +127,8 @@
|
||||
<SpecificVersion>False</SpecificVersion>
|
||||
<HintPath>..\packages\dotless.1.4.1.0\lib\dotless.Core.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Examine, Version=0.1.81.0, Culture=neutral, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\Examine.0.1.81\lib\net45\Examine.dll</HintPath>
|
||||
<Reference Include="Examine, Version=0.1.82.0, Culture=neutral, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\Examine.0.1.82\lib\net45\Examine.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="ICSharpCode.SharpZipLib, Version=0.86.0.518, Culture=neutral, PublicKeyToken=1b03e6acf1164f73, processorArchitecture=MSIL">
|
||||
<SpecificVersion>False</SpecificVersion>
|
||||
@@ -350,9 +350,8 @@
|
||||
<Name>umbraco.providers</Name>
|
||||
</ProjectReference>
|
||||
<Reference Include="System.Xml.Linq" />
|
||||
<Reference Include="Umbraco.ModelsBuilder, Version=3.0.5.96, Culture=neutral, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\Umbraco.ModelsBuilder.3.0.5\lib\Umbraco.ModelsBuilder.dll</HintPath>
|
||||
<Private>True</Private>
|
||||
<Reference Include="Umbraco.ModelsBuilder, Version=3.0.7.99, Culture=neutral, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\Umbraco.ModelsBuilder.3.0.7\lib\Umbraco.ModelsBuilder.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="UrlRewritingNet.UrlRewriter, Version=2.0.7.0, Culture=neutral, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\UrlRewritingNet.UrlRewriter.2.0.7\lib\UrlRewritingNet.UrlRewriter.dll</HintPath>
|
||||
@@ -2423,9 +2422,9 @@ xcopy "$(ProjectDir)"..\packages\SqlServerCE.4.0.0.1\x86\*.* "$(TargetDir)x86\"
|
||||
<WebProjectProperties>
|
||||
<UseIIS>True</UseIIS>
|
||||
<AutoAssignPort>True</AutoAssignPort>
|
||||
<DevelopmentServerPort>7511</DevelopmentServerPort>
|
||||
<DevelopmentServerPort>7513</DevelopmentServerPort>
|
||||
<DevelopmentServerVPath>/</DevelopmentServerVPath>
|
||||
<IISUrl>http://localhost:7511</IISUrl>
|
||||
<IISUrl>http://localhost:7513</IISUrl>
|
||||
<NTLMAuthentication>False</NTLMAuthentication>
|
||||
<UseCustomServer>False</UseCustomServer>
|
||||
<CustomServerUrl>
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<package id="ClientDependency" version="1.9.2" targetFramework="net45" />
|
||||
<package id="ClientDependency-Mvc5" version="1.8.0.0" targetFramework="net45" />
|
||||
<package id="dotless" version="1.4.1.0" targetFramework="net45" />
|
||||
<package id="Examine" version="0.1.81" targetFramework="net45" />
|
||||
<package id="Examine" version="0.1.82" targetFramework="net45" />
|
||||
<package id="ImageProcessor" version="2.5.2" targetFramework="net45" />
|
||||
<package id="ImageProcessor.Web" version="4.8.2" targetFramework="net45" />
|
||||
<package id="ImageProcessor.Web.Config" version="2.3.0" targetFramework="net45" />
|
||||
@@ -37,6 +37,6 @@
|
||||
<package id="SqlServerCE" version="4.0.0.1" targetFramework="net45" />
|
||||
<package id="System.Collections.Immutable" version="1.1.36" targetFramework="net45" />
|
||||
<package id="System.Reflection.Metadata" version="1.0.21" targetFramework="net45" />
|
||||
<package id="Umbraco.ModelsBuilder" version="3.0.5" targetFramework="net45" />
|
||||
<package id="Umbraco.ModelsBuilder" version="3.0.7" targetFramework="net45" />
|
||||
<package id="UrlRewritingNet.UrlRewriter" version="2.0.7" targetFramework="net45" />
|
||||
</packages>
|
||||
@@ -972,7 +972,7 @@ To manage your website, simply open the Umbraco back office and start adding con
|
||||
<key alias="dictionaryItemSaved">Dictionary item saved</key>
|
||||
<key alias="editContentPublishedFailedByParent">Publishing failed because the parent page isn't published</key>
|
||||
<key alias="editContentPublishedHeader">Content published</key>
|
||||
<key alias="editContentPublishedText">and visible at the website</key>
|
||||
<key alias="editContentPublishedText">and visible on the website</key>
|
||||
<key alias="editContentSavedHeader">Content saved</key>
|
||||
<key alias="editContentSavedText">Remember to publish to make changes visible</key>
|
||||
<key alias="editContentSendToPublish">Sent For Approval</key>
|
||||
|
||||
@@ -972,7 +972,7 @@ To manage your website, simply open the Umbraco back office and start adding con
|
||||
<key alias="dictionaryItemSaved">Dictionary item saved</key>
|
||||
<key alias="editContentPublishedFailedByParent">Publishing failed because the parent page isn't published</key>
|
||||
<key alias="editContentPublishedHeader">Content published</key>
|
||||
<key alias="editContentPublishedText">and visible at the website</key>
|
||||
<key alias="editContentPublishedText">and visible on the website</key>
|
||||
<key alias="editContentSavedHeader">Content saved</key>
|
||||
<key alias="editContentSavedText">Remember to publish to make changes visible</key>
|
||||
<key alias="editContentSendToPublish">Sent For Approval</key>
|
||||
|
||||
@@ -123,7 +123,6 @@
|
||||
<key alias="saveListView">Сохранить список</key>
|
||||
<key alias="select">Выбрать</key>
|
||||
<key alias="selectCurrentFolder">Выбрать текущую папку</key>
|
||||
<key alias="selected">выбранные</key>
|
||||
<key alias="showPage">Предварительный просмотр</key>
|
||||
<key alias="showPageDisabled">Предварительный просмотр запрещен, так как документу не сопоставлен шаблон</key>
|
||||
<key alias="somethingElse">Другие действия</key>
|
||||
@@ -993,6 +992,7 @@
|
||||
<key alias="installStateInstalling">Установка...</key>
|
||||
<key alias="installStateRestarting">Перезапуск, подождите, пожалуйста...</key>
|
||||
<key alias="installStateComplete">Все готово, сейчас браузер перезагрузит страницу, подождите, пожалуйста...</key>
|
||||
<key alias="installStateCompleted">Пожалуйста, нажмите кнопку 'finish' для завершения установки и перезагрузки страницы.</key>
|
||||
</area>
|
||||
<area alias="paste">
|
||||
<key alias="doNothing">Вставить, полностью сохранив форматирование (не рекомендуется)</key>
|
||||
@@ -1119,9 +1119,9 @@
|
||||
<key alias="statistics">Статистика</key>
|
||||
<key alias="translation">Перевод</key>
|
||||
<key alias="users">Пользователи</key>
|
||||
<key alias="addIcon">Добавить значок</key>
|
||||
</area>
|
||||
<area alias="settings">
|
||||
<key alias="addIcon">Добавить значок</key>
|
||||
<key alias="asAContentMasterType">в качестве родительского типа. Вкладки родительского типа не показаны и могут быть изменены непосредственно в родительском типе</key>
|
||||
<key alias="contentTypeEnabled">Родительский тип контента разрешен</key>
|
||||
<key alias="contentTypeUses">Данный тип контента использует</key>
|
||||
@@ -1178,6 +1178,7 @@
|
||||
<key alias="contentTypeTabDeletedText">Вкладка с идентификатором (id): %0% удалена</key>
|
||||
<key alias="contentUnpublished">Документ скрыт (публикация отменена)</key>
|
||||
<key alias="cssErrorHeader">Стиль CSS не сохранен</key>
|
||||
<key alias="cssErrorText">При сохранении файла произошла ошибка.</key>
|
||||
<key alias="cssSavedHeader">Стиль CSS сохранен</key>
|
||||
<key alias="cssSavedText">Стиль CSS сохранен без ошибок</key>
|
||||
<key alias="dataTypeSaved">Тип данных сохранен</key>
|
||||
@@ -1202,9 +1203,13 @@
|
||||
<key alias="fileErrorText">Файл не может быть сохранен. Пожалуйста, проверьте установки файловых разрешений</key>
|
||||
<key alias="fileSavedHeader">Файл сохранен</key>
|
||||
<key alias="fileSavedText">Файл сохранен без ошибок</key>
|
||||
<key alias="invalidUserPermissionsText">У текущего пользователя недостаточно прав, невозможно завершить операцию</key>
|
||||
<key alias="languageSaved">Язык сохранен</key>
|
||||
<key alias="mediaTypeSavedHeader">Тип медиа сохранен</key>
|
||||
<key alias="memberTypeSavedHeader">Тип участника сохранен</key>
|
||||
<key alias="operationCancelledHeader">Отменено</key>
|
||||
<key alias="operationCancelledText">Операция отменена установленным сторонним расширением или блоком кода</key>
|
||||
<key alias="operationFailedHeader">Ошибка</key>
|
||||
<key alias="partialViewErrorHeader">Представление не сохранено</key>
|
||||
<key alias="partialViewErrorText">Произошла ошибка при сохранении файла</key>
|
||||
<key alias="partialViewSavedHeader">Представление сохранено</key>
|
||||
@@ -1213,10 +1218,16 @@
|
||||
<key alias="pythonErrorText">Cкрипт Python не может быть сохранен в связи с ошибками</key>
|
||||
<key alias="pythonSavedHeader">Cкрипт Python сохранен</key>
|
||||
<key alias="pythonSavedText">Cкрипт Python сохранен без ошибок</key>
|
||||
<key alias="scriptErrorHeader">Скрипт не сохранен</key>
|
||||
<key alias="scriptErrorText">При сохранении файла скрипта произошла ошибка</key>
|
||||
<key alias="scriptSavedHeader">Скрипт сохранен</key>
|
||||
<key alias="scriptSavedText">Файл скрипта сохранен без ошибок</key>
|
||||
<key alias="templateErrorHeader">Шаблон не сохранен</key>
|
||||
<key alias="templateErrorText">Пожалуйста, проверьте, что нет двух шаблонов с одним и тем же алиасом (названием)</key>
|
||||
<key alias="templateSavedHeader">Шаблон сохранен</key>
|
||||
<key alias="templateSavedText">Шаблон сохранен без ошибок</key>
|
||||
<key alias="validationFailedHeader">Проверка значений</key>
|
||||
<key alias="validationFailedMessage">Ошибки, найденные при проверке значений, должны быть исправлены, чтобы было возможно сохранить документ</key>
|
||||
<key alias="xsltErrorHeader">XSLT-документ не сохранен</key>
|
||||
<key alias="xsltErrorText">XSLT-документ содержит одну или несколько ошибок</key>
|
||||
<key alias="xsltPermissionErrorText">XSLT-документ не может быть сохранен, проверьте установки файловых разрешений</key>
|
||||
@@ -1343,6 +1354,7 @@
|
||||
<key alias="packager">Пакеты дополнений</key>
|
||||
<key alias="packages">Пакеты дополнений</key>
|
||||
<key alias="python">Скрипты Python</key>
|
||||
<key alias="relationTypes">Типы связей</key>
|
||||
<key alias="repositories">Установить из репозитория</key>
|
||||
<key alias="runway">Установить Runway</key>
|
||||
<key alias="runwayModules">Модули Runway </key>
|
||||
@@ -1361,6 +1373,7 @@
|
||||
<area alias="user">
|
||||
<key alias="administrators">Администратор</key>
|
||||
<key alias="categoryField">Поле категории</key>
|
||||
<key alias="change">Изменить</key>
|
||||
<key alias="changePassword">Изменить пароль</key>
|
||||
<key alias="changePasswordDescription">Вы можете сменить свой пароль для доступа к административной панели Umbraco, заполнив нижеследующие поля и нажав на кнопку 'Изменить пароль'</key>
|
||||
<key alias="confirmNewPassword">Подтверждение нового пароля</key>
|
||||
|
||||
@@ -80,7 +80,7 @@
|
||||
|
||||
|
||||
<div id="feedbackMsg" data-bind="visible: processStatus() == 'complete'">
|
||||
<div data-bind="css: { success: isSuccessful(), error: !isSuccessful() }">
|
||||
<div data-bind="css: { 'text-success': isSuccessful(), 'text-error': !isSuccessful() }">
|
||||
<span data-bind="text: resultMessage, visible: resultMessages().length == 0"></span>
|
||||
<ul data-bind="foreach: resultMessages, visible: resultMessages().length > 1">
|
||||
<li data-bind="text: message"></li>
|
||||
|
||||
@@ -101,13 +101,13 @@ namespace Umbraco.Web.Cache
|
||||
ApplicationContext.Current.ApplicationCache.RuntimeCache.ClearCacheByKeySearch(CacheKeys.IdToKeyCacheKey);
|
||||
ApplicationContext.Current.ApplicationCache.RuntimeCache.ClearCacheByKeySearch(CacheKeys.KeyToIdCacheKey);
|
||||
|
||||
var dataTypeCache = ApplicationContext.Current.ApplicationCache.IsolatedRuntimeCache.GetCache<IDataTypeDefinition>();
|
||||
payloads.ForEach(payload =>
|
||||
{
|
||||
//clears the prevalue cache
|
||||
var dataTypeCache = ApplicationContext.Current.ApplicationCache.IsolatedRuntimeCache.GetCache<IDataTypeDefinition>();
|
||||
if (dataTypeCache)
|
||||
dataTypeCache.Result.ClearCacheByKeySearch(string.Format("{0}{1}", CacheKeys.DataTypePreValuesCacheKey, payload.Id));
|
||||
|
||||
dataTypeCache.Result.ClearCacheByKeySearch(string.Format("{0}_{1}", CacheKeys.DataTypePreValuesCacheKey, payload.Id));
|
||||
|
||||
PublishedContentType.ClearDataType(payload.Id);
|
||||
});
|
||||
|
||||
|
||||
@@ -64,7 +64,8 @@ namespace Umbraco.Web.HealthCheck.Checks.Security
|
||||
var url = HealthCheckContext.HttpContext.Request.Url;
|
||||
|
||||
// Access the site home page and check for the click-jack protection header or meta tag
|
||||
var useSsl = GlobalSettings.UseSSL || HealthCheckContext.HttpContext.Request.ServerVariables["SERVER_PORT"] == "443";
|
||||
var serverVariables = HealthCheckContext.HttpContext.Request.ServerVariables;
|
||||
var useSsl = GlobalSettings.UseSSL || serverVariables["SERVER_PORT"] == "443";
|
||||
var address = string.Format("http{0}://{1}:{2}", useSsl ? "s" : "", url.Host.ToLower(), url.Port);
|
||||
var request = WebRequest.Create(address);
|
||||
request.Method = "GET";
|
||||
|
||||
@@ -49,7 +49,8 @@ namespace Umbraco.Web.HealthCheck.Checks.Security
|
||||
var url = HealthCheckContext.HttpContext.Request.Url;
|
||||
|
||||
// Access the site home page and check for the headers
|
||||
var useSsl = GlobalSettings.UseSSL || HealthCheckContext.HttpContext.Request.ServerVariables["SERVER_PORT"] == "443";
|
||||
var serverVariables = HealthCheckContext.HttpContext.Request.ServerVariables;
|
||||
var useSsl = GlobalSettings.UseSSL || serverVariables["SERVER_PORT"] == "443";
|
||||
var address = string.Format("http{0}://{1}:{2}", useSsl ? "s" : "", url.Host.ToLower(), url.Port);
|
||||
var request = WebRequest.Create(address);
|
||||
request.Method = "HEAD";
|
||||
|
||||
@@ -48,12 +48,22 @@ namespace Umbraco.Web.HealthCheck
|
||||
return healthCheckGroups;
|
||||
}
|
||||
|
||||
[HttpGet]
|
||||
public object GetStatus(Guid id)
|
||||
{
|
||||
var check = _healthCheckResolver.HealthChecks.FirstOrDefault(x => x.Id == id);
|
||||
if (check == null) throw new InvalidOperationException("No health check found with ID " + id);
|
||||
|
||||
return check.GetStatus();
|
||||
try
|
||||
{
|
||||
//Core.Logging.LogHelper.Debug<HealthCheckController>("Running health check: " + check.Name);
|
||||
return check.GetStatus();
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Core.Logging.LogHelper.Error<HealthCheckController>("Exception in health check: " + check.Name, e);
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
[HttpPost]
|
||||
|
||||
@@ -19,7 +19,7 @@ namespace Umbraco.Web.HealthCheck
|
||||
/// </remarks>
|
||||
internal class HealthCheckResolver : LazyManyObjectsResolverBase<HealthCheckResolver, HealthCheck>, IHealthCheckResolver
|
||||
{
|
||||
public HealthCheckResolver(ILogger logger, Func<IEnumerable<Type>> lazyTypeList)
|
||||
public HealthCheckResolver(ILogger logger, Func<IEnumerable<Type>> lazyTypeList)
|
||||
: base(new HealthCheckServiceProvider(), logger, lazyTypeList, ObjectLifetimeScope.HttpRequest)
|
||||
{
|
||||
}
|
||||
@@ -51,7 +51,7 @@ namespace Umbraco.Web.HealthCheck
|
||||
new HealthCheckContext(new HttpContextWrapper(HttpContext.Current), UmbracoContext.Current)
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
//use normal ctor
|
||||
return Activator.CreateInstance(serviceType);
|
||||
}
|
||||
|
||||
@@ -36,7 +36,7 @@ namespace Umbraco.Web.Models.Mapping
|
||||
.ForMember(display => display.IsContainer, expression => expression.MapFrom(content => content.ContentType.IsContainer))
|
||||
.ForMember(display => display.IsChildOfListView, expression => expression.Ignore())
|
||||
.ForMember(display => display.Trashed, expression => expression.MapFrom(content => content.Trashed))
|
||||
.ForMember(display => display.PublishDate, expression => expression.MapFrom(content => GetPublishedDate(content, applicationContext)))
|
||||
.ForMember(display => display.PublishDate, expression => expression.MapFrom(content => GetPublishedDate(content)))
|
||||
.ForMember(display => display.TemplateAlias, expression => expression.MapFrom(content => content.Template.Alias))
|
||||
.ForMember(display => display.HasPublishedVersion, expression => expression.MapFrom(content => content.HasPublishedVersion))
|
||||
.ForMember(display => display.Urls,
|
||||
@@ -75,6 +75,12 @@ namespace Umbraco.Web.Models.Mapping
|
||||
.ForMember(dto => dto.Alias, expression => expression.Ignore());
|
||||
}
|
||||
|
||||
private static DateTime? GetPublishedDate(IContent content)
|
||||
{
|
||||
var date = ((Content) content).PublishedDate;
|
||||
return date == default (DateTime) ? (DateTime?) null : date;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Maps the generic tab with custom properties for content
|
||||
/// </summary>
|
||||
@@ -86,31 +92,9 @@ namespace Umbraco.Web.Models.Mapping
|
||||
private static void AfterMap(IContent content, ContentItemDisplay display, IDataTypeService dataTypeService,
|
||||
ILocalizedTextService localizedText, IContentTypeService contentTypeService)
|
||||
{
|
||||
//map the IsChildOfListView (this is actually if it is a descendant of a list view!)
|
||||
//TODO: Fix this shorthand .Ancestors() lookup, at least have an overload to use the current
|
||||
if (content.HasIdentity)
|
||||
{
|
||||
var ancesctorListView = content.Ancestors().FirstOrDefault(x => x.ContentType.IsContainer);
|
||||
display.IsChildOfListView = ancesctorListView != null;
|
||||
}
|
||||
else
|
||||
{
|
||||
//it's new so it doesn't have a path, so we need to look this up by it's parent + ancestors
|
||||
var parent = content.Parent();
|
||||
if (parent == null)
|
||||
{
|
||||
display.IsChildOfListView = false;
|
||||
}
|
||||
else if (parent.ContentType.IsContainer)
|
||||
{
|
||||
display.IsChildOfListView = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
var ancesctorListView = parent.Ancestors().FirstOrDefault(x => x.ContentType.IsContainer);
|
||||
display.IsChildOfListView = ancesctorListView != null;
|
||||
}
|
||||
}
|
||||
// map the IsChildOfListView (this is actually if it is a descendant of a list view!)
|
||||
var parent = content.Parent();
|
||||
display.IsChildOfListView = parent != null && (parent.ContentType.IsContainer || contentTypeService.HasContainerInPath(parent.Path));
|
||||
|
||||
//map the tree node url
|
||||
if (HttpContext.Current != null)
|
||||
@@ -223,26 +207,7 @@ namespace Umbraco.Web.Models.Mapping
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the published date value for the IContent object
|
||||
/// </summary>
|
||||
/// <param name="content"></param>
|
||||
/// <param name="applicationContext"></param>
|
||||
/// <returns></returns>
|
||||
private static DateTime? GetPublishedDate(IContent content, ApplicationContext applicationContext)
|
||||
{
|
||||
if (content.Published)
|
||||
{
|
||||
return content.UpdateDate;
|
||||
}
|
||||
if (content.HasPublishedVersion)
|
||||
{
|
||||
var published = applicationContext.Services.ContentService.GetPublishedVersion(content.Id);
|
||||
return published.UpdateDate;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
//TODO: This is horribly inneficient
|
||||
/// Creates the list of action buttons allowed for this user - Publish, Send to publish, save, unpublish returned as the button's 'letter'
|
||||
/// </summary>
|
||||
private class ActionButtonsResolver : ValueResolver<IContent, IEnumerable<char>>
|
||||
|
||||
@@ -41,7 +41,7 @@ namespace Umbraco.Web.Models.Mapping
|
||||
.ForMember(display => display.IsContainer, expression => expression.Ignore())
|
||||
.ForMember(display => display.HasPublishedVersion, expression => expression.Ignore())
|
||||
.ForMember(display => display.Tabs, expression => expression.ResolveUsing(new TabsAndPropertiesResolver(applicationContext.Services.TextService)))
|
||||
.AfterMap((media, display) => AfterMap(media, display, applicationContext.Services.DataTypeService, applicationContext.Services.TextService, applicationContext.ProfilingLogger.Logger));
|
||||
.AfterMap((media, display) => AfterMap(media, display, applicationContext.Services.DataTypeService, applicationContext.Services.TextService, applicationContext.Services.ContentTypeService, applicationContext.ProfilingLogger.Logger));
|
||||
|
||||
//FROM IMedia TO ContentItemBasic<ContentPropertyBasic, IMedia>
|
||||
config.CreateMap<IMedia, ContentItemBasic<ContentPropertyBasic, IMedia>>()
|
||||
@@ -64,34 +64,12 @@ namespace Umbraco.Web.Models.Mapping
|
||||
.ForMember(dto => dto.HasPublishedVersion, expression => expression.Ignore());
|
||||
}
|
||||
|
||||
private static void AfterMap(IMedia media, MediaItemDisplay display, IDataTypeService dataTypeService, ILocalizedTextService localizedText, ILogger logger)
|
||||
private static void AfterMap(IMedia media, MediaItemDisplay display, IDataTypeService dataTypeService, ILocalizedTextService localizedText, IContentTypeService contentTypeService, ILogger logger)
|
||||
{
|
||||
// Adapted from ContentModelMapper
|
||||
//map the IsChildOfListView (this is actually if it is a descendant of a list view!)
|
||||
//TODO: Fix this shorthand .Ancestors() lookup, at least have an overload to use the current
|
||||
if (media.HasIdentity)
|
||||
{
|
||||
var ancesctorListView = media.Ancestors().FirstOrDefault(x => x.ContentType.IsContainer);
|
||||
display.IsChildOfListView = ancesctorListView != null;
|
||||
}
|
||||
else
|
||||
{
|
||||
//it's new so it doesn't have a path, so we need to look this up by it's parent + ancestors
|
||||
var parent = media.Parent();
|
||||
if (parent == null)
|
||||
{
|
||||
display.IsChildOfListView = false;
|
||||
}
|
||||
else if (parent.ContentType.IsContainer)
|
||||
{
|
||||
display.IsChildOfListView = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
var ancesctorListView = parent.Ancestors().FirstOrDefault(x => x.ContentType.IsContainer);
|
||||
display.IsChildOfListView = ancesctorListView != null;
|
||||
}
|
||||
}
|
||||
// Adapted from ContentModelMapper
|
||||
//map the IsChildOfListView (this is actually if it is a descendant of a list view!)
|
||||
var parent = media.Parent();
|
||||
display.IsChildOfListView = parent != null && (parent.ContentType.IsContainer || contentTypeService.HasContainerInPath(parent.Path));
|
||||
|
||||
//map the tree node url
|
||||
if (HttpContext.Current != null)
|
||||
|
||||
@@ -175,6 +175,7 @@ namespace Umbraco.Web.Mvc
|
||||
public IModelBinder GetBinder(Type modelType)
|
||||
{
|
||||
// can bind to RenderModel (exact type match)
|
||||
// You might be tempted to change this to IRenderModel but do not change this: http://issues.umbraco.org/issue/U4-8216
|
||||
if (modelType == typeof(RenderModel)) return this;
|
||||
|
||||
// can bind to RenderModel<TContent> (exact generic type match)
|
||||
|
||||
@@ -4,6 +4,7 @@ using System.Linq;
|
||||
using System.Xml;
|
||||
using System.Xml.Serialization;
|
||||
using System.Xml.XPath;
|
||||
using umbraco;
|
||||
using Umbraco.Core;
|
||||
using Umbraco.Core.Configuration;
|
||||
using Umbraco.Core.Models;
|
||||
@@ -315,9 +316,9 @@ namespace Umbraco.Web.PublishedCache.XmlPublishedCache
|
||||
|
||||
private void InitializeNode()
|
||||
{
|
||||
InitializeNode(_xmlNode, UmbracoConfig.For.UmbracoSettings().Content.UseLegacyXmlSchema, _isPreviewing,
|
||||
out _id, out _key, out _template, out _sortOrder, out _name, out _writerName,
|
||||
out _urlName, out _creatorName, out _creatorId, out _writerId, out _docTypeAlias, out _docTypeId, out _path,
|
||||
InitializeNode(_xmlNode, UmbracoConfig.For.UmbracoSettings().Content.UseLegacyXmlSchema, _isPreviewing,
|
||||
out _id, out _key, out _template, out _sortOrder, out _name, out _writerName,
|
||||
out _urlName, out _creatorName, out _creatorId, out _writerId, out _docTypeAlias, out _docTypeId, out _path,
|
||||
out _version, out _createDate, out _updateDate, out _level, out _isDraft, out _contentType, out _properties,
|
||||
PublishedContentType.Get);
|
||||
|
||||
@@ -345,7 +346,7 @@ namespace Umbraco.Web.PublishedCache.XmlPublishedCache
|
||||
|
||||
//return if this is null
|
||||
if (xmlNode == null)
|
||||
{
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -407,8 +408,8 @@ namespace Umbraco.Web.PublishedCache.XmlPublishedCache
|
||||
}
|
||||
|
||||
//dictionary to store the property node data
|
||||
var propertyNodes = new Dictionary<string, XmlNode>();
|
||||
|
||||
var propertyNodes = new Dictionary<string, XmlNode>();
|
||||
|
||||
foreach (XmlNode n in xmlNode.ChildNodes)
|
||||
{
|
||||
var e = n as XmlElement;
|
||||
@@ -432,7 +433,22 @@ namespace Umbraco.Web.PublishedCache.XmlPublishedCache
|
||||
}
|
||||
|
||||
//lookup the content type and create the properties collection
|
||||
contentType = getPublishedContentType(PublishedItemType.Content, docTypeAlias);
|
||||
try
|
||||
{
|
||||
contentType = getPublishedContentType(PublishedItemType.Content, docTypeAlias);
|
||||
|
||||
}
|
||||
catch (InvalidOperationException e)
|
||||
{
|
||||
content.Instance.RefreshContentFromDatabase();
|
||||
|
||||
|
||||
throw new InvalidOperationException(
|
||||
string.Format("{0}. This usually indicates that the content cache is corrupt; the content cache has been rebuilt in an attempt to self-fix the issue.",
|
||||
//keep the original message but don't use this as an inner exception because we want the above message to be displayed, if we use the inner exception
|
||||
//we can keep the stack trace but the header message will be the original message and the one we really want to display will be hidden below the fold.
|
||||
e.Message));
|
||||
}
|
||||
properties = new Dictionary<string, IPublishedProperty>(StringComparer.OrdinalIgnoreCase);
|
||||
|
||||
//fill in the property collection
|
||||
|
||||
@@ -8,6 +8,7 @@ namespace Umbraco.Web.Search
|
||||
[DataContract(Name = "indexer", Namespace = "")]
|
||||
public class ExamineIndexerModel : ExamineSearcherModel
|
||||
{
|
||||
|
||||
[DataMember(Name = "indexCriteria")]
|
||||
public IIndexCriteria IndexCriteria { get; set; }
|
||||
|
||||
|
||||
@@ -14,6 +14,18 @@ namespace Umbraco.Web.Search
|
||||
ProviderProperties = new Dictionary<string, string>();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// If the index is not healthy this represents the index error state
|
||||
/// </summary>
|
||||
[DataMember(Name = "error")]
|
||||
public string Error { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// If the index can be open/read
|
||||
/// </summary>
|
||||
[DataMember(Name = "isHealthy")]
|
||||
public bool IsHealthy { get; set; }
|
||||
|
||||
[DataMember(Name = "name")]
|
||||
public string Name { get; set; }
|
||||
|
||||
|
||||
@@ -15,6 +15,28 @@ namespace Umbraco.Web.Search
|
||||
/// </summary>
|
||||
internal static class ExamineExtensions
|
||||
{
|
||||
/// <summary>
|
||||
/// Checks if the index can be read/opened
|
||||
/// </summary>
|
||||
/// <param name="indexer"></param>
|
||||
/// <param name="ex">The exception returned if there was an error</param>
|
||||
/// <returns></returns>
|
||||
public static bool IsHealthy(this LuceneIndexer indexer, out Exception ex)
|
||||
{
|
||||
try
|
||||
{
|
||||
using (indexer.GetIndexWriter().GetReader())
|
||||
{
|
||||
ex = null;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
ex = e;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Return the number of indexed documents in Lucene
|
||||
|
||||
@@ -112,8 +112,8 @@
|
||||
<Reference Include="dotless.Core, Version=1.4.1.0, Culture=neutral, PublicKeyToken=96b446c9e63eae34, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\dotless.1.4.1.0\lib\dotless.Core.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Examine, Version=0.1.81.0, Culture=neutral, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\Examine.0.1.81\lib\net45\Examine.dll</HintPath>
|
||||
<Reference Include="Examine, Version=0.1.82.0, Culture=neutral, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\Examine.0.1.82\lib\net45\Examine.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="HtmlAgilityPack, Version=1.4.9.0, Culture=neutral, PublicKeyToken=bd319b19eaf3b43a, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\HtmlAgilityPack.1.4.9\lib\Net45\HtmlAgilityPack.dll</HintPath>
|
||||
|
||||
@@ -1389,10 +1389,15 @@ namespace Umbraco.Web
|
||||
return test ? new HtmlString(valueIfTrue) : new HtmlString(string.Empty);
|
||||
}
|
||||
|
||||
#endregion
|
||||
#endregion
|
||||
|
||||
#region Prevalues
|
||||
|
||||
/// <summary>
|
||||
/// Gets a specific PreValue by its Id
|
||||
/// </summary>
|
||||
/// <param name="id">Id of the PreValue to retrieve the value from</param>
|
||||
/// <returns>PreValue as a string</returns>
|
||||
public string GetPreValueAsString(int id)
|
||||
{
|
||||
return DataTypeService.GetPreValueAsString(id);
|
||||
|
||||
@@ -579,6 +579,15 @@ namespace Umbraco.Web
|
||||
// is complete and cancel this current event so the rebuild process doesn't start right now.
|
||||
args.Cancel = true;
|
||||
IndexesToRebuild.Add((BaseIndexProvider)args.Indexer);
|
||||
|
||||
//check if the index is rebuilding due to an error and log it
|
||||
if (args.IsHealthy == false)
|
||||
{
|
||||
var baseIndex = args.Indexer as BaseIndexProvider;
|
||||
var name = baseIndex != null ? baseIndex.Name : "[UKNOWN]";
|
||||
|
||||
ProfilingLogger.Logger.Error<WebBootManager>(string.Format("The index {0} is rebuilding due to being unreadable/corrupt", name), args.UnhealthyException);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -46,16 +46,16 @@ namespace Umbraco.Web.WebServices
|
||||
/*var result = ((ContentService) Services.ContentService)
|
||||
.PublishWithChildrenInternal(content, UmbracoUser.Id, includeUnpublished)
|
||||
.ToArray();*/
|
||||
var result = doc.PublishWithSubs(UmbracoUser.Id, includeUnpublished);
|
||||
var result = doc.PublishWithSubs(UmbracoUser.Id, includeUnpublished).ToArray();
|
||||
return Json(new
|
||||
{
|
||||
success = result.All(x => x.Success),
|
||||
message = GetMessageForStatuses(result.Select(x => x.Result), content)
|
||||
message = GetMessageForStatuses(result.Select(x => x.Result).ToArray(), content)
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
private string GetMessageForStatuses(IEnumerable<PublishStatus> statuses, IContent doc)
|
||||
private string GetMessageForStatuses(PublishStatus[] statuses, IContent doc)
|
||||
{
|
||||
//if all are successful then just say it was successful
|
||||
if (statuses.All(x => ((int) x.StatusType) < 10))
|
||||
@@ -91,12 +91,12 @@ namespace Umbraco.Web.WebServices
|
||||
return "Cannot publish document with a status of " + status.StatusType;
|
||||
case PublishStatusType.FailedCancelledByEvent:
|
||||
return ui.Text("publish", "contentPublishedFailedByEvent",
|
||||
string.Format("{0} ({1})", status.ContentItem.Name, status.ContentItem.Id), UmbracoUser);
|
||||
string.Format("'{0}' ({1})", status.ContentItem.Name, status.ContentItem.Id), UmbracoUser);
|
||||
case PublishStatusType.FailedContentInvalid:
|
||||
return ui.Text("publish", "contentPublishedFailedInvalid",
|
||||
new []{
|
||||
string.Format("{0} ({1})", status.ContentItem.Name, status.ContentItem.Id),
|
||||
string.Join(",", status.InvalidProperties.Select(x => x.Alias))
|
||||
string.Format("'{0}' ({1})", status.ContentItem.Name, status.ContentItem.Id),
|
||||
string.Format("'{0}'", string.Join(", ", status.InvalidProperties.Select(x => x.Alias)))
|
||||
},
|
||||
UmbracoUser);
|
||||
default:
|
||||
|
||||
@@ -86,7 +86,7 @@ namespace Umbraco.Web.WebServices
|
||||
var model = new List<ExamineSearcherModel>(
|
||||
ExamineManager.Instance.SearchProviderCollection.Cast<BaseSearchProvider>().Select(searcher =>
|
||||
{
|
||||
var indexerModel = new ExamineIndexerModel()
|
||||
var indexerModel = new ExamineSearcherModel()
|
||||
{
|
||||
Name = searcher.Name
|
||||
};
|
||||
@@ -260,6 +260,7 @@ namespace Umbraco.Web.WebServices
|
||||
IndexCriteria = indexer.IndexerData,
|
||||
Name = indexer.Name
|
||||
};
|
||||
|
||||
var props = TypeHelper.CachedDiscoverableProperties(indexer.GetType(), mustWrite: false)
|
||||
//ignore these properties
|
||||
.Where(x => new[] {"IndexerData", "Description", "WorkingFolder"}.InvariantContains(x.Name) == false)
|
||||
@@ -281,11 +282,21 @@ namespace Umbraco.Web.WebServices
|
||||
|
||||
var luceneIndexer = indexer as LuceneIndexer;
|
||||
if (luceneIndexer != null)
|
||||
{
|
||||
{
|
||||
indexerModel.IsLuceneIndex = true;
|
||||
|
||||
if (luceneIndexer.IndexExists())
|
||||
{
|
||||
Exception indexError;
|
||||
indexerModel.IsHealthy = luceneIndexer.IsHealthy(out indexError);
|
||||
|
||||
if (indexerModel.IsHealthy == false)
|
||||
{
|
||||
//we cannot continue at this point
|
||||
indexerModel.Error = indexError.ToString();
|
||||
return indexerModel;
|
||||
}
|
||||
|
||||
indexerModel.DocumentCount = luceneIndexer.GetIndexDocumentCount();
|
||||
indexerModel.FieldCount = luceneIndexer.GetIndexFieldCount();
|
||||
indexerModel.IsOptimized = luceneIndexer.IsIndexOptimized();
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
<package id="AutoMapper" version="3.3.1" targetFramework="net45" />
|
||||
<package id="ClientDependency" version="1.9.2" targetFramework="net45" />
|
||||
<package id="dotless" version="1.4.1.0" targetFramework="net45" />
|
||||
<package id="Examine" version="0.1.81" targetFramework="net45" />
|
||||
<package id="Examine" version="0.1.82" targetFramework="net45" />
|
||||
<package id="HtmlAgilityPack" version="1.4.9" targetFramework="net45" />
|
||||
<package id="Lucene.Net" version="2.9.4.1" targetFramework="net45" />
|
||||
<package id="Markdown" version="1.14.7" targetFramework="net45" />
|
||||
|
||||
@@ -431,7 +431,7 @@ namespace umbraco
|
||||
{
|
||||
XmlNode x;
|
||||
|
||||
//Hack: this is here purely for backwards compat if someone for some reason is using the
|
||||
//Hack: this is here purely for backwards compat if someone for some reason is using the
|
||||
// ClearDocumentCache(int documentId) method and expecting it to remove the xml
|
||||
if (removeDbXmlEntry)
|
||||
{
|
||||
@@ -870,8 +870,15 @@ namespace umbraco
|
||||
catch (Exception e)
|
||||
{
|
||||
// if something goes wrong remove the file
|
||||
DeleteXmlFile();
|
||||
|
||||
try
|
||||
{
|
||||
DeleteXmlFile();
|
||||
}
|
||||
catch
|
||||
{
|
||||
// don't make it worse: could be that we failed to write because we cannot
|
||||
// access the file, in which case we won't be able to delete it either
|
||||
}
|
||||
LogHelper.Error<content>("Failed to save Xml to file.", e);
|
||||
}
|
||||
}
|
||||
@@ -933,7 +940,15 @@ namespace umbraco
|
||||
catch (Exception e)
|
||||
{
|
||||
LogHelper.Error<content>("Failed to load Xml from file.", e);
|
||||
DeleteXmlFile();
|
||||
try
|
||||
{
|
||||
DeleteXmlFile();
|
||||
}
|
||||
catch
|
||||
{
|
||||
// don't make it worse: could be that we failed to read because we cannot
|
||||
// access the file, in which case we won't be able to delete it either
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -99,7 +99,7 @@ namespace umbraco.presentation.preview
|
||||
//Inject preview xml
|
||||
parentId = document.Level == 1 ? -1 : document.ParentId;
|
||||
var previewXml = document.ToPreviewXml(XmlContent);
|
||||
if (document.ContentEntity.Published == false
|
||||
if (document.ContentEntity.Published == false
|
||||
&& ApplicationContext.Current.Services.ContentService.HasPublishedVersion(document.Id))
|
||||
previewXml.Attributes.Append(XmlContent.CreateAttribute("isDraft"));
|
||||
XmlContent = content.GetAddOrUpdateXmlNode(XmlContent, document.Id, document.Level, parentId, previewXml);
|
||||
@@ -187,13 +187,9 @@ namespace umbraco.presentation.preview
|
||||
|
||||
private static void CleanPreviewDirectory(int userId, DirectoryInfo dir)
|
||||
{
|
||||
foreach (FileInfo file in dir.GetFiles(userId + "_*.config"))
|
||||
{
|
||||
DeletePreviewFile(userId, file);
|
||||
}
|
||||
// also delete any files accessed more than 10 minutes ago
|
||||
var now = DateTime.Now;
|
||||
foreach (FileInfo file in dir.GetFiles("*.config"))
|
||||
foreach (var file in dir.GetFiles("*.config"))
|
||||
{
|
||||
if ((now - file.LastAccessTime).TotalMinutes > 10)
|
||||
DeletePreviewFile(userId, file);
|
||||
@@ -206,6 +202,12 @@ namespace umbraco.presentation.preview
|
||||
{
|
||||
file.Delete();
|
||||
}
|
||||
catch (IOException)
|
||||
{
|
||||
// for *some* reason deleting the file can fail,
|
||||
// and it will work later on (long-lasting locks, etc),
|
||||
// so just ignore the exception
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogHelper.Error<PreviewContent>(string.Format("Couldn't delete preview set: {0} - User {1}", file.Name, userId), ex);
|
||||
|
||||
@@ -36,6 +36,7 @@ namespace UmbracoExamine
|
||||
private readonly IUserService _userService;
|
||||
private readonly IContentTypeService _contentTypeService;
|
||||
private readonly EntityXmlSerializer _serializer = new EntityXmlSerializer();
|
||||
private const int PageSize = 10000;
|
||||
|
||||
#region Constructors
|
||||
|
||||
@@ -407,8 +408,7 @@ namespace UmbracoExamine
|
||||
{
|
||||
if (SupportedTypes.Contains(type) == false)
|
||||
return;
|
||||
|
||||
const int pageSize = 10000;
|
||||
|
||||
var pageIndex = 0;
|
||||
|
||||
DataService.LogService.AddInfoLog(-1, string.Format("PerformIndexAll - Start data queries - {0}", type));
|
||||
@@ -444,6 +444,7 @@ namespace UmbracoExamine
|
||||
|
||||
//sorted by: umbracoNode.level, umbracoNode.parentID, umbracoNode.sortOrder
|
||||
var result = _contentService.GetPagedXmlEntries(path, pIndex, pSize, out totalContent).ToArray();
|
||||
var more = result.Length == pSize;
|
||||
|
||||
//then like we do in the ContentRepository.BuildXmlCache we need to track what Parents have been processed
|
||||
// already so that we can then exclude implicitly unpublished content items
|
||||
@@ -479,7 +480,7 @@ namespace UmbracoExamine
|
||||
filtered.Add(xml);
|
||||
}
|
||||
|
||||
return new Tuple<long, XElement[]>(totalContent, filtered.ToArray());
|
||||
return Tuple.Create(filtered.ToArray(), more);
|
||||
},
|
||||
i => _contentService.GetById(i));
|
||||
}
|
||||
@@ -497,13 +498,13 @@ namespace UmbracoExamine
|
||||
IContent[] descendants;
|
||||
if (SupportUnpublishedContent)
|
||||
{
|
||||
descendants = _contentService.GetPagedDescendants(contentParentId, pageIndex, pageSize, out total, "umbracoNode.id").ToArray();
|
||||
descendants = _contentService.GetPagedDescendants(contentParentId, pageIndex, PageSize, out total, "umbracoNode.id").ToArray();
|
||||
}
|
||||
else
|
||||
{
|
||||
//get all paged records but order by level ascending, we need to do this because we need to track which nodes are not published so that we can determine
|
||||
// which descendent nodes are implicitly not published
|
||||
descendants = _contentService.GetPagedDescendants(contentParentId, pageIndex, pageSize, out total, "level", Direction.Ascending, true, (string)null).ToArray();
|
||||
descendants = _contentService.GetPagedDescendants(contentParentId, pageIndex, PageSize, out total, "level", Direction.Ascending, true, (string)null).ToArray();
|
||||
}
|
||||
|
||||
// need to store decendants count before filtering, in order for loop to work correctly
|
||||
@@ -527,7 +528,7 @@ namespace UmbracoExamine
|
||||
content, notPublished).WhereNotNull(), type);
|
||||
|
||||
pageIndex++;
|
||||
} while (currentPageSize == pageSize);
|
||||
} while (currentPageSize == PageSize);
|
||||
}
|
||||
|
||||
break;
|
||||
@@ -545,7 +546,8 @@ namespace UmbracoExamine
|
||||
{
|
||||
long totalMedia;
|
||||
var result = _mediaService.GetPagedXmlEntries(path, pIndex, pSize, out totalMedia).ToArray();
|
||||
return new Tuple<long, XElement[]>(totalMedia, result);
|
||||
var more = result.Length == pSize;
|
||||
return Tuple.Create(result, more);
|
||||
},
|
||||
i => _mediaService.GetById(i));
|
||||
|
||||
@@ -573,39 +575,37 @@ namespace UmbracoExamine
|
||||
string type,
|
||||
int parentId,
|
||||
Func<TContentType[]> getContentTypes,
|
||||
Func<string, int, int, Tuple<long, XElement[]>> getPagedXmlEntries,
|
||||
Func<string, int, int, Tuple<XElement[], bool>> getPagedXmlEntries,
|
||||
Func<int, IContentBase> getContent)
|
||||
where TContentType: IContentTypeComposition
|
||||
{
|
||||
const int pageSize = 10000;
|
||||
var pageIndex = 0;
|
||||
|
||||
XElement[] xElements;
|
||||
var pageIndex = 0;
|
||||
|
||||
var contentTypes = getContentTypes();
|
||||
var icons = contentTypes.ToDictionary(x => x.Id, y => y.Icon);
|
||||
var parent = parentId == -1 ? null : getContent(parentId);
|
||||
bool more;
|
||||
|
||||
do
|
||||
{
|
||||
long total;
|
||||
XElement[] xElements;
|
||||
|
||||
if (parentId == -1)
|
||||
{
|
||||
var pagedElements = getPagedXmlEntries("-1", pageIndex, pageSize);
|
||||
total = pagedElements.Item1;
|
||||
xElements = pagedElements.Item2;
|
||||
var pagedElements = getPagedXmlEntries("-1", pageIndex, PageSize);
|
||||
xElements = pagedElements.Item1;
|
||||
more = pagedElements.Item2;
|
||||
}
|
||||
else if (parent == null)
|
||||
{
|
||||
xElements = new XElement[0];
|
||||
more = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
//Get the parent
|
||||
var parent = getContent(parentId);
|
||||
if (parent == null)
|
||||
xElements = new XElement[0];
|
||||
else
|
||||
{
|
||||
var pagedElements = getPagedXmlEntries(parent.Path, pageIndex, pageSize);
|
||||
total = pagedElements.Item1;
|
||||
xElements = pagedElements.Item2;
|
||||
}
|
||||
var pagedElements = getPagedXmlEntries(parent.Path, pageIndex, PageSize);
|
||||
xElements = pagedElements.Item1;
|
||||
more = pagedElements.Item2;
|
||||
}
|
||||
|
||||
//if specific types are declared we need to post filter them
|
||||
@@ -626,7 +626,7 @@ namespace UmbracoExamine
|
||||
|
||||
AddNodesToIndex(xElements, type);
|
||||
pageIndex++;
|
||||
} while (xElements.Length == pageSize);
|
||||
} while (more);
|
||||
}
|
||||
|
||||
internal static IEnumerable<XElement> GetSerializedContent(
|
||||
|
||||
@@ -82,8 +82,8 @@
|
||||
<AssemblyOriginatorKeyFile>..\Solution Items\TheFARM-Public.snk</AssemblyOriginatorKeyFile>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="Examine, Version=0.1.81.0, Culture=neutral, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\Examine.0.1.81\lib\net45\Examine.dll</HintPath>
|
||||
<Reference Include="Examine, Version=0.1.82.0, Culture=neutral, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\Examine.0.1.82\lib\net45\Examine.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="ICSharpCode.SharpZipLib, Version=0.86.0.518, Culture=neutral, PublicKeyToken=1b03e6acf1164f73, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\SharpZipLib.0.86.0\lib\20\ICSharpCode.SharpZipLib.dll</HintPath>
|
||||
|
||||
@@ -117,7 +117,7 @@ namespace UmbracoExamine
|
||||
if (indexerData.UserFields.Any(x => x.Name == "_searchEmail") == false)
|
||||
{
|
||||
var field = new IndexField { Name = "_searchEmail" };
|
||||
|
||||
|
||||
StaticField policy;
|
||||
if (IndexFieldPolicies.TryGetValue("_searchEmail", out policy))
|
||||
{
|
||||
@@ -173,7 +173,8 @@ namespace UmbracoExamine
|
||||
{
|
||||
long totalContent;
|
||||
var result = _memberService.GetPagedXmlEntries(pIndex, pSize, out totalContent).ToArray();
|
||||
return new Tuple<long, XElement[]>(totalContent, result);
|
||||
var more = result.Length == pSize;
|
||||
return Tuple.Create(result, more);
|
||||
},
|
||||
i => _memberService.GetById(i));
|
||||
}
|
||||
@@ -219,7 +220,7 @@ namespace UmbracoExamine
|
||||
{
|
||||
stopwatch.Stop();
|
||||
}
|
||||
|
||||
|
||||
DataService.LogService.AddInfoLog(-1, string.Format("PerformIndexAll - End data queries - {0}, took {1}ms", type, stopwatch.ElapsedMilliseconds));
|
||||
}
|
||||
|
||||
@@ -247,7 +248,7 @@ namespace UmbracoExamine
|
||||
fields.Add("__key", valuesForIndexing);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
return fields;
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<packages>
|
||||
<package id="Examine" version="0.1.81" targetFramework="net45" />
|
||||
<package id="Examine" version="0.1.82" targetFramework="net45" />
|
||||
<package id="Lucene.Net" version="2.9.4.1" targetFramework="net45" />
|
||||
<package id="SharpZipLib" version="0.86.0" targetFramework="net45" />
|
||||
</packages>
|
||||
@@ -1,6 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<packages>
|
||||
<package id="Examine" version="0.1.81" targetFramework="net45" />
|
||||
<package id="Examine" version="0.1.82" targetFramework="net45" />
|
||||
<package id="HtmlAgilityPack" version="1.4.9" targetFramework="net45" />
|
||||
<package id="Lucene.Net" version="2.9.4.1" targetFramework="net45" />
|
||||
<package id="Microsoft.AspNet.Mvc" version="5.2.3" targetFramework="net45" />
|
||||
|
||||
@@ -45,8 +45,8 @@
|
||||
<Prefer32Bit>false</Prefer32Bit>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="Examine, Version=0.1.81.0, Culture=neutral, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\Examine.0.1.81\lib\net45\Examine.dll</HintPath>
|
||||
<Reference Include="Examine, Version=0.1.82.0, Culture=neutral, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\Examine.0.1.82\lib\net45\Examine.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="HtmlAgilityPack, Version=1.4.9.0, Culture=neutral, PublicKeyToken=bd319b19eaf3b43a, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\HtmlAgilityPack.1.4.9\lib\Net45\HtmlAgilityPack.dll</HintPath>
|
||||
|
||||
@@ -43,23 +43,28 @@ namespace umbraco.cms.businesslogic.packager.standardPackageActions
|
||||
|
||||
if (xmlData.HasChildNodes)
|
||||
{
|
||||
string sectionAlias = xmlData.Attributes["dashboardAlias"].Value;
|
||||
string dbConfig = SystemFiles.DashboardConfig;
|
||||
string sectionAlias = xmlData.Attributes["dashboardAlias"].Value;
|
||||
string dbConfig = SystemFiles.DashboardConfig;
|
||||
|
||||
XmlNode section = xmlData.SelectSingleNode("./section");
|
||||
XmlDocument dashboardFile = XmlHelper.OpenAsXmlDocument(dbConfig);
|
||||
XmlNode section = xmlData.SelectSingleNode("./section");
|
||||
XmlDocument dashboardFile = XmlHelper.OpenAsXmlDocument(dbConfig);
|
||||
|
||||
XmlNode importedSection = dashboardFile.ImportNode(section, true);
|
||||
//don't continue if it already exists
|
||||
var found = dashboardFile.SelectNodes("//section[@alias='" + sectionAlias + "']");
|
||||
if (found == null || found.Count <= 0)
|
||||
{
|
||||
XmlNode importedSection = dashboardFile.ImportNode(section, true);
|
||||
|
||||
XmlAttribute alias = XmlHelper.AddAttribute(dashboardFile, "alias", sectionAlias);
|
||||
importedSection.Attributes.Append(alias);
|
||||
XmlAttribute alias = XmlHelper.AddAttribute(dashboardFile, "alias", sectionAlias);
|
||||
importedSection.Attributes.Append(alias);
|
||||
|
||||
dashboardFile.DocumentElement.AppendChild(importedSection);
|
||||
dashboardFile.DocumentElement.AppendChild(importedSection);
|
||||
|
||||
dashboardFile.Save(IOHelper.MapPath(dbConfig));
|
||||
dashboardFile.Save(IOHelper.MapPath(dbConfig));
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -302,7 +302,11 @@ namespace umbraco.cms.businesslogic.packager
|
||||
XmlHelper.SetAttribute(Source, xmlDef, "enableSkins", package.EnableSkins.ToString());
|
||||
XmlHelper.SetAttribute(Source, xmlDef, "skinRepoGuid", package.SkinRepoGuid.ToString());
|
||||
XmlHelper.SetAttribute(Source, xmlDef, "iconUrl", package.IconUrl);
|
||||
XmlHelper.SetAttribute(Source, xmlDef, "umbVersion", package.UmbracoVersion.ToString(3));
|
||||
if (package.UmbracoVersion != null)
|
||||
{
|
||||
XmlHelper.SetAttribute(Source, xmlDef, "umbVersion", package.UmbracoVersion.ToString(3));
|
||||
}
|
||||
|
||||
|
||||
var licenseNode = xmlDef.SelectSingleNode("license");
|
||||
if (licenseNode == null)
|
||||
|
||||
@@ -874,18 +874,15 @@ namespace umbraco.cms.businesslogic.web
|
||||
[Obsolete("Don't use! Only used internally to support the legacy events", false)]
|
||||
internal IEnumerable<Attempt<PublishStatus>> PublishWithSubs(int userId, bool includeUnpublished)
|
||||
{
|
||||
PublishEventArgs e = new PublishEventArgs();
|
||||
var e = new PublishEventArgs();
|
||||
FireBeforePublish(e);
|
||||
|
||||
IEnumerable<Attempt<PublishStatus>> publishedResults = Enumerable.Empty<Attempt<PublishStatus>>();
|
||||
if (e.Cancel) return Enumerable.Empty<Attempt<PublishStatus>>();
|
||||
|
||||
if (!e.Cancel)
|
||||
{
|
||||
publishedResults = ApplicationContext.Current.Services.ContentService
|
||||
.PublishWithChildrenWithStatus(ContentEntity, userId, includeUnpublished);
|
||||
var publishedResults = ApplicationContext.Current.Services.ContentService
|
||||
.PublishWithChildrenWithStatus(ContentEntity, userId, includeUnpublished);
|
||||
|
||||
FireAfterPublish(e);
|
||||
}
|
||||
FireAfterPublish(e);
|
||||
|
||||
return publishedResults;
|
||||
}
|
||||
@@ -893,7 +890,6 @@ namespace umbraco.cms.businesslogic.web
|
||||
[Obsolete("Don't use! Only used internally to support the legacy events", false)]
|
||||
internal Attempt<PublishStatus> SaveAndPublish(int userId)
|
||||
{
|
||||
var result = Attempt.Fail(new PublishStatus(ContentEntity, PublishStatusType.FailedCancelledByEvent, new EventMessages()));
|
||||
foreach (var property in GenericProperties)
|
||||
{
|
||||
ContentEntity.SetValue(property.PropertyType.Alias, property.Value);
|
||||
@@ -901,32 +897,28 @@ namespace umbraco.cms.businesslogic.web
|
||||
|
||||
var saveArgs = new SaveEventArgs();
|
||||
FireBeforeSave(saveArgs);
|
||||
if (saveArgs.Cancel) return Attempt.Fail(new PublishStatus(ContentEntity, PublishStatusType.FailedCancelledByEvent, new EventMessages()));
|
||||
|
||||
if (!saveArgs.Cancel)
|
||||
{
|
||||
var publishArgs = new PublishEventArgs();
|
||||
FireBeforePublish(publishArgs);
|
||||
var publishArgs = new PublishEventArgs();
|
||||
FireBeforePublish(publishArgs);
|
||||
if (publishArgs.Cancel) return Attempt.Fail(new PublishStatus(ContentEntity, PublishStatusType.FailedCancelledByEvent, new EventMessages()));
|
||||
|
||||
if (!publishArgs.Cancel)
|
||||
{
|
||||
//NOTE: The 'false' parameter will cause the PublishingStrategy events to fire which will ensure that the cache is refreshed.
|
||||
result = ApplicationContext.Current.Services.ContentService
|
||||
.SaveAndPublishWithStatus(ContentEntity, userId);
|
||||
base.VersionDate = ContentEntity.UpdateDate;
|
||||
this.UpdateDate = ContentEntity.UpdateDate;
|
||||
//NOTE: The 'false' parameter will cause the PublishingStrategy events to fire which will ensure that the cache is refreshed.
|
||||
var result = ApplicationContext.Current.Services.ContentService
|
||||
.SaveAndPublishWithStatus(ContentEntity, userId);
|
||||
VersionDate = ContentEntity.UpdateDate;
|
||||
UpdateDate = ContentEntity.UpdateDate;
|
||||
|
||||
//NOTE: This is just going to call the CMSNode Save which will launch into the CMSNode.BeforeSave and CMSNode.AfterSave evenths
|
||||
// which actually do dick all and there's no point in even having them there but just in case for some insane reason someone
|
||||
// has bound to those events, I suppose we'll need to keep this here.
|
||||
base.Save();
|
||||
//NOTE: This is just going to call the CMSNode Save which will launch into the CMSNode.BeforeSave and CMSNode.AfterSave evenths
|
||||
// which actually do dick all and there's no point in even having them there but just in case for some insane reason someone
|
||||
// has bound to those events, I suppose we'll need to keep this here.
|
||||
base.Save();
|
||||
|
||||
//Launch the After Save event since we're doing 2 things in one operation: Saving and publishing.
|
||||
FireAfterSave(saveArgs);
|
||||
//Launch the After Save event since we're doing 2 things in one operation: Saving and publishing.
|
||||
FireAfterSave(saveArgs);
|
||||
|
||||
//Now we need to fire the After publish event
|
||||
FireAfterPublish(publishArgs);
|
||||
}
|
||||
}
|
||||
//Now we need to fire the After publish event
|
||||
FireAfterPublish(publishArgs);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user