Compare commits
97 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 32ad98cde2 | |||
| f4b1df1ede | |||
| 2b0f2577b5 | |||
| a39557a3a7 | |||
| 2239316889 | |||
| d3582e2296 | |||
| 1a37d88855 | |||
| 2d5ffabe1e | |||
| f61b7579a2 | |||
| 86a3780c61 | |||
| 552909fde2 | |||
| 7adae4d345 | |||
| d747cf69c3 | |||
| bc5e3b4d66 | |||
| febeb82d10 | |||
| 1c2b2c1409 | |||
| b4eb9f333e | |||
| af00a421cd | |||
| fed06c88e8 | |||
| 5dec2861d9 | |||
| 23b3bb37ee | |||
| 4dabb606e7 | |||
| d5f66ebe02 | |||
| c7783d1cd1 | |||
| 2104b109f2 | |||
| 578ca7d41d | |||
| bd38dde1fc | |||
| 42c23da9f5 | |||
| cab1536a30 | |||
| 33d35fd9f7 | |||
| cc885c1231 | |||
| 422dd1a627 | |||
| 759e444624 | |||
| 2a7ef5de26 | |||
| 43e892563d | |||
| 4d1e64b279 | |||
| 975c97cfb0 | |||
| 0c613347ae | |||
| 83f75fdaff | |||
| 487792920b | |||
| 6ae06ad2e0 | |||
| 8387c435d4 | |||
| 5807bbccc4 | |||
| 1bfc041bbe | |||
| a5ca058cb2 | |||
| 88a1ad04aa | |||
| e619c402b4 | |||
| c9294e5281 | |||
| f5a204d1de | |||
| 7c049b55a8 | |||
| 051b3f2e6a | |||
| 21f947efbd | |||
| a68f4e284a | |||
| 90b43584d2 | |||
| 9461e35028 | |||
| d554417fde | |||
| eedcfc122b | |||
| 8cf3110708 | |||
| dbe489c0f2 | |||
| 2652a583e0 | |||
| bc1758f569 | |||
| a898c2d697 | |||
| e612bcae58 | |||
| 9c5526f281 | |||
| 9c803cc234 | |||
| f24fd42a69 | |||
| 9b7f459c44 | |||
| 273a5cef28 | |||
| 7da7c1e5a1 | |||
| a20cc60c10 | |||
| 846ac573cc | |||
| 122295c89f | |||
| 0e727f91da | |||
| 179523224a | |||
| 19e4bee34e | |||
| f1709f6066 | |||
| f2be235f85 | |||
| d97cc36c53 | |||
| db86f6e1ee | |||
| a03e0dfb53 | |||
| ff6ea0b42e | |||
| 384a31e3c6 | |||
| 69b913c608 | |||
| 83757c60b5 | |||
| e95cb14d48 | |||
| 8d598cd37c | |||
| 30c2f95844 | |||
| 0078a5d8cc | |||
| 09085e3bcf | |||
| a31b03b3e2 | |||
| 9ef53536bf | |||
| 547351a719 | |||
| 371c4ae1a3 | |||
| 060137c798 | |||
| a5af5ba1a9 | |||
| ca1f43d048 | |||
| e962a48138 |
@@ -1,3 +1,3 @@
|
||||
# Usage: on line 2 put the release version, on line 3 put the version comment (example: beta)
|
||||
7.6.0
|
||||
alpha063
|
||||
alpha070
|
||||
|
||||
+1
-1
@@ -12,4 +12,4 @@ using System.Resources;
|
||||
[assembly: AssemblyVersion("1.0.*")]
|
||||
|
||||
[assembly: AssemblyFileVersion("7.6.0")]
|
||||
[assembly: AssemblyInformationalVersion("7.6.0-alpha063")]
|
||||
[assembly: AssemblyInformationalVersion("7.6.0-alpha070")]
|
||||
@@ -0,0 +1,15 @@
|
||||
using System;
|
||||
|
||||
namespace Umbraco.Core.CodeAnnotations
|
||||
{
|
||||
[AttributeUsage(AttributeTargets.Field, AllowMultiple = false, Inherited = false)]
|
||||
internal class UmbracoUdiTypeAttribute : Attribute
|
||||
{
|
||||
public string UdiType { get; private set; }
|
||||
|
||||
public UmbracoUdiTypeAttribute(string udiType)
|
||||
{
|
||||
UdiType = udiType;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -159,6 +159,12 @@ namespace Umbraco.Core.Configuration.UmbracoSettings
|
||||
get { return GetOptionalTextElement("defaultDocumentTypeProperty", "Textstring"); }
|
||||
}
|
||||
|
||||
[ConfigurationProperty("showDeprecatedPropertyEditors")]
|
||||
internal InnerTextConfigurationElement<bool> ShowDeprecatedPropertyEditors
|
||||
{
|
||||
get { return GetOptionalTextElement("showDeprecatedPropertyEditors", false); }
|
||||
}
|
||||
|
||||
[ConfigurationProperty("EnableInheritedDocumentTypes")]
|
||||
internal InnerTextConfigurationElement<bool> EnableInheritedDocumentTypes
|
||||
{
|
||||
@@ -306,6 +312,11 @@ namespace Umbraco.Core.Configuration.UmbracoSettings
|
||||
get { return DefaultDocumentTypeProperty; }
|
||||
}
|
||||
|
||||
bool IContentSection.ShowDeprecatedPropertyEditors
|
||||
{
|
||||
get { return ShowDeprecatedPropertyEditors; }
|
||||
}
|
||||
|
||||
bool IContentSection.EnableInheritedDocumentTypes
|
||||
{
|
||||
get { return EnableInheritedDocumentTypes; }
|
||||
|
||||
@@ -60,6 +60,12 @@ namespace Umbraco.Core.Configuration.UmbracoSettings
|
||||
|
||||
string DefaultDocumentTypeProperty { get; }
|
||||
|
||||
/// <summary>
|
||||
/// The default for this is false but if you would like deprecated property editors displayed
|
||||
/// in the data type editor you can enable this
|
||||
/// </summary>
|
||||
bool ShowDeprecatedPropertyEditors { get; }
|
||||
|
||||
bool EnableInheritedDocumentTypes { get; }
|
||||
|
||||
bool EnableInheritedMediaTypes { get; }
|
||||
|
||||
@@ -24,7 +24,7 @@ namespace Umbraco.Core.Configuration
|
||||
/// Gets the version comment (like beta or RC).
|
||||
/// </summary>
|
||||
/// <value>The version comment.</value>
|
||||
public static string CurrentComment { get { return "alpha063"; } }
|
||||
public static string CurrentComment { get { return "alpha070"; } }
|
||||
|
||||
// Get the version of the umbraco.dll by looking at a class in that dll
|
||||
// Had to do it like this due to medium trust issues, see: http://haacked.com/archive/2010/11/04/assembly-location-and-medium-trust.aspx
|
||||
|
||||
@@ -109,6 +109,11 @@ namespace Umbraco.Core
|
||||
/// </summary>
|
||||
public const string Member = "39EB0F98-B348-42A1-8662-E7EB18487560";
|
||||
|
||||
/// <summary>
|
||||
/// Guid for a Media Type object.
|
||||
/// </summary>
|
||||
public static readonly Guid MemberGuid = new Guid(Member);
|
||||
|
||||
/// <summary>
|
||||
/// Guid for a Member Group object.
|
||||
/// </summary>
|
||||
|
||||
@@ -42,10 +42,14 @@ namespace Umbraco.Core
|
||||
[Obsolete("GUIDs are no longer used to reference Property Editors, use the Alias constant instead. This will be removed in future versions")]
|
||||
public const string ContentPicker = "158AA029-24ED-4948-939E-C3DA209E5FBA";
|
||||
|
||||
|
||||
[Obsolete("This is an obsoleted content picker, use ContentPicker2Alias instead")]
|
||||
public const string ContentPickerAlias = "Umbraco.ContentPickerAlias";
|
||||
|
||||
/// <summary>
|
||||
/// Alias for the Content Picker datatype.
|
||||
/// </summary>
|
||||
public const string ContentPickerAlias = "Umbraco.ContentPickerAlias";
|
||||
public const string ContentPicker2Alias = "Umbraco.ContentPicker2";
|
||||
|
||||
/// <summary>
|
||||
/// Guid for the Date datatype.
|
||||
@@ -192,11 +196,15 @@ namespace Umbraco.Core
|
||||
[Obsolete("GUIDs are no longer used to reference Property Editors, use the Alias constant instead. This will be removed in future versions")]
|
||||
public const string MediaPicker = "EAD69342-F06D-4253-83AC-28000225583B";
|
||||
|
||||
[Obsolete("This is an obsoleted picker, use MediaPicker2Alias instead")]
|
||||
public const string MediaPickerAlias = "Umbraco.MediaPicker";
|
||||
|
||||
/// <summary>
|
||||
/// Alias for the Media Picker datatype.
|
||||
/// </summary>
|
||||
public const string MediaPickerAlias = "Umbraco.MediaPicker";
|
||||
public const string MediaPicker2Alias = "Umbraco.MediaPicker2";
|
||||
|
||||
[Obsolete("This is an obsoleted picker, use MediaPicker2Alias instead")]
|
||||
public const string MultipleMediaPickerAlias = "Umbraco.MultipleMediaPicker";
|
||||
|
||||
/// <summary>
|
||||
@@ -205,26 +213,32 @@ namespace Umbraco.Core
|
||||
[Obsolete("GUIDs are no longer used to reference Property Editors, use the Alias constant instead. This will be removed in future versions")]
|
||||
public const string MemberPicker = "39F533E4-0551-4505-A64B-E0425C5CE775";
|
||||
|
||||
[Obsolete("This is an obsoleted picker, use MemberPicker2Alias instead")]
|
||||
public const string MemberPickerAlias = "Umbraco.MemberPicker";
|
||||
|
||||
/// <summary>
|
||||
/// Alias for the Member Picker datatype.
|
||||
/// </summary>
|
||||
public const string MemberPickerAlias = "Umbraco.MemberPicker";
|
||||
public const string MemberPicker2Alias = "Umbraco.MemberPicker2";
|
||||
|
||||
/// <summary>
|
||||
/// Alias for the Member Group Picker datatype.
|
||||
/// </summary>
|
||||
public const string MemberGroupPickerAlias = "Umbraco.MemberGroupPicker";
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Guid for the Multi-Node Tree Picker datatype
|
||||
/// </summary>
|
||||
[Obsolete("GUIDs are no longer used to reference Property Editors, use the Alias constant instead. This will be removed in future versions")]
|
||||
public const string MultiNodeTreePicker = "7E062C13-7C41-4AD9-B389-41D88AEEF87C";
|
||||
|
||||
[Obsolete("This is an obsoleted picker, use MultiNodeTreePicker2Alias instead")]
|
||||
public const string MultiNodeTreePickerAlias = "Umbraco.MultiNodeTreePicker";
|
||||
|
||||
/// <summary>
|
||||
/// Alias for the Multi-Node Tree Picker datatype
|
||||
/// </summary>
|
||||
public const string MultiNodeTreePickerAlias = "Umbraco.MultiNodeTreePicker";
|
||||
public const string MultiNodeTreePicker2Alias = "Umbraco.MultiNodeTreePicker2";
|
||||
|
||||
/// <summary>
|
||||
/// Guid for the Multiple Textstring datatype.
|
||||
|
||||
@@ -16,6 +16,7 @@ namespace Umbraco.Core.Deploy
|
||||
if (udi == null)
|
||||
throw new ArgumentNullException("udi");
|
||||
Udi = udi;
|
||||
Name = Udi.ToString();
|
||||
|
||||
Dependencies = dependencies ?? Enumerable.Empty<ArtifactDependency>();
|
||||
_checksum = new Lazy<string>(GetChecksum);
|
||||
@@ -48,5 +49,8 @@ namespace Umbraco.Core.Deploy
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
public string Name { get; set; }
|
||||
public string Alias { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -4,5 +4,8 @@ namespace Umbraco.Core.Deploy
|
||||
/// Represents an artifact ie an object that can be transfered between environments.
|
||||
/// </summary>
|
||||
public interface IArtifact : IArtifactSignature
|
||||
{ }
|
||||
{
|
||||
string Name { get; }
|
||||
string Alias { get; }
|
||||
}
|
||||
}
|
||||
@@ -66,10 +66,20 @@ namespace Umbraco.Core.Deploy
|
||||
/// <returns>The length of the file, or -1 if the file does not exist.</returns>
|
||||
Task<long> GetFileLengthAsync(StringUdi udi, CancellationToken token);
|
||||
|
||||
// fixme - doc
|
||||
void GetFiles(IEnumerable<StringUdi> udis, IFileStore fileStore);
|
||||
/// <summary>
|
||||
/// Gets files and store them using a file store.
|
||||
/// </summary>
|
||||
/// <param name="udis">The udis of the files to get.</param>
|
||||
/// <param name="fileTypes">A collection of file types which can store the files.</param>
|
||||
void GetFiles(IEnumerable<StringUdi> udis, IFileTypeCollection fileTypes);
|
||||
|
||||
Task GetFilesAsync(IEnumerable<StringUdi> udis, IFileStore fileStore, CancellationToken token);
|
||||
/// <summary>
|
||||
/// Gets files and store them using a file store.
|
||||
/// </summary>
|
||||
/// <param name="udis">The udis of the files to get.</param>
|
||||
/// <param name="fileTypes">A collection of file types which can store the files.</param>
|
||||
/// <param name="token">A cancellation token.</param>
|
||||
Task GetFilesAsync(IEnumerable<StringUdi> udis, IFileTypeCollection fileTypes, CancellationToken token);
|
||||
|
||||
///// <summary>
|
||||
///// Gets the content of a file as a bytes array.
|
||||
|
||||
@@ -1,9 +0,0 @@
|
||||
using System.IO;
|
||||
|
||||
namespace Umbraco.Core.Deploy
|
||||
{
|
||||
public interface IFileStore
|
||||
{
|
||||
void SaveStream(StringUdi udi, Stream stream);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
using System.IO;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Umbraco.Core.Deploy
|
||||
{
|
||||
public interface IFileType
|
||||
{
|
||||
Stream GetStream(StringUdi udi);
|
||||
|
||||
Task<Stream> GetStreamAsync(StringUdi udi, CancellationToken token);
|
||||
|
||||
Stream GetChecksumStream(StringUdi udi);
|
||||
|
||||
long GetLength(StringUdi udi);
|
||||
|
||||
void SetStream(StringUdi udi, Stream stream);
|
||||
|
||||
Task SetStreamAsync(StringUdi udi, Stream stream, CancellationToken token);
|
||||
|
||||
bool CanSetPhysical { get; }
|
||||
|
||||
void Set(StringUdi udi, string physicalPath, bool copy = false);
|
||||
|
||||
// this is not pretty as *everywhere* in Deploy we take care of ignoring
|
||||
// the physical path and always rely on Core's virtual IFileSystem but
|
||||
// Cloud wants to add some of these files to Git and needs the path...
|
||||
string GetPhysicalPath(StringUdi udi);
|
||||
|
||||
string GetVirtualPath(StringUdi udi);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
namespace Umbraco.Core.Deploy
|
||||
{
|
||||
public interface IFileTypeCollection
|
||||
{
|
||||
IFileType this[string entityType] { get; }
|
||||
|
||||
bool Contains(string entityType);
|
||||
}
|
||||
}
|
||||
@@ -1,8 +0,0 @@
|
||||
namespace Umbraco.Core.Deploy
|
||||
{
|
||||
public interface IPrettyArtifact
|
||||
{
|
||||
string Name { get; }
|
||||
string Alias { get; }
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,7 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
@@ -67,22 +68,15 @@ namespace Umbraco.Core
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>The for each.</summary>
|
||||
/// <param name="items">The items.</param>
|
||||
/// <param name="func">The func.</param>
|
||||
/// <typeparam name="TItem">item type</typeparam>
|
||||
/// <typeparam name="TResult">Result type</typeparam>
|
||||
/// <returns>the Results</returns>
|
||||
[EditorBrowsable(EditorBrowsableState.Never)]
|
||||
[Obsolete("Use a normal foreach loop instead, this adds more allocations than necessary")]
|
||||
public static TResult[] ForEach<TItem, TResult>(this IEnumerable<TItem> items, Func<TItem, TResult> func)
|
||||
{
|
||||
return items.Select(func).ToArray();
|
||||
}
|
||||
|
||||
/// <summary>The for each.</summary>
|
||||
/// <param name="items">The items.</param>
|
||||
/// <param name="action">The action.</param>
|
||||
/// <typeparam name="TItem">Item type</typeparam>
|
||||
/// <returns>list of TItem</returns>
|
||||
[EditorBrowsable(EditorBrowsableState.Never)]
|
||||
[Obsolete("Use a normal foreach loop instead, this adds more allocations than necessary")]
|
||||
public static IEnumerable<TItem> ForEach<TItem>(this IEnumerable<TItem> items, Action<TItem> action)
|
||||
{
|
||||
if (items != null)
|
||||
@@ -101,6 +95,7 @@ namespace Umbraco.Core
|
||||
/// <param name="f">The select child.</param>
|
||||
/// <typeparam name="T">Item type</typeparam>
|
||||
/// <returns>list of TItem</returns>
|
||||
[EditorBrowsable(EditorBrowsableState.Never)]
|
||||
[Obsolete("Do not use, use SelectRecursive instead which has far less potential of re-iterating an iterator which may cause significantly more SQL queries")]
|
||||
public static IEnumerable<T> FlattenList<T>(this IEnumerable<T> e, Func<T, IEnumerable<T>> f)
|
||||
{
|
||||
|
||||
@@ -0,0 +1,58 @@
|
||||
using System;
|
||||
using Umbraco.Core.Scoping;
|
||||
|
||||
namespace Umbraco.Core.Events
|
||||
{
|
||||
/// <summary>
|
||||
/// Stores the instance of EventMessages in the current scope.
|
||||
/// </summary>
|
||||
internal class ScopeLifespanMessagesFactory : IEventMessagesFactory
|
||||
{
|
||||
public const string ContextKey = "Umbraco.Core.Events.ScopeLifespanMessagesFactory";
|
||||
|
||||
private readonly IHttpContextAccessor _contextAccessor;
|
||||
private readonly IScopeProviderInternal _scopeProvider;
|
||||
|
||||
public static ScopeLifespanMessagesFactory Current { get; private set; }
|
||||
|
||||
public ScopeLifespanMessagesFactory(IHttpContextAccessor contextAccesor, IScopeProvider scopeProvider)
|
||||
{
|
||||
if (contextAccesor == null) throw new ArgumentNullException("contextAccesor");
|
||||
if (scopeProvider == null) throw new ArgumentNullException("scopeProvider");
|
||||
if (scopeProvider is IScopeProviderInternal == false) throw new ArgumentException("Not IScopeProviderInternal.", "scopeProvider");
|
||||
_contextAccessor = contextAccesor;
|
||||
_scopeProvider = (IScopeProviderInternal) scopeProvider;
|
||||
Current = this;
|
||||
}
|
||||
|
||||
public EventMessages Get()
|
||||
{
|
||||
var messages = GetFromHttpContext();
|
||||
if (messages != null) return messages;
|
||||
|
||||
var scope = _scopeProvider.GetAmbientOrNoScope();
|
||||
return scope.Messages;
|
||||
}
|
||||
|
||||
public EventMessages GetFromHttpContext()
|
||||
{
|
||||
if (_contextAccessor == null || _contextAccessor.Value == null) return null;
|
||||
return (EventMessages)_contextAccessor.Value.Items[ContextKey];
|
||||
}
|
||||
|
||||
public EventMessages TryGet()
|
||||
{
|
||||
var messages = GetFromHttpContext();
|
||||
if (messages != null) return messages;
|
||||
|
||||
var scope = _scopeProvider.AmbientScope;
|
||||
return scope == null ? null : scope.MessagesOrNull;
|
||||
}
|
||||
|
||||
public void Set(EventMessages messages)
|
||||
{
|
||||
if (_contextAccessor.Value == null) return;
|
||||
_contextAccessor.Value.Items[ContextKey] = messages;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
using System.Web;
|
||||
|
||||
namespace Umbraco.Core
|
||||
{
|
||||
public interface IHttpContextAccessor
|
||||
{
|
||||
HttpContextBase Value { get; }
|
||||
}
|
||||
}
|
||||
@@ -2,6 +2,7 @@
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text.RegularExpressions;
|
||||
|
||||
namespace Umbraco.Core.IO
|
||||
{
|
||||
@@ -209,19 +210,20 @@ namespace Umbraco.Core.IO
|
||||
|
||||
public IEnumerable<string> GetFiles(string path)
|
||||
{
|
||||
var normPath = NormPath(path);
|
||||
var shadows = Nodes.Where(kvp => IsChild(normPath, kvp.Key)).ToArray();
|
||||
var files = _fs.GetFiles(path);
|
||||
return files
|
||||
.Except(shadows.Where(kvp => (kvp.Value.IsFile && kvp.Value.IsDelete) || kvp.Value.IsDir)
|
||||
.Select(kvp => kvp.Key))
|
||||
.Union(shadows.Where(kvp => kvp.Value.IsFile && kvp.Value.IsExist).Select(kvp => kvp.Key))
|
||||
.Distinct();
|
||||
return GetFiles(path, null);
|
||||
}
|
||||
|
||||
public IEnumerable<string> GetFiles(string path, string filter)
|
||||
{
|
||||
return _fs.GetFiles(path, filter);
|
||||
var normPath = NormPath(path);
|
||||
var shadows = Nodes.Where(kvp => IsChild(normPath, kvp.Key)).ToArray();
|
||||
var files = filter != null ? _fs.GetFiles(path, filter) : _fs.GetFiles(path);
|
||||
var regexFilter = FilterToRegex(filter);
|
||||
return files
|
||||
.Except(shadows.Where(kvp => (kvp.Value.IsFile && kvp.Value.IsDelete) || kvp.Value.IsDir)
|
||||
.Select(kvp => kvp.Key))
|
||||
.Union(shadows.Where(kvp => kvp.Value.IsFile && kvp.Value.IsExist && FilterByRegex(kvp.Key, regexFilter)).Select(kvp => kvp.Key))
|
||||
.Distinct();
|
||||
}
|
||||
|
||||
public Stream OpenFile(string path)
|
||||
@@ -253,6 +255,9 @@ namespace Umbraco.Core.IO
|
||||
|
||||
public string GetFullPath(string path)
|
||||
{
|
||||
ShadowNode sf;
|
||||
if (Nodes.TryGetValue(NormPath(path), out sf))
|
||||
return sf.IsDir || sf.IsDelete ? null : _sfs.GetFullPath(path);
|
||||
return _fs.GetFullPath(path);
|
||||
}
|
||||
|
||||
@@ -321,5 +326,32 @@ namespace Umbraco.Core.IO
|
||||
_sfs.AddFile(path, physicalPath, overrideIfExists, copy);
|
||||
Nodes[normPath] = new ShadowNode(false, false);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Helper function for filtering keys by Regex if a filter is specified.
|
||||
/// </summary>
|
||||
/// <param name="input"></param>
|
||||
/// <param name="regexFilter"></param>
|
||||
/// <returns></returns>
|
||||
internal static bool FilterByRegex(string input, string regexFilter)
|
||||
{
|
||||
if (regexFilter == null) return true;
|
||||
return regexFilter != string.Empty && Regex.IsMatch(input, regexFilter);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Transforms a filter pattern into a Regex pattern
|
||||
/// </summary>
|
||||
/// <param name="pattern"></param>
|
||||
/// <returns></returns>
|
||||
/// <remarks>
|
||||
/// Appending '$' only if not containing wildcard is stupid and broken.
|
||||
/// It is however what seems to be what they're doing in .NET so we need to match the functionality.
|
||||
/// </remarks>
|
||||
internal static string FilterToRegex(string pattern)
|
||||
{
|
||||
if (pattern == null) return null;
|
||||
return "^" + Regex.Escape(pattern).Replace("\\*", ".*").Replace("\\?", ".") + (pattern.Contains("*") ? string.Empty : "$");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -27,7 +27,7 @@ namespace Umbraco.Core.IO
|
||||
// on ShadowFileSystemsScope.None - and if None is false then we should be running
|
||||
// in a single thread anyways
|
||||
|
||||
var virt = "~/App_Data/Shadow/" + id + "/" + _shadowPath;
|
||||
var virt = "~/App_Data/TEMP/ShadowFs/" + id + "/" + _shadowPath;
|
||||
_shadowDir = IOHelper.MapPath(virt);
|
||||
Directory.CreateDirectory(_shadowDir);
|
||||
var tempfs = new PhysicalFileSystem(virt);
|
||||
|
||||
@@ -30,7 +30,8 @@ namespace Umbraco.Core.Models
|
||||
return descendants;
|
||||
}
|
||||
|
||||
throw new NotSupportedException("The content type must be " + typeof(IContentType) + " or " + typeof(IMediaType));
|
||||
//No other content types have children (i.e. member types)
|
||||
return Enumerable.Empty<IContentTypeBase>();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -13,6 +13,7 @@ namespace Umbraco.Core.Models.Identity
|
||||
public override void ConfigureMappings(IConfiguration config, ApplicationContext applicationContext)
|
||||
{
|
||||
config.CreateMap<IUser, BackOfficeIdentityUser>()
|
||||
.ForMember(user => user.LastLoginDateUtc, expression => expression.MapFrom(user => user.LastLoginDate.ToUniversalTime()))
|
||||
.ForMember(user => user.Email, expression => expression.MapFrom(user => user.Email))
|
||||
.ForMember(user => user.Id, expression => expression.MapFrom(user => user.Id))
|
||||
.ForMember(user => user.LockoutEndDateUtc, expression => expression.MapFrom(user => user.IsLockedOut ? DateTime.MaxValue.ToUniversalTime() : (DateTime?)null))
|
||||
|
||||
@@ -24,12 +24,17 @@ namespace Umbraco.Core.Models.Identity
|
||||
///
|
||||
/// </summary>
|
||||
public IdentityUser()
|
||||
{
|
||||
{
|
||||
this.Claims = new List<TClaim>();
|
||||
this.Roles = new List<TRole>();
|
||||
this.Logins = new List<TLogin>();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Last login date
|
||||
/// </summary>
|
||||
public virtual DateTime? LastLoginDateUtc { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Email
|
||||
///
|
||||
|
||||
@@ -9,7 +9,7 @@ namespace Umbraco.Core.Models.Rdbms
|
||||
internal class DataTypePreValueDto
|
||||
{
|
||||
[Column("id")]
|
||||
[PrimaryKeyColumn(IdentitySeed = 6)]
|
||||
[PrimaryKeyColumn(IdentitySeed = 10)]
|
||||
public int Id { get; set; }
|
||||
|
||||
[Column("datatypeNodeId")]
|
||||
|
||||
@@ -15,6 +15,7 @@ namespace Umbraco.Core.Models.Rdbms
|
||||
|
||||
[Column("nodeId")]
|
||||
[ForeignKey(typeof(NodeDto))]
|
||||
[Index(IndexTypes.NonClustered, Name = "IX_umbracoUser2NodePermission_nodeId")]
|
||||
public int NodeId { get; set; }
|
||||
|
||||
[Column("permission")]
|
||||
|
||||
@@ -113,6 +113,11 @@ namespace Umbraco.Core.Models
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// When resolved from EntityService this checks if the entity has the HasChildren flag
|
||||
/// </summary>
|
||||
/// <param name="entity"></param>
|
||||
/// <returns></returns>
|
||||
public static bool HasChildren(this IUmbracoEntity entity)
|
||||
{
|
||||
if (entity.AdditionalData.ContainsKey("HasChildren"))
|
||||
@@ -133,6 +138,11 @@ namespace Umbraco.Core.Models
|
||||
return entity.AdditionalData.GetValueIgnoreCase(key, defaultVal);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// When resolved from EntityService this checks if the entity has the IsContainer flag
|
||||
/// </summary>
|
||||
/// <param name="entity"></param>
|
||||
/// <returns></returns>
|
||||
public static bool IsContainer(this IUmbracoEntity entity)
|
||||
{
|
||||
if (entity.AdditionalData.ContainsKeyIgnoreCase("IsContainer") == false) return false;
|
||||
|
||||
@@ -26,7 +26,7 @@ namespace Umbraco.Core.Models
|
||||
/// <summary>
|
||||
/// Root
|
||||
/// </summary>
|
||||
[UmbracoObjectType(Constants.ObjectTypes.SystemRoot)]
|
||||
[UmbracoObjectType(Constants.ObjectTypes.SystemRoot)]
|
||||
[FriendlyName("Root")]
|
||||
ROOT,
|
||||
|
||||
@@ -35,6 +35,7 @@ namespace Umbraco.Core.Models
|
||||
/// </summary>
|
||||
[UmbracoObjectType(Constants.ObjectTypes.Document, typeof(IContent))]
|
||||
[FriendlyName("Document")]
|
||||
[UmbracoUdiType(Constants.UdiEntityType.Document)]
|
||||
Document,
|
||||
|
||||
/// <summary>
|
||||
@@ -42,6 +43,7 @@ namespace Umbraco.Core.Models
|
||||
/// </summary>
|
||||
[UmbracoObjectType(Constants.ObjectTypes.Media, typeof(IMedia))]
|
||||
[FriendlyName("Media")]
|
||||
[UmbracoUdiType(Constants.UdiEntityType.Media)]
|
||||
Media,
|
||||
|
||||
/// <summary>
|
||||
@@ -49,6 +51,7 @@ namespace Umbraco.Core.Models
|
||||
/// </summary>
|
||||
[UmbracoObjectType(Constants.ObjectTypes.MemberType, typeof(IMemberType))]
|
||||
[FriendlyName("Member Type")]
|
||||
[UmbracoUdiType(Constants.UdiEntityType.MemberType)]
|
||||
MemberType,
|
||||
|
||||
/// <summary>
|
||||
@@ -56,6 +59,7 @@ namespace Umbraco.Core.Models
|
||||
/// </summary>
|
||||
[UmbracoObjectType(Constants.ObjectTypes.Template, typeof(ITemplate))]
|
||||
[FriendlyName("Template")]
|
||||
[UmbracoUdiType(Constants.UdiEntityType.Template)]
|
||||
Template,
|
||||
|
||||
/// <summary>
|
||||
@@ -63,6 +67,7 @@ namespace Umbraco.Core.Models
|
||||
/// </summary>
|
||||
[UmbracoObjectType(Constants.ObjectTypes.MemberGroup)]
|
||||
[FriendlyName("Member Group")]
|
||||
[UmbracoUdiType(Constants.UdiEntityType.MemberGroup)]
|
||||
MemberGroup,
|
||||
|
||||
//TODO: What is a 'Content Item' supposed to be???
|
||||
@@ -80,6 +85,7 @@ namespace Umbraco.Core.Models
|
||||
/// </summary>
|
||||
[UmbracoObjectType(Constants.ObjectTypes.MediaType, typeof(IMediaType))]
|
||||
[FriendlyName("Media Type")]
|
||||
[UmbracoUdiType(Constants.UdiEntityType.MediaType)]
|
||||
MediaType,
|
||||
|
||||
/// <summary>
|
||||
@@ -87,13 +93,14 @@ namespace Umbraco.Core.Models
|
||||
/// </summary>
|
||||
[UmbracoObjectType(Constants.ObjectTypes.DocumentType, typeof(IContentType))]
|
||||
[FriendlyName("Document Type")]
|
||||
[UmbracoUdiType(Constants.UdiEntityType.DocumentType)]
|
||||
DocumentType,
|
||||
|
||||
/// <summary>
|
||||
/// Recycle Bin
|
||||
/// </summary>
|
||||
[UmbracoObjectType(Constants.ObjectTypes.ContentRecycleBin)]
|
||||
[FriendlyName("Recycle Bin")]
|
||||
[FriendlyName("Recycle Bin")]
|
||||
RecycleBin,
|
||||
|
||||
/// <summary>
|
||||
@@ -101,6 +108,7 @@ namespace Umbraco.Core.Models
|
||||
/// </summary>
|
||||
[UmbracoObjectType(Constants.ObjectTypes.Stylesheet)]
|
||||
[FriendlyName("Stylesheet")]
|
||||
[UmbracoUdiType(Constants.UdiEntityType.Stylesheet)]
|
||||
Stylesheet,
|
||||
|
||||
/// <summary>
|
||||
@@ -108,6 +116,7 @@ namespace Umbraco.Core.Models
|
||||
/// </summary>
|
||||
[UmbracoObjectType(Constants.ObjectTypes.Member, typeof(IMember))]
|
||||
[FriendlyName("Member")]
|
||||
[UmbracoUdiType(Constants.UdiEntityType.Member)]
|
||||
Member,
|
||||
|
||||
/// <summary>
|
||||
@@ -115,6 +124,7 @@ namespace Umbraco.Core.Models
|
||||
/// </summary>
|
||||
[UmbracoObjectType(Constants.ObjectTypes.DataType, typeof(IDataTypeDefinition))]
|
||||
[FriendlyName("Data Type")]
|
||||
[UmbracoUdiType(Constants.UdiEntityType.DataType)]
|
||||
DataType,
|
||||
|
||||
/// <summary>
|
||||
@@ -122,6 +132,7 @@ namespace Umbraco.Core.Models
|
||||
/// </summary>
|
||||
[UmbracoObjectType(Constants.ObjectTypes.DocumentTypeContainer)]
|
||||
[FriendlyName("Document Type Container")]
|
||||
[UmbracoUdiType(Constants.UdiEntityType.DocumentTypeContainer)]
|
||||
DocumentTypeContainer,
|
||||
|
||||
/// <summary>
|
||||
@@ -129,6 +140,7 @@ namespace Umbraco.Core.Models
|
||||
/// </summary>
|
||||
[UmbracoObjectType(Constants.ObjectTypes.MediaTypeContainer)]
|
||||
[FriendlyName("Media Type Container")]
|
||||
[UmbracoUdiType(Constants.UdiEntityType.MediaTypeContainer)]
|
||||
MediaTypeContainer,
|
||||
|
||||
/// <summary>
|
||||
@@ -136,6 +148,7 @@ namespace Umbraco.Core.Models
|
||||
/// </summary>
|
||||
[UmbracoObjectType(Constants.ObjectTypes.DataTypeContainer)]
|
||||
[FriendlyName("Data Type Container")]
|
||||
[UmbracoUdiType(Constants.UdiEntityType.DataTypeContainer)]
|
||||
DataTypeContainer,
|
||||
|
||||
/// <summary>
|
||||
@@ -143,6 +156,7 @@ namespace Umbraco.Core.Models
|
||||
/// </summary>
|
||||
[UmbracoObjectType(Constants.ObjectTypes.RelationType)]
|
||||
[FriendlyName("Relation Type")]
|
||||
[UmbracoUdiType(Constants.UdiEntityType.RelationType)]
|
||||
RelationType,
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -12,6 +12,7 @@ namespace Umbraco.Core.Models
|
||||
{
|
||||
//MUST be concurrent to avoid thread collisions!
|
||||
private static readonly ConcurrentDictionary<UmbracoObjectTypes, Guid> UmbracoObjectTypeCache = new ConcurrentDictionary<UmbracoObjectTypes, Guid>();
|
||||
private static readonly ConcurrentDictionary<UmbracoObjectTypes, string> UmbracoObjectTypeUdiCache = new ConcurrentDictionary<UmbracoObjectTypes, string>();
|
||||
|
||||
/// <summary>
|
||||
/// Get an UmbracoObjectTypes value from it's name
|
||||
@@ -43,6 +44,21 @@ namespace Umbraco.Core.Models
|
||||
return umbracoObjectType;
|
||||
}
|
||||
|
||||
public static string GetUdiType(Guid guid)
|
||||
{
|
||||
var umbracoObjectType = Constants.UdiEntityType.Unknown;
|
||||
|
||||
foreach (var name in Enum.GetNames(typeof(UmbracoObjectTypes)))
|
||||
{
|
||||
var objType = GetUmbracoObjectType(name);
|
||||
if (objType.GetGuid() == guid)
|
||||
{
|
||||
umbracoObjectType = GetUdiType(objType);
|
||||
}
|
||||
}
|
||||
return umbracoObjectType;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Extension method for the UmbracoObjectTypes enum to return the enum GUID
|
||||
/// </summary>
|
||||
@@ -68,6 +84,26 @@ namespace Umbraco.Core.Models
|
||||
});
|
||||
}
|
||||
|
||||
public static string GetUdiType(this UmbracoObjectTypes umbracoObjectType)
|
||||
{
|
||||
return UmbracoObjectTypeUdiCache.GetOrAdd(umbracoObjectType, types =>
|
||||
{
|
||||
var type = typeof(UmbracoObjectTypes);
|
||||
var memInfo = type.GetMember(umbracoObjectType.ToString());
|
||||
var attributes = memInfo[0].GetCustomAttributes(typeof(UmbracoUdiTypeAttribute),
|
||||
false);
|
||||
|
||||
if (attributes.Length == 0)
|
||||
return Constants.UdiEntityType.Unknown;
|
||||
|
||||
var attribute = ((UmbracoUdiTypeAttribute)attributes[0]);
|
||||
if (attribute == null)
|
||||
return Constants.UdiEntityType.Unknown;
|
||||
|
||||
return attribute.UdiType;
|
||||
});
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Extension method for the UmbracoObjectTypes enum to return the enum name
|
||||
/// </summary>
|
||||
|
||||
@@ -50,7 +50,7 @@ namespace Umbraco.Core.Persistence.Factories
|
||||
entity.ContentTypeThumbnail = asDictionary.ContainsKey("thumbnail") ? (d.thumbnail ?? string.Empty) : string.Empty;
|
||||
|
||||
var publishedVersion = default(Guid);
|
||||
//some content items don't have a published version
|
||||
//some content items don't have a published/newest version
|
||||
if (asDictionary.ContainsKey("publishedVersion") && asDictionary["publishedVersion"] != null)
|
||||
{
|
||||
Guid.TryParse(d.publishedVersion.ToString(), out publishedVersion);
|
||||
|
||||
@@ -130,21 +130,21 @@ namespace Umbraco.Core.Persistence.Migrations.Initial
|
||||
_database.Insert("umbracoNode", "id", false, new NodeDto { NodeId = Constants.System.DefaultMembersListViewDataTypeId, Trashed = false, ParentId = -1, UserId = 0, Level = 1, Path = "-1,-97", SortOrder = 2, UniqueId = new Guid("AA2C52A0-CE87-4E65-A47C-7DF09358585D"), Text = Constants.Conventions.DataTypes.ListViewPrefix + "Members", NodeObjectType = new Guid(Constants.ObjectTypes.DataType), CreateDate = DateTime.Now });
|
||||
_database.Insert("umbracoNode", "id", false, new NodeDto { NodeId = 1031, Trashed = false, ParentId = -1, UserId = 0, Level = 1, Path = "-1,1031", SortOrder = 2, UniqueId = new Guid("f38bd2d7-65d0-48e6-95dc-87ce06ec2d3d"), Text = Constants.Conventions.MediaTypes.Folder, NodeObjectType = new Guid(Constants.ObjectTypes.MediaType), CreateDate = DateTime.Now });
|
||||
_database.Insert("umbracoNode", "id", false, new NodeDto { NodeId = 1032, Trashed = false, ParentId = -1, UserId = 0, Level = 1, Path = "-1,1032", SortOrder = 2, UniqueId = new Guid("cc07b313-0843-4aa8-bbda-871c8da728c8"), Text = Constants.Conventions.MediaTypes.Image, NodeObjectType = new Guid(Constants.ObjectTypes.MediaType), CreateDate = DateTime.Now });
|
||||
_database.Insert("umbracoNode", "id", false, new NodeDto { NodeId = 1033, Trashed = false, ParentId = -1, UserId = 0, Level = 1, Path = "-1,1033", SortOrder = 2, UniqueId = new Guid("4c52d8ab-54e6-40cd-999c-7a5f24903e4d"), Text = Constants.Conventions.MediaTypes.File, NodeObjectType = new Guid(Constants.ObjectTypes.MediaType), CreateDate = DateTime.Now });
|
||||
_database.Insert("umbracoNode", "id", false, new NodeDto { NodeId = 1034, Trashed = false, ParentId = -1, UserId = 0, Level = 1, Path = "-1,1034", SortOrder = 2, UniqueId = new Guid("a6857c73-d6e9-480c-b6e6-f15f6ad11125"), Text = "Content Picker", NodeObjectType = new Guid(Constants.ObjectTypes.DataType), CreateDate = DateTime.Now });
|
||||
_database.Insert("umbracoNode", "id", false, new NodeDto { NodeId = 1035, Trashed = false, ParentId = -1, UserId = 0, Level = 1, Path = "-1,1035", SortOrder = 2, UniqueId = new Guid("93929b9a-93a2-4e2a-b239-d99334440a59"), Text = "Media Picker", NodeObjectType = new Guid(Constants.ObjectTypes.DataType), CreateDate = DateTime.Now });
|
||||
_database.Insert("umbracoNode", "id", false, new NodeDto { NodeId = 1036, Trashed = false, ParentId = -1, UserId = 0, Level = 1, Path = "-1,1036", SortOrder = 2, UniqueId = new Guid("2b24165f-9782-4aa3-b459-1de4a4d21f60"), Text = "Member Picker", NodeObjectType = new Guid(Constants.ObjectTypes.DataType), CreateDate = DateTime.Now });
|
||||
_database.Insert("umbracoNode", "id", false, new NodeDto { NodeId = 1033, Trashed = false, ParentId = -1, UserId = 0, Level = 1, Path = "-1,1033", SortOrder = 2, UniqueId = new Guid("4c52d8ab-54e6-40cd-999c-7a5f24903e4d"), Text = Constants.Conventions.MediaTypes.File, NodeObjectType = new Guid(Constants.ObjectTypes.MediaType), CreateDate = DateTime.Now });
|
||||
_database.Insert("umbracoNode", "id", false, new NodeDto { NodeId = 1040, Trashed = false, ParentId = -1, UserId = 0, Level = 1, Path = "-1,1040", SortOrder = 2, UniqueId = new Guid("21e798da-e06e-4eda-a511-ed257f78d4fa"), Text = "Related Links", NodeObjectType = new Guid(Constants.ObjectTypes.DataType), CreateDate = DateTime.Now });
|
||||
_database.Insert("umbracoNode", "id", false, new NodeDto { NodeId = 1041, Trashed = false, ParentId = -1, UserId = 0, Level = 1, Path = "-1,1041", SortOrder = 2, UniqueId = new Guid("b6b73142-b9c1-4bf8-a16d-e1c23320b549"), Text = "Tags", NodeObjectType = new Guid(Constants.ObjectTypes.DataType), CreateDate = DateTime.Now });
|
||||
_database.Insert("umbracoNode", "id", false, new NodeDto { NodeId = 1043, Trashed = false, ParentId = -1, UserId = 0, Level = 1, Path = "-1,1043", SortOrder = 2, UniqueId = new Guid("1df9f033-e6d4-451f-b8d2-e0cbc50a836f"), Text = "Image Cropper", NodeObjectType = new Guid(Constants.ObjectTypes.DataType), CreateDate = DateTime.Now });
|
||||
_database.Insert("umbracoNode", "id", false, new NodeDto { NodeId = 1044, Trashed = false, ParentId = -1, UserId = 0, Level = 1, Path = "-1,1044", SortOrder = 0, UniqueId = new Guid("d59be02f-1df9-4228-aa1e-01917d806cda"), Text = Constants.Conventions.MemberTypes.DefaultAlias, NodeObjectType = new Guid(Constants.ObjectTypes.MemberType), CreateDate = DateTime.Now });
|
||||
_database.Insert("umbracoNode", "id", false, new NodeDto { NodeId = 1045, Trashed = false, ParentId = -1, UserId = 0, Level = 1, Path = "-1,1045", SortOrder = 2, UniqueId = new Guid("7E3962CC-CE20-4FFC-B661-5897A894BA7E"), Text = "Multiple Media Picker", NodeObjectType = new Guid(Constants.ObjectTypes.DataType), CreateDate = DateTime.Now });
|
||||
|
||||
//New UDI pickers with newer Ids
|
||||
_database.Insert("umbracoNode", "id", false, new NodeDto { NodeId = 1046, Trashed = false, ParentId = -1, UserId = 0, Level = 1, Path = "-1,1046", SortOrder = 2, UniqueId = new Guid("FD1E0DA5-5606-4862-B679-5D0CF3A52A59"), Text = "Content Picker", NodeObjectType = new Guid(Constants.ObjectTypes.DataType), CreateDate = DateTime.Now });
|
||||
_database.Insert("umbracoNode", "id", false, new NodeDto { NodeId = 1047, Trashed = false, ParentId = -1, UserId = 0, Level = 1, Path = "-1,1047", SortOrder = 2, UniqueId = new Guid("1EA2E01F-EBD8-4CE1-8D71-6B1149E63548"), Text = "Member Picker", NodeObjectType = new Guid(Constants.ObjectTypes.DataType), CreateDate = DateTime.Now });
|
||||
_database.Insert("umbracoNode", "id", false, new NodeDto { NodeId = 1048, Trashed = false, ParentId = -1, UserId = 0, Level = 1, Path = "-1,1048", SortOrder = 2, UniqueId = new Guid("135D60E0-64D9-49ED-AB08-893C9BA44AE5"), Text = "Media Picker", NodeObjectType = new Guid(Constants.ObjectTypes.DataType), CreateDate = DateTime.Now });
|
||||
_database.Insert("umbracoNode", "id", false, new NodeDto { NodeId = 1049, Trashed = false, ParentId = -1, UserId = 0, Level = 1, Path = "-1,1049", SortOrder = 2, UniqueId = new Guid("9DBBCBBB-2327-434A-B355-AF1B84E5010A"), Text = "Multiple Media Picker", NodeObjectType = new Guid(Constants.ObjectTypes.DataType), CreateDate = DateTime.Now });
|
||||
|
||||
//TODO: We're not creating these for 7.0
|
||||
//_database.Insert("umbracoNode", "id", false, new NodeDto { NodeId = 1039, Trashed = false, ParentId = -1, UserId = 0, Level = 1, Path = "-1,1039", SortOrder = 2, UniqueId = new Guid("06f349a9-c949-4b6a-8660-59c10451af42"), Text = "Ultimate Picker", NodeObjectType = new Guid(Constants.ObjectTypes.DataType), CreateDate = DateTime.Now });
|
||||
//_database.Insert("umbracoNode", "id", false, new NodeDto { NodeId = 1038, Trashed = false, ParentId = -1, UserId = 0, Level = 1, Path = "-1,1038", SortOrder = 2, UniqueId = new Guid("1251c96c-185c-4e9b-93f4-b48205573cbd"), Text = "Simple Editor", NodeObjectType = new Guid(Constants.ObjectTypes.DataType), CreateDate = DateTime.Now });
|
||||
|
||||
//_database.Insert("umbracoNode", "id", false, new NodeDto { NodeId = 1042, Trashed = false, ParentId = -1, UserId = 0, Level = 1, Path = "-1,1042", SortOrder = 2, UniqueId = new Guid("0a452bd5-83f9-4bc3-8403-1286e13fb77e"), Text = "Macro Container", NodeObjectType = new Guid(Constants.ObjectTypes.DataType), CreateDate = DateTime.Now });
|
||||
}
|
||||
|
||||
@@ -246,17 +246,19 @@ namespace Umbraco.Core.Persistence.Migrations.Initial
|
||||
_database.Insert("cmsDataType", "pk", false, new DataTypeDto { PrimaryKey = 12, DataTypeId = -40, PropertyEditorAlias = Constants.PropertyEditors.RadioButtonListAlias, DbType = "Nvarchar" });
|
||||
_database.Insert("cmsDataType", "pk", false, new DataTypeDto { PrimaryKey = 13, DataTypeId = -41, PropertyEditorAlias = Constants.PropertyEditors.DateAlias, DbType = "Date" });
|
||||
_database.Insert("cmsDataType", "pk", false, new DataTypeDto { PrimaryKey = 14, DataTypeId = -42, PropertyEditorAlias = Constants.PropertyEditors.DropDownListAlias, DbType = "Integer" });
|
||||
_database.Insert("cmsDataType", "pk", false, new DataTypeDto { PrimaryKey = 15, DataTypeId = -43, PropertyEditorAlias = Constants.PropertyEditors.CheckBoxListAlias, DbType = "Nvarchar" });
|
||||
_database.Insert("cmsDataType", "pk", false, new DataTypeDto { PrimaryKey = 16, DataTypeId = 1034, PropertyEditorAlias = Constants.PropertyEditors.ContentPickerAlias, DbType = "Integer" });
|
||||
_database.Insert("cmsDataType", "pk", false, new DataTypeDto { PrimaryKey = 18, DataTypeId = 1036, PropertyEditorAlias = Constants.PropertyEditors.MemberPickerAlias, DbType = "Integer" });
|
||||
_database.Insert("cmsDataType", "pk", false, new DataTypeDto { PrimaryKey = 17, DataTypeId = 1035, PropertyEditorAlias = Constants.PropertyEditors.MultipleMediaPickerAlias, DbType = "Nvarchar" });
|
||||
_database.Insert("cmsDataType", "pk", false, new DataTypeDto { PrimaryKey = 15, DataTypeId = -43, PropertyEditorAlias = Constants.PropertyEditors.CheckBoxListAlias, DbType = "Nvarchar" });
|
||||
_database.Insert("cmsDataType", "pk", false, new DataTypeDto { PrimaryKey = 21, DataTypeId = 1040, PropertyEditorAlias = Constants.PropertyEditors.RelatedLinksAlias, DbType = "Ntext" });
|
||||
_database.Insert("cmsDataType", "pk", false, new DataTypeDto { PrimaryKey = 22, DataTypeId = 1041, PropertyEditorAlias = Constants.PropertyEditors.TagsAlias, DbType = "Ntext" });
|
||||
_database.Insert("cmsDataType", "pk", false, new DataTypeDto { PrimaryKey = 24, DataTypeId = 1043, PropertyEditorAlias = Constants.PropertyEditors.ImageCropperAlias, DbType = "Ntext" });
|
||||
_database.Insert("cmsDataType", "pk", false, new DataTypeDto { PrimaryKey = 25, DataTypeId = 1045, PropertyEditorAlias = Constants.PropertyEditors.MultipleMediaPickerAlias, DbType = "Nvarchar" });
|
||||
_database.Insert("cmsDataType", "pk", false, new DataTypeDto { PrimaryKey = -26, DataTypeId = Constants.System.DefaultContentListViewDataTypeId, PropertyEditorAlias = Constants.PropertyEditors.ListViewAlias, DbType = "Nvarchar" });
|
||||
_database.Insert("cmsDataType", "pk", false, new DataTypeDto { PrimaryKey = -27, DataTypeId = Constants.System.DefaultMediaListViewDataTypeId, PropertyEditorAlias = Constants.PropertyEditors.ListViewAlias, DbType = "Nvarchar" });
|
||||
_database.Insert("cmsDataType", "pk", false, new DataTypeDto { PrimaryKey = -28, DataTypeId = Constants.System.DefaultMembersListViewDataTypeId, PropertyEditorAlias = Constants.PropertyEditors.ListViewAlias, DbType = "Nvarchar" });
|
||||
_database.Insert("cmsDataType", "pk", false, new DataTypeDto { PrimaryKey = -28, DataTypeId = Constants.System.DefaultMembersListViewDataTypeId, PropertyEditorAlias = Constants.PropertyEditors.ListViewAlias, DbType = "Nvarchar" });
|
||||
|
||||
//New UDI pickers with newer Ids
|
||||
_database.Insert("cmsDataType", "pk", false, new DataTypeDto { PrimaryKey = 26, DataTypeId = 1046, PropertyEditorAlias = Constants.PropertyEditors.ContentPicker2Alias, DbType = "Nvarchar" });
|
||||
_database.Insert("cmsDataType", "pk", false, new DataTypeDto { PrimaryKey = 27, DataTypeId = 1047, PropertyEditorAlias = Constants.PropertyEditors.MemberPicker2Alias, DbType = "Nvarchar" });
|
||||
_database.Insert("cmsDataType", "pk", false, new DataTypeDto { PrimaryKey = 28, DataTypeId = 1048, PropertyEditorAlias = Constants.PropertyEditors.MediaPicker2Alias, DbType = "Ntext" });
|
||||
_database.Insert("cmsDataType", "pk", false, new DataTypeDto { PrimaryKey = 29, DataTypeId = 1049, PropertyEditorAlias = Constants.PropertyEditors.MediaPicker2Alias, DbType = "Ntext" });
|
||||
|
||||
//TODO: We're not creating these for 7.0
|
||||
//_database.Insert("cmsDataType", "pk", false, new DataTypeDto { PrimaryKey = 19, DataTypeId = 1038, PropertyEditorAlias = Constants.PropertyEditors.MarkdownEditorAlias, DbType = "Ntext" });
|
||||
@@ -268,10 +270,7 @@ namespace Umbraco.Core.Persistence.Migrations.Initial
|
||||
{
|
||||
_database.Insert("cmsDataTypePreValues", "id", false, new DataTypePreValueDto { Id = 3, Alias = "", SortOrder = 0, DataTypeNodeId = -87, Value = ",code,undo,redo,cut,copy,mcepasteword,stylepicker,bold,italic,bullist,numlist,outdent,indent,mcelink,unlink,mceinsertanchor,mceimage,umbracomacro,mceinserttable,umbracoembed,mcecharmap,|1|1,2,3,|0|500,400|1049,|true|" });
|
||||
_database.Insert("cmsDataTypePreValues", "id", false, new DataTypePreValueDto { Id = 4, Alias = "group", SortOrder = 0, DataTypeNodeId = 1041, Value = "default" });
|
||||
|
||||
//default's for MultipleMediaPickerAlias picker
|
||||
_database.Insert("cmsDataTypePreValues", "id", false, new DataTypePreValueDto { Id = 5, Alias = "multiPicker", SortOrder = 0, DataTypeNodeId = 1045, Value = "1" });
|
||||
|
||||
|
||||
//defaults for the member list
|
||||
_database.Insert("cmsDataTypePreValues", "id", false, new DataTypePreValueDto { Id = -1, Alias = "pageSize", SortOrder = 1, DataTypeNodeId = Constants.System.DefaultMembersListViewDataTypeId, Value = "10" });
|
||||
_database.Insert("cmsDataTypePreValues", "id", false, new DataTypePreValueDto { Id = -2, Alias = "orderBy", SortOrder = 2, DataTypeNodeId = Constants.System.DefaultMembersListViewDataTypeId, Value = "username" });
|
||||
@@ -288,6 +287,9 @@ namespace Umbraco.Core.Persistence.Migrations.Initial
|
||||
_database.Insert("cmsDataTypePreValues", "id", false, new DataTypePreValueDto { Id = -7, Alias = "orderDirection", SortOrder = 3, DataTypeNodeId = Constants.System.DefaultMediaListViewDataTypeId, Value = "desc" });
|
||||
_database.Insert("cmsDataTypePreValues", "id", false, new DataTypePreValueDto { Id = -8, Alias = "layouts", SortOrder = 4, DataTypeNodeId = Constants.System.DefaultMediaListViewDataTypeId, Value = "[" + cardLayout + "," + listLayout + "]" });
|
||||
_database.Insert("cmsDataTypePreValues", "id", false, new DataTypePreValueDto { Id = -9, Alias = "includeProperties", SortOrder = 5, DataTypeNodeId = Constants.System.DefaultMediaListViewDataTypeId, Value = "[{\"alias\":\"updateDate\",\"header\":\"Last edited\",\"isSystem\":1},{\"alias\":\"owner\",\"header\":\"Updated by\",\"isSystem\":1}]" });
|
||||
|
||||
//default's for MultipleMediaPickerAlias picker
|
||||
_database.Insert("cmsDataTypePreValues", "id", false, new DataTypePreValueDto { Id = 6, Alias = "multiPicker", SortOrder = 0, DataTypeNodeId = 1049, Value = "1" });
|
||||
}
|
||||
|
||||
private void CreateUmbracoRelationTypeData()
|
||||
|
||||
+1
-8
@@ -14,14 +14,7 @@ namespace Umbraco.Core.Persistence.Migrations.Upgrades.TargetVersionSevenSixZero
|
||||
|
||||
public override void Up()
|
||||
{
|
||||
var dbIndexes = SqlSyntax.GetDefinedIndexes(Context.Database)
|
||||
.Select(x => new DbIndexDefinition()
|
||||
{
|
||||
TableName = x.Item1,
|
||||
IndexName = x.Item2,
|
||||
ColumnName = x.Item3,
|
||||
IsUnique = x.Item4
|
||||
}).ToArray();
|
||||
var dbIndexes = SqlSyntax.GetDefinedIndexesDefinitions(Context.Database);
|
||||
|
||||
//make sure it doesn't already exist
|
||||
if (dbIndexes.Any(x => x.IndexName.InvariantEquals("IX_cmsMember_LoginName")) == false)
|
||||
|
||||
+34
@@ -0,0 +1,34 @@
|
||||
using System.Linq;
|
||||
using Umbraco.Core.Logging;
|
||||
using Umbraco.Core.Persistence.SqlSyntax;
|
||||
|
||||
namespace Umbraco.Core.Persistence.Migrations.Upgrades.TargetVersionSevenSixZero
|
||||
{
|
||||
[Migration("7.6.0", 0, Constants.System.UmbracoMigrationName)]
|
||||
public class AddIndexToUser2NodePermission : MigrationBase
|
||||
{
|
||||
public AddIndexToUser2NodePermission(ISqlSyntaxProvider sqlSyntax, ILogger logger)
|
||||
: base(sqlSyntax, logger)
|
||||
{ }
|
||||
|
||||
public override void Up()
|
||||
{
|
||||
var dbIndexes = SqlSyntax.GetDefinedIndexesDefinitions(Context.Database);
|
||||
|
||||
//make sure it doesn't already exist
|
||||
if (dbIndexes.Any(x => x.IndexName.InvariantEquals("IX_umbracoUser2NodePermission_nodeId")) == false)
|
||||
{
|
||||
Create.Index("IX_umbracoUser2NodePermission_nodeId").OnTable("umbracoUser2NodePermission")
|
||||
.OnColumn("nodeId")
|
||||
.Ascending()
|
||||
.WithOptions()
|
||||
.NonClustered();
|
||||
}
|
||||
}
|
||||
|
||||
public override void Down()
|
||||
{
|
||||
Delete.Index("IX_umbracoUser2NodePermission_nodeId").OnTable("cmsMember");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -703,7 +703,7 @@ namespace Umbraco.Core.Persistence
|
||||
|
||||
static Regex rxColumns = new Regex(@"\A\s*SELECT\s+((?:\((?>\((?<depth>)|\)(?<-depth>)|.?)*(?(depth)(?!))\)|.)*?)(?<!,\s+)\bFROM\b", RegexOptions.IgnoreCase | RegexOptions.Multiline | RegexOptions.Singleline | RegexOptions.Compiled);
|
||||
static Regex rxOrderBy = new Regex(@"\bORDER\s+BY\s+(?:\((?>\((?<depth>)|\)(?<-depth>)|.?)*(?(depth)(?!))\)|[\w\(\)\.])+(?:\s+(?:ASC|DESC))?(?:\s*,\s*(?:\((?>\((?<depth>)|\)(?<-depth>)|.?)*(?(depth)(?!))\)|[\w\(\)\.])+(?:\s+(?:ASC|DESC))?)*", RegexOptions.IgnoreCase | RegexOptions.Multiline | RegexOptions.Singleline | RegexOptions.Compiled);
|
||||
static Regex rxDistinct = new Regex(@"\ADISTINCT\s", RegexOptions.IgnoreCase | RegexOptions.Multiline | RegexOptions.Singleline | RegexOptions.Compiled);
|
||||
static Regex rxDistinct = new Regex(@"\ADISTINCT\s", RegexOptions.IgnoreCase | RegexOptions.Multiline | RegexOptions.Singleline | RegexOptions.Compiled);
|
||||
public static bool SplitSqlForPaging(string sql, out string sqlCount, out string sqlSelectRemoved, out string sqlOrderBy)
|
||||
{
|
||||
sqlSelectRemoved = null;
|
||||
@@ -723,10 +723,9 @@ namespace Umbraco.Core.Persistence
|
||||
sqlCount = sql.Substring(0, g.Index) + "COUNT(" + m.Groups[1].ToString().Trim() + ") " + sql.Substring(g.Index + g.Length);
|
||||
else
|
||||
sqlCount = sql.Substring(0, g.Index) + "COUNT(*) " + sql.Substring(g.Index + g.Length);
|
||||
|
||||
|
||||
// Look for an "ORDER BY <whatever>" clause
|
||||
m = rxOrderBy.Match(sqlCount);
|
||||
|
||||
// Look for an "ORDER BY <whatever>" clause
|
||||
m = rxOrderBy.Match(sqlCount);
|
||||
if (!m.Success)
|
||||
{
|
||||
sqlOrderBy = null;
|
||||
@@ -737,8 +736,7 @@ namespace Umbraco.Core.Persistence
|
||||
sqlOrderBy = g.ToString();
|
||||
sqlCount = sqlCount.Substring(0, g.Index) + sqlCount.Substring(g.Index + g.Length);
|
||||
}
|
||||
|
||||
return true;
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -820,7 +818,7 @@ namespace Umbraco.Core.Persistence
|
||||
result.CurrentPage = page;
|
||||
result.ItemsPerPage = itemsPerPage;
|
||||
result.TotalItems = ExecuteScalar<long>(sqlCount, args);
|
||||
result.TotalPages = result.TotalItems / itemsPerPage;
|
||||
result.TotalPages = result.TotalItems / itemsPerPage;
|
||||
if ((result.TotalItems % itemsPerPage) != 0)
|
||||
result.TotalPages++;
|
||||
|
||||
|
||||
@@ -785,13 +785,8 @@ order by umbracoNode.{2}, umbracoNode.parentID, umbracoNode.sortOrder",
|
||||
|
||||
public void ClearPublished(IContent content)
|
||||
{
|
||||
// race cond!
|
||||
var documentDtos = Database.Fetch<DocumentDto>("WHERE nodeId=@id AND published=@published", new { id = content.Id, published = true });
|
||||
foreach (var documentDto in documentDtos)
|
||||
{
|
||||
documentDto.Published = false;
|
||||
Database.Update(documentDto);
|
||||
}
|
||||
var sql = "UPDATE cmsDocument SET published=0 WHERE nodeId=@id AND published=1";
|
||||
Database.Execute(sql, new {id = content.Id});
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -9,6 +9,7 @@ using Umbraco.Core.Models;
|
||||
using Umbraco.Core;
|
||||
using Umbraco.Core.Models.EntityBase;
|
||||
using Umbraco.Core.Models.Rdbms;
|
||||
using Umbraco.Core.Persistence.DatabaseModelDefinitions;
|
||||
using Umbraco.Core.Persistence.Factories;
|
||||
using Umbraco.Core.Persistence.Querying;
|
||||
using Umbraco.Core.Persistence.UnitOfWork;
|
||||
@@ -49,6 +50,124 @@ namespace Umbraco.Core.Persistence.Repositories
|
||||
|
||||
#region Query Methods
|
||||
|
||||
public IEnumerable<IUmbracoEntity> GetPagedResultsByQuery(IQuery<IUmbracoEntity> query, Guid objectTypeId, long pageIndex, int pageSize, out long totalRecords,
|
||||
string orderBy, Direction orderDirection, IQuery<IUmbracoEntity> filter = null)
|
||||
{
|
||||
bool isContent = objectTypeId == new Guid(Constants.ObjectTypes.Document);
|
||||
bool isMedia = objectTypeId == new Guid(Constants.ObjectTypes.Media);
|
||||
var factory = new UmbracoEntityFactory();
|
||||
|
||||
var sqlClause = GetBaseWhere(GetBase, isContent, isMedia, sql =>
|
||||
{
|
||||
if (filter != null)
|
||||
{
|
||||
foreach (var filterClaus in filter.GetWhereClauses())
|
||||
{
|
||||
sql.Where(filterClaus.Item1, filterClaus.Item2);
|
||||
}
|
||||
}
|
||||
}, objectTypeId);
|
||||
var translator = new SqlTranslator<IUmbracoEntity>(sqlClause, query);
|
||||
var entitySql = translator.Translate();
|
||||
var pagedSql = entitySql.Append(GetGroupBy(isContent, isMedia, false)).OrderBy("umbracoNode.id");
|
||||
|
||||
IEnumerable<IUmbracoEntity> result;
|
||||
|
||||
if (isMedia)
|
||||
{
|
||||
//Treat media differently for now, as an Entity it will be returned with ALL of it's properties in the AdditionalData bag!
|
||||
var pagedResult = _work.Database.Page<dynamic>(pageIndex + 1, pageSize, pagedSql);
|
||||
|
||||
var ids = pagedResult.Items.Select(x => (int) x.id).InGroupsOf(2000);
|
||||
var entities = pagedResult.Items.Select(factory.BuildEntityFromDynamic).Cast<IUmbracoEntity>().ToList();
|
||||
|
||||
//Now we need to merge in the property data since we need paging and we can't do this the way that the big media query was working before
|
||||
foreach (var idGroup in ids)
|
||||
{
|
||||
var propSql = GetPropertySql(Constants.ObjectTypes.Media)
|
||||
.Where("contentNodeId IN (@ids)", new {ids = idGroup})
|
||||
.OrderBy("contentNodeId");
|
||||
|
||||
//This does NOT fetch all data into memory in a list, this will read
|
||||
// over the records as a data reader, this is much better for performance and memory,
|
||||
// but it means that during the reading of this data set, nothing else can be read
|
||||
// from SQL server otherwise we'll get an exception.
|
||||
var allPropertyData = _work.Database.Query<dynamic>(propSql);
|
||||
|
||||
//keep track of the current property data item being enumerated
|
||||
var propertyDataSetEnumerator = allPropertyData.GetEnumerator();
|
||||
var hasCurrent = false; // initially there is no enumerator.Current
|
||||
|
||||
try
|
||||
{
|
||||
//This must be sorted by node id (which is done by SQL) because this is how we are sorting the query to lookup property types above,
|
||||
// which allows us to more efficiently iterate over the large data set of property values.
|
||||
foreach (var entity in entities)
|
||||
{
|
||||
// assemble the dtos for this def
|
||||
// use the available enumerator.Current if any else move to next
|
||||
while (hasCurrent || propertyDataSetEnumerator.MoveNext())
|
||||
{
|
||||
if (propertyDataSetEnumerator.Current.contentNodeId == entity.Id)
|
||||
{
|
||||
hasCurrent = false; // enumerator.Current is not available
|
||||
|
||||
//the property data goes into the additional data
|
||||
entity.AdditionalData[propertyDataSetEnumerator.Current.propertyTypeAlias] = new UmbracoEntity.EntityProperty
|
||||
{
|
||||
PropertyEditorAlias = propertyDataSetEnumerator.Current.propertyEditorAlias,
|
||||
Value = StringExtensions.IsNullOrWhiteSpace(propertyDataSetEnumerator.Current.dataNtext)
|
||||
? propertyDataSetEnumerator.Current.dataNvarchar
|
||||
: StringExtensions.ConvertToJsonIfPossible(propertyDataSetEnumerator.Current.dataNtext)
|
||||
};
|
||||
}
|
||||
else
|
||||
{
|
||||
hasCurrent = true; // enumerator.Current is available for another def
|
||||
break; // no more propertyDataDto for this def
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
propertyDataSetEnumerator.Dispose();
|
||||
}
|
||||
}
|
||||
|
||||
result = entities;
|
||||
}
|
||||
else
|
||||
{
|
||||
var pagedResult = _work.Database.Page<dynamic>(pageIndex + 1, pageSize, pagedSql);
|
||||
result = pagedResult.Items.Select(factory.BuildEntityFromDynamic).Cast<IUmbracoEntity>().ToList();
|
||||
}
|
||||
|
||||
//The total items from the PetaPoco page query will be wrong due to the Outer join used on parent, depending on the search this will
|
||||
//return duplicate results when the COUNT is used in conjuction with it, so we need to get the total on our own.
|
||||
|
||||
//generate a query that does not contain the LEFT Join for parent, this would cause
|
||||
//the COUNT(*) query to return the wrong
|
||||
var sqlCountClause = GetBaseWhere(
|
||||
(isC, isM, f) => GetBase(isC, isM, f, true), //true == is a count query
|
||||
isContent, isMedia, sql =>
|
||||
{
|
||||
if (filter != null)
|
||||
{
|
||||
foreach (var filterClaus in filter.GetWhereClauses())
|
||||
{
|
||||
sql.Where(filterClaus.Item1, filterClaus.Item2);
|
||||
}
|
||||
}
|
||||
}, objectTypeId);
|
||||
var translatorCount = new SqlTranslator<IUmbracoEntity>(sqlCountClause, query);
|
||||
var countSql = translatorCount.Translate();
|
||||
|
||||
totalRecords = _work.Database.ExecuteScalar<int>(countSql);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public IUmbracoEntity GetByKey(Guid key)
|
||||
{
|
||||
var sql = GetBaseWhere(GetBase, false, false, key);
|
||||
@@ -71,8 +190,7 @@ namespace Umbraco.Core.Persistence.Repositories
|
||||
|
||||
if (isMedia)
|
||||
{
|
||||
//for now treat media differently
|
||||
//TODO: We should really use this methodology for Content/Members too!! since it includes properties and ALL of the dynamic db fields
|
||||
//Treat media differently for now, as an Entity it will be returned with ALL of it's properties in the AdditionalData bag!
|
||||
var entities = _work.Database.Fetch<dynamic, UmbracoPropertyDto, UmbracoEntity>(
|
||||
new UmbracoEntityRelator().Map, sql);
|
||||
|
||||
@@ -115,8 +233,7 @@ namespace Umbraco.Core.Persistence.Repositories
|
||||
|
||||
if (isMedia)
|
||||
{
|
||||
//for now treat media differently
|
||||
//TODO: We should really use this methodology for Content/Members too!! since it includes properties and ALL of the dynamic db fields
|
||||
//Treat media differently for now, as an Entity it will be returned with ALL of it's properties in the AdditionalData bag!
|
||||
var entities = _work.Database.Fetch<dynamic, UmbracoPropertyDto, UmbracoEntity>(
|
||||
new UmbracoEntityRelator().Map, sql);
|
||||
|
||||
@@ -171,8 +288,7 @@ namespace Umbraco.Core.Persistence.Repositories
|
||||
|
||||
if (isMedia)
|
||||
{
|
||||
//for now treat media differently
|
||||
//TODO: We should really use this methodology for Content/Members too!! since it includes properties and ALL of the dynamic db fields
|
||||
//Treat media differently for now, as an Entity it will be returned with ALL of it's properties in the AdditionalData bag!
|
||||
var entities = _work.Database.Fetch<dynamic, UmbracoPropertyDto, UmbracoEntity>(
|
||||
new UmbracoEntityRelator().Map, sql);
|
||||
foreach (var entity in entities)
|
||||
@@ -231,8 +347,7 @@ namespace Umbraco.Core.Persistence.Repositories
|
||||
}
|
||||
});
|
||||
|
||||
//treat media differently for now
|
||||
//TODO: We should really use this methodology for Content/Members too!! since it includes properties and ALL of the dynamic db fields
|
||||
//Treat media differently for now, as an Entity it will be returned with ALL of it's properties in the AdditionalData bag!
|
||||
var entities = _work.Database.Fetch<dynamic, UmbracoPropertyDto, UmbracoEntity>(
|
||||
new UmbracoEntityRelator().Map, mediaSql);
|
||||
return entities;
|
||||
@@ -278,11 +393,9 @@ namespace Umbraco.Core.Persistence.Repositories
|
||||
return GetFullSqlForMedia(entitySql.Append(GetGroupBy(isContent, true, false)), filter);
|
||||
}
|
||||
|
||||
private Sql GetFullSqlForMedia(Sql entitySql, Action<Sql> filter = null)
|
||||
private Sql GetPropertySql(string nodeObjectType)
|
||||
{
|
||||
//this will add any dataNvarchar property to the output which can be added to the additional properties
|
||||
|
||||
var joinSql = new Sql()
|
||||
var sql = new Sql()
|
||||
.Select("contentNodeId, versionId, dataNvarchar, dataNtext, propertyEditorAlias, alias as propertyTypeAlias")
|
||||
.From<PropertyDataDto>()
|
||||
.InnerJoin<NodeDto>()
|
||||
@@ -291,7 +404,16 @@ namespace Umbraco.Core.Persistence.Repositories
|
||||
.On<PropertyTypeDto, PropertyDataDto>(dto => dto.Id, dto => dto.PropertyTypeId)
|
||||
.InnerJoin<DataTypeDto>()
|
||||
.On<PropertyTypeDto, DataTypeDto>(dto => dto.DataTypeId, dto => dto.DataTypeId)
|
||||
.Where("umbracoNode.nodeObjectType = @nodeObjectType", new {nodeObjectType = Constants.ObjectTypes.Media});
|
||||
.Where("umbracoNode.nodeObjectType = @nodeObjectType", new { nodeObjectType = nodeObjectType });
|
||||
|
||||
return sql;
|
||||
}
|
||||
|
||||
private Sql GetFullSqlForMedia(Sql entitySql, Action<Sql> filter = null)
|
||||
{
|
||||
//this will add any dataNvarchar property to the output which can be added to the additional properties
|
||||
|
||||
var joinSql = GetPropertySql(Constants.ObjectTypes.Media);
|
||||
|
||||
if (filter != null)
|
||||
{
|
||||
@@ -310,34 +432,52 @@ namespace Umbraco.Core.Persistence.Repositories
|
||||
.OrderBy("sortOrder, id");
|
||||
|
||||
return wrappedSql;
|
||||
}
|
||||
}
|
||||
|
||||
protected virtual Sql GetBase(bool isContent, bool isMedia, Action<Sql> customFilter)
|
||||
{
|
||||
var columns = new List<object>
|
||||
{
|
||||
"umbracoNode.id",
|
||||
"umbracoNode.trashed",
|
||||
"umbracoNode.parentID",
|
||||
"umbracoNode.nodeUser",
|
||||
"umbracoNode.level",
|
||||
"umbracoNode.path",
|
||||
"umbracoNode.sortOrder",
|
||||
"umbracoNode.uniqueID",
|
||||
"umbracoNode.text",
|
||||
"umbracoNode.nodeObjectType",
|
||||
"umbracoNode.createDate",
|
||||
"COUNT(parent.parentID) as children"
|
||||
};
|
||||
return GetBase(isContent, isMedia, customFilter, false);
|
||||
}
|
||||
|
||||
if (isContent || isMedia)
|
||||
protected virtual Sql GetBase(bool isContent, bool isMedia, Action<Sql> customFilter, bool isCount)
|
||||
{
|
||||
var columns = new List<object>();
|
||||
if (isCount)
|
||||
{
|
||||
columns.Add("published.versionId as publishedVersion");
|
||||
columns.Add("latest.versionId as newestVersion");
|
||||
columns.Add("contenttype.alias");
|
||||
columns.Add("contenttype.icon");
|
||||
columns.Add("contenttype.thumbnail");
|
||||
columns.Add("contenttype.isContainer");
|
||||
columns.Add("COUNT(*)");
|
||||
}
|
||||
else
|
||||
{
|
||||
columns.AddRange(new List<object>
|
||||
{
|
||||
"umbracoNode.id",
|
||||
"umbracoNode.trashed",
|
||||
"umbracoNode.parentID",
|
||||
"umbracoNode.nodeUser",
|
||||
"umbracoNode.level",
|
||||
"umbracoNode.path",
|
||||
"umbracoNode.sortOrder",
|
||||
"umbracoNode.uniqueID",
|
||||
"umbracoNode.text",
|
||||
"umbracoNode.nodeObjectType",
|
||||
"umbracoNode.createDate",
|
||||
"COUNT(parent.parentID) as children"
|
||||
});
|
||||
|
||||
if (isContent || isMedia)
|
||||
{
|
||||
if (isContent)
|
||||
{
|
||||
//only content has this info
|
||||
columns.Add("published.versionId as publishedVersion");
|
||||
columns.Add("document.versionId as newestVersion");
|
||||
}
|
||||
|
||||
columns.Add("contenttype.alias");
|
||||
columns.Add("contenttype.icon");
|
||||
columns.Add("contenttype.thumbnail");
|
||||
columns.Add("contenttype.isContainer");
|
||||
}
|
||||
}
|
||||
|
||||
//Creates an SQL query to return a single row for the entity
|
||||
@@ -348,17 +488,24 @@ namespace Umbraco.Core.Persistence.Repositories
|
||||
|
||||
if (isContent || isMedia)
|
||||
{
|
||||
entitySql.InnerJoin("cmsContent content").On("content.nodeId = umbracoNode.id")
|
||||
.LeftJoin("cmsContentType contenttype").On("contenttype.nodeId = content.contentType")
|
||||
.LeftJoin(
|
||||
"(SELECT nodeId, versionId FROM cmsDocument WHERE published = 1 GROUP BY nodeId, versionId) as published")
|
||||
.On("umbracoNode.id = published.nodeId")
|
||||
.LeftJoin(
|
||||
"(SELECT nodeId, versionId FROM cmsDocument WHERE newest = 1 GROUP BY nodeId, versionId) as latest")
|
||||
.On("umbracoNode.id = latest.nodeId");
|
||||
entitySql.InnerJoin("cmsContent content").On("content.nodeId = umbracoNode.id");
|
||||
|
||||
if (isContent)
|
||||
{
|
||||
//only content has this info
|
||||
entitySql
|
||||
.InnerJoin("cmsDocument document").On("document.nodeId = umbracoNode.id")
|
||||
.LeftJoin("(SELECT nodeId, versionId FROM cmsDocument WHERE published = 1) as published")
|
||||
.On("umbracoNode.id = published.nodeId");
|
||||
}
|
||||
|
||||
entitySql.LeftJoin("cmsContentType contenttype").On("contenttype.nodeId = content.contentType");
|
||||
}
|
||||
|
||||
entitySql.LeftJoin("umbracoNode parent").On("parent.parentID = umbracoNode.id");
|
||||
if (isCount == false)
|
||||
{
|
||||
entitySql.LeftJoin("umbracoNode parent").On("parent.parentID = umbracoNode.id");
|
||||
}
|
||||
|
||||
if (customFilter != null)
|
||||
{
|
||||
@@ -372,22 +519,42 @@ namespace Umbraco.Core.Persistence.Repositories
|
||||
{
|
||||
var sql = baseQuery(isContent, isMedia, filter)
|
||||
.Where("umbracoNode.nodeObjectType = @NodeObjectType", new { NodeObjectType = nodeObjectType });
|
||||
|
||||
if (isContent)
|
||||
{
|
||||
sql.Where("document.newest = 1");
|
||||
}
|
||||
|
||||
return sql;
|
||||
}
|
||||
|
||||
protected virtual Sql GetBaseWhere(Func<bool, bool, Action<Sql>, Sql> baseQuery, bool isContent, bool isMedia, int id)
|
||||
{
|
||||
var sql = baseQuery(isContent, isMedia, null)
|
||||
.Where("umbracoNode.id = @Id", new { Id = id })
|
||||
.Append(GetGroupBy(isContent, isMedia));
|
||||
.Where("umbracoNode.id = @Id", new { Id = id });
|
||||
|
||||
if (isContent)
|
||||
{
|
||||
sql.Where("document.newest = 1");
|
||||
}
|
||||
|
||||
sql.Append(GetGroupBy(isContent, isMedia));
|
||||
|
||||
return sql;
|
||||
}
|
||||
|
||||
protected virtual Sql GetBaseWhere(Func<bool, bool, Action<Sql>, Sql> baseQuery, bool isContent, bool isMedia, Guid key)
|
||||
{
|
||||
var sql = baseQuery(isContent, isMedia, null)
|
||||
.Where("umbracoNode.uniqueID = @UniqueID", new { UniqueID = key })
|
||||
.Append(GetGroupBy(isContent, isMedia));
|
||||
.Where("umbracoNode.uniqueID = @UniqueID", new { UniqueID = key });
|
||||
|
||||
if (isContent)
|
||||
{
|
||||
sql.Where("document.newest = 1");
|
||||
}
|
||||
|
||||
sql.Append(GetGroupBy(isContent, isMedia));
|
||||
|
||||
return sql;
|
||||
}
|
||||
|
||||
@@ -396,6 +563,12 @@ namespace Umbraco.Core.Persistence.Repositories
|
||||
var sql = baseQuery(isContent, isMedia, null)
|
||||
.Where("umbracoNode.id = @Id AND umbracoNode.nodeObjectType = @NodeObjectType",
|
||||
new {Id = id, NodeObjectType = nodeObjectType});
|
||||
|
||||
if (isContent)
|
||||
{
|
||||
sql.Where("document.newest = 1");
|
||||
}
|
||||
|
||||
return sql;
|
||||
}
|
||||
|
||||
@@ -404,30 +577,39 @@ namespace Umbraco.Core.Persistence.Repositories
|
||||
var sql = baseQuery(isContent, isMedia, null)
|
||||
.Where("umbracoNode.uniqueID = @UniqueID AND umbracoNode.nodeObjectType = @NodeObjectType",
|
||||
new { UniqueID = key, NodeObjectType = nodeObjectType });
|
||||
|
||||
if (isContent)
|
||||
{
|
||||
sql.Where("document.newest = 1");
|
||||
}
|
||||
|
||||
return sql;
|
||||
}
|
||||
|
||||
protected virtual Sql GetGroupBy(bool isContent, bool isMedia, bool includeSort = true)
|
||||
{
|
||||
var columns = new List<object>
|
||||
{
|
||||
"umbracoNode.id",
|
||||
"umbracoNode.trashed",
|
||||
"umbracoNode.parentID",
|
||||
"umbracoNode.nodeUser",
|
||||
"umbracoNode.level",
|
||||
"umbracoNode.path",
|
||||
"umbracoNode.sortOrder",
|
||||
"umbracoNode.uniqueID",
|
||||
"umbracoNode.text",
|
||||
"umbracoNode.nodeObjectType",
|
||||
"umbracoNode.createDate"
|
||||
};
|
||||
{
|
||||
"umbracoNode.id",
|
||||
"umbracoNode.trashed",
|
||||
"umbracoNode.parentID",
|
||||
"umbracoNode.nodeUser",
|
||||
"umbracoNode.level",
|
||||
"umbracoNode.path",
|
||||
"umbracoNode.sortOrder",
|
||||
"umbracoNode.uniqueID",
|
||||
"umbracoNode.text",
|
||||
"umbracoNode.nodeObjectType",
|
||||
"umbracoNode.createDate"
|
||||
};
|
||||
|
||||
if (isContent || isMedia)
|
||||
{
|
||||
columns.Add("published.versionId");
|
||||
columns.Add("latest.versionId");
|
||||
if (isContent)
|
||||
{
|
||||
columns.Add("published.versionId");
|
||||
columns.Add("document.versionId");
|
||||
}
|
||||
columns.Add("contenttype.alias");
|
||||
columns.Add("contenttype.icon");
|
||||
columns.Add("contenttype.thumbnail");
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Umbraco.Core.Models.EntityBase;
|
||||
using Umbraco.Core.Persistence.DatabaseModelDefinitions;
|
||||
using Umbraco.Core.Persistence.Querying;
|
||||
|
||||
namespace Umbraco.Core.Persistence.Repositories
|
||||
@@ -16,6 +17,21 @@ namespace Umbraco.Core.Persistence.Repositories
|
||||
IEnumerable<IUmbracoEntity> GetByQuery(IQuery<IUmbracoEntity> query);
|
||||
IEnumerable<IUmbracoEntity> GetByQuery(IQuery<IUmbracoEntity> query, Guid objectTypeId);
|
||||
|
||||
/// <summary>
|
||||
/// Gets paged results
|
||||
/// </summary>
|
||||
/// <param name="query">Query to excute</param>
|
||||
/// <param name="objectTypeId"></param>
|
||||
/// <param name="pageIndex">Page number</param>
|
||||
/// <param name="pageSize">Page size</param>
|
||||
/// <param name="totalRecords">Total records query would return without paging</param>
|
||||
/// <param name="orderBy">Field to order by</param>
|
||||
/// <param name="orderDirection">Direction to order by</param>
|
||||
/// <param name="filter"></param>
|
||||
/// <returns>An Enumerable list of <see cref="IUmbracoEntity"/> objects</returns>
|
||||
IEnumerable<IUmbracoEntity> GetPagedResultsByQuery(IQuery<IUmbracoEntity> query, Guid objectTypeId, long pageIndex, int pageSize, out long totalRecords,
|
||||
string orderBy, Direction orderDirection, IQuery<IUmbracoEntity> filter = null);
|
||||
|
||||
/// <summary>
|
||||
/// Returns true if the entity exists
|
||||
/// </summary>
|
||||
|
||||
@@ -63,6 +63,7 @@ namespace Umbraco.Core.Persistence.Repositories
|
||||
FormatDeleteStatement("cmsContentVersion", "ContentId"),
|
||||
FormatDeleteStatement("cmsContentXml", "nodeId"),
|
||||
FormatDeleteStatement("cmsContent", "nodeId"),
|
||||
//TODO: Why is this being done? We just delete this exact data in the next line
|
||||
"UPDATE umbracoNode SET parentID = '" + RecycleBinId + "' WHERE trashed = '1' AND nodeObjectType = @NodeObjectType",
|
||||
"DELETE FROM umbracoNode WHERE trashed = '1' AND nodeObjectType = @NodeObjectType"
|
||||
};
|
||||
@@ -91,14 +92,18 @@ namespace Umbraco.Core.Persistence.Repositories
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// A delete statement that will delete anything in the table specified where its PK (keyName) is found in the
|
||||
/// list of umbracoNode.id that have trashed flag set
|
||||
/// </summary>
|
||||
/// <param name="tableName"></param>
|
||||
/// <param name="keyName"></param>
|
||||
/// <returns></returns>
|
||||
private string FormatDeleteStatement(string tableName, string keyName)
|
||||
{
|
||||
//This query works with sql ce and sql server:
|
||||
//DELETE FROM umbracoUser2NodeNotify WHERE umbracoUser2NodeNotify.nodeId IN
|
||||
//(SELECT nodeId FROM umbracoUser2NodeNotify as TB1 INNER JOIN umbracoNode as TB2 ON TB1.nodeId = TB2.id WHERE TB2.trashed = '1' AND TB2.nodeObjectType = 'C66BA18E-EAF3-4CFF-8A22-41B16D66A972')
|
||||
return
|
||||
string.Format(
|
||||
"DELETE FROM {0} WHERE {0}.{1} IN (SELECT TB1.{1} FROM {0} as TB1 INNER JOIN umbracoNode as TB2 ON TB1.{1} = TB2.id WHERE TB2.trashed = '1' AND TB2.nodeObjectType = @NodeObjectType)",
|
||||
"DELETE FROM {0} WHERE {0}.{1} IN (SELECT id FROM umbracoNode WHERE trashed = '1' AND nodeObjectType = @NodeObjectType)",
|
||||
tableName, keyName);
|
||||
}
|
||||
|
||||
|
||||
@@ -73,12 +73,16 @@ namespace Umbraco.Core.Persistence.Repositories
|
||||
RelationFactory factory = null;
|
||||
var relationTypeId = -1;
|
||||
|
||||
// the ToList() here is important because we are using _relationTypeRepository and we
|
||||
// cannot wait until the result is actually enumerated to do so, because that would
|
||||
// mean we kinda capture the current unit of work and reuse it after it's been disposed
|
||||
|
||||
return dtos.Select(x =>
|
||||
{
|
||||
if (relationTypeId != x.RelationType)
|
||||
factory = new RelationFactory(_relationTypeRepository.Get(relationTypeId = x.RelationType));
|
||||
return DtoToEntity(x, factory);
|
||||
});
|
||||
}).ToList();
|
||||
}
|
||||
|
||||
private static IRelation DtoToEntity(RelationDto dto, RelationFactory factory)
|
||||
|
||||
@@ -15,6 +15,7 @@ namespace Umbraco.Core.PropertyEditors
|
||||
public PreValueField()
|
||||
{
|
||||
Validators = new List<IPropertyValidator>();
|
||||
Config = new Dictionary<string, object>();
|
||||
|
||||
//check for an attribute and fill the values
|
||||
var att = GetType().GetCustomAttribute<PreValueFieldAttribute>(false);
|
||||
@@ -79,5 +80,11 @@ namespace Umbraco.Core.PropertyEditors
|
||||
/// </summary>
|
||||
[JsonProperty("validation", ItemConverterType = typeof(ManifestValidatorConverter))]
|
||||
public List<IPropertyValidator> Validators { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// This allows for custom configuration to be injected into the pre-value editor
|
||||
/// </summary>
|
||||
[JsonProperty("config")]
|
||||
public IDictionary<string, object> Config { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -38,6 +38,7 @@ namespace Umbraco.Core.PropertyEditors
|
||||
IsParameterEditor = _attribute.IsParameterEditor;
|
||||
Icon = _attribute.Icon;
|
||||
Group = _attribute.Group;
|
||||
IsDeprecated = _attribute.IsDeprecated;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -90,6 +91,9 @@ namespace Umbraco.Core.PropertyEditors
|
||||
get { return CreateValueEditor(); }
|
||||
}
|
||||
|
||||
[JsonIgnore]
|
||||
public bool IsDeprecated { get; internal set; }
|
||||
|
||||
[JsonIgnore]
|
||||
IValueEditor IParameterEditor.ValueEditor
|
||||
{
|
||||
|
||||
@@ -60,6 +60,12 @@ namespace Umbraco.Core.PropertyEditors
|
||||
public string ValueType { get; set; }
|
||||
public bool IsParameterEditor { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// If set to true, this property editor will not show up in the DataType's drop down list
|
||||
/// if there is not already one of them chosen for a DataType
|
||||
/// </summary>
|
||||
public bool IsDeprecated { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// If this is is true than the editor will be displayed full width without a label
|
||||
/// </summary>
|
||||
|
||||
@@ -15,6 +15,7 @@ namespace Umbraco.Core.Scoping
|
||||
private bool _disposed;
|
||||
|
||||
private UmbracoDatabase _database;
|
||||
private EventMessages _messages;
|
||||
|
||||
public NoScope(ScopeProvider scopeProvider)
|
||||
{
|
||||
@@ -61,12 +62,42 @@ namespace Umbraco.Core.Scoping
|
||||
/// <inheritdoc />
|
||||
public EventMessages Messages
|
||||
{
|
||||
get { throw new NotSupportedException(); }
|
||||
get
|
||||
{
|
||||
EnsureNotDisposed();
|
||||
if (_messages != null) return _messages;
|
||||
|
||||
// see comments in Scope
|
||||
|
||||
var factory = ScopeLifespanMessagesFactory.Current;
|
||||
if (factory == null)
|
||||
{
|
||||
_messages = new EventMessages();
|
||||
}
|
||||
else
|
||||
{
|
||||
_messages = factory.GetFromHttpContext();
|
||||
if (_messages == null)
|
||||
factory.Set(_messages = new EventMessages());
|
||||
}
|
||||
|
||||
return _messages;
|
||||
}
|
||||
}
|
||||
|
||||
public EventMessages MessagesOrNull
|
||||
{
|
||||
get { throw new NotSupportedException(); }
|
||||
get
|
||||
{
|
||||
EnsureNotDisposed();
|
||||
|
||||
// see comments in Scope
|
||||
|
||||
if (_messages != null) return _messages;
|
||||
|
||||
var factory = ScopeLifespanMessagesFactory.Current;
|
||||
return factory == null ? null : factory.GetFromHttpContext();
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
|
||||
@@ -24,6 +24,7 @@ namespace Umbraco.Core.Scoping
|
||||
|
||||
private IsolatedRuntimeCache _isolatedRuntimeCache;
|
||||
private UmbracoDatabase _database;
|
||||
private EventMessages _messages;
|
||||
private ICompletable _fscope;
|
||||
private IEventDispatcher _eventDispatcher;
|
||||
|
||||
@@ -127,6 +128,7 @@ namespace Umbraco.Core.Scoping
|
||||
{
|
||||
// steal everything from NoScope
|
||||
_database = noScope.DatabaseOrNull;
|
||||
_messages = noScope.MessagesOrNull;
|
||||
|
||||
// make sure the NoScope can be replaced ie not in a transaction
|
||||
if (_database != null && _database.InTransaction)
|
||||
@@ -271,11 +273,27 @@ namespace Umbraco.Core.Scoping
|
||||
{
|
||||
EnsureNotDisposed();
|
||||
if (ParentScope != null) return ParentScope.Messages;
|
||||
//return _messages ?? (_messages = new EventMessages());
|
||||
|
||||
// ok, this isn't pretty, but it works
|
||||
// TODO kill the message factory and let the scope manage it all
|
||||
return ApplicationContext.Current.Services.EventMessagesFactory.Get();
|
||||
if (_messages != null) return _messages;
|
||||
|
||||
// this is ugly - in v7 for backward compatibility reasons, EventMessages need
|
||||
// to survive way longer that the scopes, and kinda resides on its own in http
|
||||
// context, but must also be in scopes for when we do async and lose http context
|
||||
// TODO refactor in v8
|
||||
|
||||
var factory = ScopeLifespanMessagesFactory.Current;
|
||||
if (factory == null)
|
||||
{
|
||||
_messages = new EventMessages();
|
||||
}
|
||||
else
|
||||
{
|
||||
_messages = factory.GetFromHttpContext();
|
||||
if (_messages == null)
|
||||
factory.Set(_messages = new EventMessages());
|
||||
}
|
||||
|
||||
return _messages;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -284,7 +302,14 @@ namespace Umbraco.Core.Scoping
|
||||
get
|
||||
{
|
||||
EnsureNotDisposed();
|
||||
return ParentScope == null ? null : ParentScope.MessagesOrNull;
|
||||
if (ParentScope != null) return ParentScope.MessagesOrNull;
|
||||
|
||||
// see comments in Messages
|
||||
|
||||
if (_messages != null) return _messages;
|
||||
|
||||
var factory = ScopeLifespanMessagesFactory.Current;
|
||||
return factory == null ? null : factory.GetFromHttpContext();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -343,13 +368,13 @@ namespace Umbraco.Core.Scoping
|
||||
#endif
|
||||
}
|
||||
|
||||
var parent = ParentScope;
|
||||
_scopeProvider.AmbientScope = parent;
|
||||
|
||||
#if DEBUG_SCOPES
|
||||
_scopeProvider.Disposed(this);
|
||||
#endif
|
||||
|
||||
var parent = ParentScope;
|
||||
_scopeProvider.AmbientScope = parent;
|
||||
|
||||
if (parent != null)
|
||||
parent.ChildCompleted(_completed);
|
||||
else
|
||||
|
||||
@@ -3,6 +3,7 @@ using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Data;
|
||||
using System.Runtime.Remoting.Messaging;
|
||||
using System.Text;
|
||||
using System.Web;
|
||||
using Umbraco.Core.Events;
|
||||
using Umbraco.Core.Persistence;
|
||||
@@ -99,18 +100,23 @@ namespace Umbraco.Core.Scoping
|
||||
where T : class
|
||||
{
|
||||
var objectKey = CallContext.LogicalGetData(key).AsGuid();
|
||||
if (objectKey == Guid.Empty) return null;
|
||||
|
||||
lock (StaticCallContextObjectsLock)
|
||||
{
|
||||
object callContextObject;
|
||||
if (StaticCallContextObjects.TryGetValue(objectKey, out callContextObject))
|
||||
{
|
||||
#if DEBUG_SCOPES
|
||||
//Logging.LogHelper.Debug<ScopeProvider>("GotObject " + objectKey.ToString("N").Substring(0, 8));
|
||||
Logging.LogHelper.Debug<ScopeProvider>("Got " + typeof(T).Name + " Object " + objectKey.ToString("N").Substring(0, 8));
|
||||
//Logging.LogHelper.Debug<ScopeProvider>("At:\r\n" + Head(Environment.StackTrace, 24));
|
||||
#endif
|
||||
return (T) callContextObject;
|
||||
}
|
||||
|
||||
Logging.LogHelper.Warn<ScopeProvider>("Missed " + typeof(T).Name + " Object " + objectKey.ToString("N").Substring(0, 8));
|
||||
#if DEBUG_SCOPES
|
||||
//Logging.LogHelper.Debug<ScopeProvider>("MissedObject " + objectKey.ToString("N").Substring(0, 8));
|
||||
//Logging.LogHelper.Debug<ScopeProvider>("At:\r\n" + Head(Environment.StackTrace, 24));
|
||||
#endif
|
||||
return null;
|
||||
}
|
||||
@@ -146,7 +152,8 @@ namespace Umbraco.Core.Scoping
|
||||
lock (StaticCallContextObjectsLock)
|
||||
{
|
||||
#if DEBUG_SCOPES
|
||||
//Logging.LogHelper.Debug<ScopeProvider>("RemoveObject " + objectKey.ToString("N").Substring(0, 8));
|
||||
Logging.LogHelper.Debug<ScopeProvider>("Remove Object " + objectKey.ToString("N").Substring(0, 8));
|
||||
//Logging.LogHelper.Debug<ScopeProvider>("At:\r\n" + Head(Environment.StackTrace, 24));
|
||||
#endif
|
||||
StaticCallContextObjects.Remove(objectKey);
|
||||
}
|
||||
@@ -160,7 +167,8 @@ namespace Umbraco.Core.Scoping
|
||||
lock (StaticCallContextObjectsLock)
|
||||
{
|
||||
#if DEBUG_SCOPES
|
||||
//Logging.LogHelper.Debug<ScopeProvider>("AddObject " + objectKey.ToString("N").Substring(0, 8));
|
||||
Logging.LogHelper.Debug<ScopeProvider>("AddObject " + objectKey.ToString("N").Substring(0, 8));
|
||||
//Logging.LogHelper.Debug<ScopeProvider>("At:\r\n" + Head(Environment.StackTrace, 24));
|
||||
#endif
|
||||
StaticCallContextObjects.Add(objectKey, value);
|
||||
}
|
||||
@@ -506,7 +514,7 @@ namespace Umbraco.Core.Scoping
|
||||
lock (StaticScopeInfosLock)
|
||||
{
|
||||
if (StaticScopeInfos.ContainsKey(scope)) throw new Exception("oops: already registered.");
|
||||
//Logging.LogHelper.Debug<ScopeProvider>("Register " + scope.InstanceId.ToString("N").Substring(0, 8));
|
||||
Logging.LogHelper.Debug<ScopeProvider>("Register " + scope.InstanceId.ToString("N").Substring(0, 8));
|
||||
StaticScopeInfos[scope] = new ScopeInfo(scope, Environment.StackTrace);
|
||||
}
|
||||
}
|
||||
@@ -524,14 +532,35 @@ namespace Umbraco.Core.Scoping
|
||||
if (context == null) return;
|
||||
throw new Exception("oops: unregistered scope.");
|
||||
}
|
||||
//Logging.LogHelper.Debug<ScopeProvider>("Register context " + (context ?? "null") + " for " + scope.InstanceId.ToString("N").Substring(0, 8));
|
||||
var sb = new StringBuilder();
|
||||
var s = scope;
|
||||
while (s != null)
|
||||
{
|
||||
if (sb.Length > 0) sb.Append(" < ");
|
||||
sb.Append(s.InstanceId.ToString("N").Substring(0, 8));
|
||||
var ss = s as IScopeInternal;
|
||||
s = ss == null ? null : ss.ParentScope;
|
||||
}
|
||||
Logging.LogHelper.Debug<ScopeProvider>("Register " + (context ?? "null") + " context " + sb);
|
||||
if (context == null) info.NullStack = Environment.StackTrace;
|
||||
//if (context == null)
|
||||
// Logging.LogHelper.Debug<ScopeProvider>("STACK\r\n" + info.NullStack);
|
||||
//Logging.LogHelper.Debug<ScopeProvider>("At:\r\n" + Head(Environment.StackTrace, 16));
|
||||
info.Context = context;
|
||||
}
|
||||
}
|
||||
|
||||
private static string Head(string s, int count)
|
||||
{
|
||||
var pos = 0;
|
||||
var i = 0;
|
||||
while (i < count && pos >= 0)
|
||||
{
|
||||
pos = s.IndexOf("\r\n", pos + 1, StringComparison.OrdinalIgnoreCase);
|
||||
i++;
|
||||
}
|
||||
if (pos < 0) return s;
|
||||
return s.Substring(0, pos);
|
||||
}
|
||||
|
||||
public void Disposed(IScope scope)
|
||||
{
|
||||
lock (StaticScopeInfosLock)
|
||||
@@ -541,7 +570,7 @@ namespace Umbraco.Core.Scoping
|
||||
// enable this by default
|
||||
//Console.WriteLine("unregister " + scope.InstanceId.ToString("N").Substring(0, 8));
|
||||
StaticScopeInfos.Remove(scope);
|
||||
//Logging.LogHelper.Debug<ScopeProvider>("Remove " + scope.InstanceId.ToString("N").Substring(0, 8));
|
||||
Logging.LogHelper.Debug<ScopeProvider>("Remove " + scope.InstanceId.ToString("N").Substring(0, 8));
|
||||
|
||||
// instead, enable this to keep *all* scopes
|
||||
// beware, there can be a lot of scopes!
|
||||
|
||||
@@ -176,7 +176,7 @@ namespace Umbraco.Core.Security
|
||||
AllowRefresh = true,
|
||||
IssuedUtc = nowUtc,
|
||||
ExpiresUtc = nowUtc.AddMinutes(GlobalSettings.TimeOutInMinutes)
|
||||
}, userIdentity, rememberBrowserIdentity);
|
||||
}, userIdentity, rememberBrowserIdentity);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -189,6 +189,10 @@ namespace Umbraco.Core.Security
|
||||
}, userIdentity);
|
||||
}
|
||||
|
||||
//track the last login date
|
||||
user.LastLoginDateUtc = DateTime.UtcNow;
|
||||
await UserManager.UpdateAsync(user);
|
||||
|
||||
_logger.WriteCore(TraceEventType.Information, 0,
|
||||
string.Format(
|
||||
"Login attempt succeeded for username {0} from IP address {1}",
|
||||
|
||||
@@ -625,6 +625,12 @@ namespace Umbraco.Core.Security
|
||||
var anythingChanged = false;
|
||||
//don't assign anything if nothing has changed as this will trigger
|
||||
//the track changes of the model
|
||||
if ((user.LastLoginDate != default(DateTime) && identityUser.LastLoginDateUtc.HasValue == false)
|
||||
|| identityUser.LastLoginDateUtc.HasValue && user.LastLoginDate.ToUniversalTime() != identityUser.LastLoginDateUtc.Value)
|
||||
{
|
||||
anythingChanged = true;
|
||||
user.LastLoginDate = identityUser.LastLoginDateUtc.Value.ToLocalTime();
|
||||
}
|
||||
if (user.Name != identityUser.Name && identityUser.Name.IsNullOrWhiteSpace() == false)
|
||||
{
|
||||
anythingChanged = true;
|
||||
|
||||
@@ -69,7 +69,7 @@ namespace Umbraco.Core.Services
|
||||
repo.AddOrUpdate(container);
|
||||
uow.Commit();
|
||||
|
||||
uow.Events.Dispatch(SavedContentTypeContainer, this, new SaveEventArgs<EntityContainer>(container, evtMsgs));
|
||||
uow.Events.Dispatch(SavedContentTypeContainer, this, new SaveEventArgs<EntityContainer>(container, evtMsgs), "SavedContentTypeContainer");
|
||||
//TODO: Audit trail ?
|
||||
|
||||
return Attempt.Succeed(new OperationStatus<EntityContainer, OperationStatusType>(container, OperationStatusType.Success, evtMsgs));
|
||||
@@ -106,7 +106,7 @@ namespace Umbraco.Core.Services
|
||||
repo.AddOrUpdate(container);
|
||||
uow.Commit();
|
||||
|
||||
uow.Events.Dispatch(SavedMediaTypeContainer, this, new SaveEventArgs<EntityContainer>(container, evtMsgs));
|
||||
uow.Events.Dispatch(SavedMediaTypeContainer, this, new SaveEventArgs<EntityContainer>(container, evtMsgs), "SavedMediaTypeContainer");
|
||||
//TODO: Audit trail ?
|
||||
|
||||
return Attempt.Succeed(new OperationStatus<EntityContainer, OperationStatusType>(container, OperationStatusType.Success, evtMsgs));
|
||||
@@ -122,14 +122,16 @@ namespace Umbraco.Core.Services
|
||||
{
|
||||
return SaveContainer(
|
||||
SavingContentTypeContainer, SavedContentTypeContainer,
|
||||
container, Constants.ObjectTypes.DocumentTypeContainerGuid, "document type", userId);
|
||||
container, Constants.ObjectTypes.DocumentTypeContainerGuid, "document type",
|
||||
"SavedContentTypeContainer", userId);
|
||||
}
|
||||
|
||||
public Attempt<OperationStatus> SaveMediaTypeContainer(EntityContainer container, int userId = 0)
|
||||
{
|
||||
return SaveContainer(
|
||||
SavingMediaTypeContainer, SavedMediaTypeContainer,
|
||||
container, Constants.ObjectTypes.MediaTypeContainerGuid, "media type", userId);
|
||||
container, Constants.ObjectTypes.MediaTypeContainerGuid, "media type",
|
||||
"SavedMediaTypeContainer", userId);
|
||||
}
|
||||
|
||||
private Attempt<OperationStatus> SaveContainer(
|
||||
@@ -137,7 +139,9 @@ namespace Umbraco.Core.Services
|
||||
TypedEventHandler<IContentTypeService, SaveEventArgs<EntityContainer>> savedEvent,
|
||||
EntityContainer container,
|
||||
Guid containerObjectType,
|
||||
string objectTypeName, int userId)
|
||||
string objectTypeName,
|
||||
string savedEventName,
|
||||
int userId)
|
||||
{
|
||||
var evtMsgs = EventMessagesFactory.Get();
|
||||
|
||||
@@ -165,7 +169,7 @@ namespace Umbraco.Core.Services
|
||||
var repo = RepositoryFactory.CreateEntityContainerRepository(uow, containerObjectType);
|
||||
repo.AddOrUpdate(container);
|
||||
uow.Commit();
|
||||
uow.Events.Dispatch(savedEvent, this, new SaveEventArgs<EntityContainer>(container, evtMsgs));
|
||||
uow.Events.Dispatch(savedEvent, this, new SaveEventArgs<EntityContainer>(container, evtMsgs), savedEventName);
|
||||
}
|
||||
|
||||
//TODO: Audit trail ?
|
||||
|
||||
@@ -9,6 +9,7 @@ using Umbraco.Core.Models;
|
||||
using Umbraco.Core.Models.EntityBase;
|
||||
using Umbraco.Core.Models.Rdbms;
|
||||
using Umbraco.Core.Persistence;
|
||||
using Umbraco.Core.Persistence.DatabaseModelDefinitions;
|
||||
using Umbraco.Core.Persistence.Querying;
|
||||
using Umbraco.Core.Persistence.UnitOfWork;
|
||||
|
||||
@@ -91,6 +92,7 @@ namespace Umbraco.Core.Services
|
||||
case UmbracoObjectTypes.Member:
|
||||
case UmbracoObjectTypes.DataType:
|
||||
case UmbracoObjectTypes.DocumentTypeContainer:
|
||||
uow.Commit();
|
||||
return uow.Database.ExecuteScalar<int?>(new Sql().Select("id").From<NodeDto>().Where<NodeDto>(dto => dto.UniqueId == key));
|
||||
case UmbracoObjectTypes.RecycleBin:
|
||||
case UmbracoObjectTypes.Stylesheet:
|
||||
@@ -129,6 +131,7 @@ namespace Umbraco.Core.Services
|
||||
case UmbracoObjectTypes.DocumentType:
|
||||
case UmbracoObjectTypes.Member:
|
||||
case UmbracoObjectTypes.DataType:
|
||||
uow.Commit();
|
||||
return uow.Database.ExecuteScalar<Guid?>(new Sql().Select("uniqueID").From<NodeDto>().Where<NodeDto>(dto => dto.NodeId == id));
|
||||
case UmbracoObjectTypes.RecycleBin:
|
||||
case UmbracoObjectTypes.Stylesheet:
|
||||
@@ -374,6 +377,115 @@ namespace Umbraco.Core.Services
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns a paged collection of children
|
||||
/// </summary>
|
||||
/// <param name="parentId">The parent id to return children for</param>
|
||||
/// <param name="umbracoObjectType"></param>
|
||||
/// <param name="pageIndex"></param>
|
||||
/// <param name="pageSize"></param>
|
||||
/// <param name="totalRecords"></param>
|
||||
/// <param name="orderBy"></param>
|
||||
/// <param name="orderDirection"></param>
|
||||
/// <param name="filter"></param>
|
||||
/// <returns></returns>
|
||||
public IEnumerable<IUmbracoEntity> GetPagedChildren(int parentId, UmbracoObjectTypes umbracoObjectType, long pageIndex, int pageSize, out long totalRecords,
|
||||
string orderBy = "SortOrder", Direction orderDirection = Direction.Ascending, string filter = "")
|
||||
{
|
||||
var objectTypeId = umbracoObjectType.GetGuid();
|
||||
using (var uow = UowProvider.GetUnitOfWork())
|
||||
{
|
||||
var repository = RepositoryFactory.CreateEntityRepository(uow);
|
||||
var query = Query<IUmbracoEntity>.Builder.Where(x => x.ParentId == parentId && x.Trashed == false);
|
||||
|
||||
IQuery<IUmbracoEntity> filterQuery = null;
|
||||
if (filter.IsNullOrWhiteSpace() == false)
|
||||
{
|
||||
filterQuery = Query<IUmbracoEntity>.Builder.Where(x => x.Name.Contains(filter));
|
||||
}
|
||||
|
||||
var contents = repository.GetPagedResultsByQuery(query, objectTypeId, pageIndex, pageSize, out totalRecords, orderBy, orderDirection, filterQuery);
|
||||
uow.Commit();
|
||||
return contents;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns a paged collection of descendants
|
||||
/// </summary>
|
||||
/// <param name="id"></param>
|
||||
/// <param name="umbracoObjectType"></param>
|
||||
/// <param name="pageIndex"></param>
|
||||
/// <param name="pageSize"></param>
|
||||
/// <param name="totalRecords"></param>
|
||||
/// <param name="orderBy"></param>
|
||||
/// <param name="orderDirection"></param>
|
||||
/// <param name="filter"></param>
|
||||
/// <returns></returns>
|
||||
public IEnumerable<IUmbracoEntity> GetPagedDescendants(int id, UmbracoObjectTypes umbracoObjectType, long pageIndex, int pageSize, out long totalRecords,
|
||||
string orderBy = "path", Direction orderDirection = Direction.Ascending, string filter = "")
|
||||
{
|
||||
var objectTypeId = umbracoObjectType.GetGuid();
|
||||
using (var uow = UowProvider.GetUnitOfWork())
|
||||
{
|
||||
var repository = RepositoryFactory.CreateEntityRepository(uow);
|
||||
|
||||
var query = Query<IUmbracoEntity>.Builder;
|
||||
//if the id is System Root, then just get all
|
||||
if (id != Constants.System.Root)
|
||||
query.Where(x => x.Path.SqlContains(string.Format(",{0},", id), TextColumnType.NVarchar));
|
||||
|
||||
IQuery<IUmbracoEntity> filterQuery = null;
|
||||
if (filter.IsNullOrWhiteSpace() == false)
|
||||
{
|
||||
filterQuery = Query<IUmbracoEntity>.Builder.Where(x => x.Name.Contains(filter));
|
||||
}
|
||||
|
||||
var contents = repository.GetPagedResultsByQuery(query, objectTypeId, pageIndex, pageSize, out totalRecords, orderBy, orderDirection, filterQuery);
|
||||
uow.Commit();
|
||||
return contents;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns a paged collection of descendants from the root
|
||||
/// </summary>
|
||||
/// <param name="umbracoObjectType"></param>
|
||||
/// <param name="pageIndex"></param>
|
||||
/// <param name="pageSize"></param>
|
||||
/// <param name="totalRecords"></param>
|
||||
/// <param name="orderBy"></param>
|
||||
/// <param name="orderDirection"></param>
|
||||
/// <param name="filter"></param>
|
||||
/// <param name="includeTrashed">true/false to include trashed objects</param>
|
||||
/// <returns></returns>
|
||||
public IEnumerable<IUmbracoEntity> GetPagedDescendantsFromRoot(UmbracoObjectTypes umbracoObjectType, long pageIndex, int pageSize, out long totalRecords,
|
||||
string orderBy = "path", Direction orderDirection = Direction.Ascending, string filter = "", bool includeTrashed = true)
|
||||
{
|
||||
var objectTypeId = umbracoObjectType.GetGuid();
|
||||
using (var uow = UowProvider.GetUnitOfWork())
|
||||
{
|
||||
var repository = RepositoryFactory.CreateEntityRepository(uow);
|
||||
|
||||
var query = Query<IUmbracoEntity>.Builder;
|
||||
//don't include trashed if specfied
|
||||
if (includeTrashed == false)
|
||||
{
|
||||
query.Where(x => x.Trashed == false);
|
||||
}
|
||||
|
||||
IQuery<IUmbracoEntity> filterQuery = null;
|
||||
if (filter.IsNullOrWhiteSpace() == false)
|
||||
{
|
||||
filterQuery = Query<IUmbracoEntity>.Builder.Where(x => x.Name.Contains(filter));
|
||||
}
|
||||
|
||||
var contents = repository.GetPagedResultsByQuery(query, objectTypeId, pageIndex, pageSize, out totalRecords, orderBy, orderDirection, filterQuery);
|
||||
uow.Commit();
|
||||
return contents;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets a collection of descendents by the parents Id
|
||||
/// </summary>
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
using System.Collections.Generic;
|
||||
using Umbraco.Core.Models;
|
||||
using Umbraco.Core.Models.EntityBase;
|
||||
using Umbraco.Core.Persistence.DatabaseModelDefinitions;
|
||||
|
||||
namespace Umbraco.Core.Services
|
||||
{
|
||||
@@ -137,6 +138,51 @@ namespace Umbraco.Core.Services
|
||||
/// <returns>An enumerable list of <see cref="IUmbracoEntity"/> objects</returns>
|
||||
IEnumerable<IUmbracoEntity> GetChildren(int parentId, UmbracoObjectTypes umbracoObjectType);
|
||||
|
||||
/// <summary>
|
||||
/// Returns a paged collection of children
|
||||
/// </summary>
|
||||
/// <param name="parentId">The parent id to return children for</param>
|
||||
/// <param name="umbracoObjectType"></param>
|
||||
/// <param name="pageIndex"></param>
|
||||
/// <param name="pageSize"></param>
|
||||
/// <param name="totalRecords"></param>
|
||||
/// <param name="orderBy"></param>
|
||||
/// <param name="orderDirection"></param>
|
||||
/// <param name="filter"></param>
|
||||
/// <returns></returns>
|
||||
IEnumerable<IUmbracoEntity> GetPagedChildren(int parentId, UmbracoObjectTypes umbracoObjectType, long pageIndex, int pageSize, out long totalRecords,
|
||||
string orderBy = "SortOrder", Direction orderDirection = Direction.Ascending, string filter = "");
|
||||
|
||||
/// <summary>
|
||||
/// Returns a paged collection of descendants
|
||||
/// </summary>
|
||||
/// <param name="id"></param>
|
||||
/// <param name="umbracoObjectType"></param>
|
||||
/// <param name="pageIndex"></param>
|
||||
/// <param name="pageSize"></param>
|
||||
/// <param name="totalRecords"></param>
|
||||
/// <param name="orderBy"></param>
|
||||
/// <param name="orderDirection"></param>
|
||||
/// <param name="filter"></param>
|
||||
/// <returns></returns>
|
||||
IEnumerable<IUmbracoEntity> GetPagedDescendants(int id, UmbracoObjectTypes umbracoObjectType, long pageIndex, int pageSize, out long totalRecords,
|
||||
string orderBy = "path", Direction orderDirection = Direction.Ascending, string filter = "");
|
||||
|
||||
/// <summary>
|
||||
/// Returns a paged collection of descendants from the root
|
||||
/// </summary>
|
||||
/// <param name="umbracoObjectType"></param>
|
||||
/// <param name="pageIndex"></param>
|
||||
/// <param name="pageSize"></param>
|
||||
/// <param name="totalRecords"></param>
|
||||
/// <param name="orderBy"></param>
|
||||
/// <param name="orderDirection"></param>
|
||||
/// <param name="filter"></param>
|
||||
/// <param name="includeTrashed">true/false to include trashed objects</param>
|
||||
/// <returns></returns>
|
||||
IEnumerable<IUmbracoEntity> GetPagedDescendantsFromRoot(UmbracoObjectTypes umbracoObjectType, long pageIndex, int pageSize, out long totalRecords,
|
||||
string orderBy = "path", Direction orderDirection = Direction.Ascending, string filter = "", bool includeTrashed = true);
|
||||
|
||||
/// <summary>
|
||||
/// Gets a collection of descendents by the parents Id
|
||||
/// </summary>
|
||||
|
||||
@@ -425,7 +425,28 @@ namespace Umbraco.Core
|
||||
assemblyName.FullName.StartsWith("App_Code.") ? "App_Code" : assemblyName.Name);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// If the given <paramref name="type"/> is an array or some other collection
|
||||
/// comprised of 0 or more instances of a "subtype", get that type
|
||||
/// </summary>
|
||||
/// <param name="type">the source type</param>
|
||||
/// <returns></returns>
|
||||
internal static Type GetEnumeratedType(this Type type)
|
||||
{
|
||||
if (typeof(IEnumerable).IsAssignableFrom(type) == false)
|
||||
return null;
|
||||
|
||||
// provided by Array
|
||||
var elType = type.GetElementType();
|
||||
if (null != elType) return elType;
|
||||
|
||||
// otherwise provided by collection
|
||||
var elTypes = type.GetGenericArguments();
|
||||
if (elTypes.Length > 0) return elTypes[0];
|
||||
|
||||
// otherwise is not an 'enumerated' type
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
+55
-34
@@ -1,7 +1,9 @@
|
||||
using System;
|
||||
using System.Collections.Concurrent;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using Umbraco.Core.Deploy;
|
||||
|
||||
namespace Umbraco.Core
|
||||
@@ -10,9 +12,10 @@ namespace Umbraco.Core
|
||||
/// Represents an entity identifier.
|
||||
/// </summary>
|
||||
/// <remarks>An Udi can be fully qualified or "closed" eg umb://document/{guid} or "open" eg umb://document.</remarks>
|
||||
[TypeConverter(typeof(UdiTypeConverter))]
|
||||
public abstract class Udi : IComparable<Udi>
|
||||
{
|
||||
private static readonly Dictionary<string, UdiType> UdiTypes = new Dictionary<string, UdiType>();
|
||||
private static readonly Lazy<Dictionary<string, UdiType>> UdiTypes;
|
||||
private static readonly ConcurrentDictionary<string, Udi> RootUdis = new ConcurrentDictionary<string, Udi>();
|
||||
internal readonly Uri UriValue; // internal for UdiRange
|
||||
|
||||
@@ -39,32 +42,50 @@ namespace Umbraco.Core
|
||||
|
||||
static Udi()
|
||||
{
|
||||
// for tests etc.
|
||||
UdiTypes[Constants.DeployEntityType.AnyGuid] = UdiType.GuidUdi;
|
||||
UdiTypes[Constants.DeployEntityType.AnyString] = UdiType.StringUdi;
|
||||
|
||||
// we don't have connectors for these...
|
||||
UdiTypes[Constants.DeployEntityType.Member] = UdiType.GuidUdi;
|
||||
UdiTypes[Constants.DeployEntityType.MemberGroup] = UdiType.GuidUdi;
|
||||
|
||||
// fixme - or inject from...?
|
||||
// there is no way we can get the "registered" service connectors, as registration
|
||||
// happens in Deploy, not in Core, and the Udi class belongs to Core - therefore, we
|
||||
// just pick every service connectors - just making sure that not two of them
|
||||
// would register the same entity type, with different udi types (would not make
|
||||
// much sense anyways).
|
||||
var connectors = PluginManager.Current.ResolveTypes<IServiceConnector>();
|
||||
foreach (var connector in connectors)
|
||||
UdiTypes = new Lazy<Dictionary<string, UdiType>>(() =>
|
||||
{
|
||||
var attrs = connector.GetCustomAttributes<UdiDefinitionAttribute>(false);
|
||||
foreach (var attr in attrs)
|
||||
var result = new Dictionary<string, UdiType>();
|
||||
|
||||
// known types:
|
||||
foreach (var fi in typeof(Constants.UdiEntityType).GetFields(BindingFlags.Public | BindingFlags.Static))
|
||||
{
|
||||
UdiType udiType;
|
||||
if (UdiTypes.TryGetValue(attr.EntityType, out udiType) && udiType != attr.UdiType)
|
||||
throw new Exception(string.Format("Entity type \"{0}\" is declared by more than one IServiceConnector, with different UdiTypes.", attr.EntityType));
|
||||
UdiTypes[attr.EntityType] = attr.UdiType;
|
||||
// IsLiteral determines if its value is written at
|
||||
// compile time and not changeable
|
||||
// IsInitOnly determine if the field can be set
|
||||
// in the body of the constructor
|
||||
// for C# a field which is readonly keyword would have both true
|
||||
// but a const field would have only IsLiteral equal to true
|
||||
if (fi.IsLiteral && fi.IsInitOnly == false)
|
||||
{
|
||||
var udiType = fi.GetCustomAttribute<Constants.UdiTypeAttribute>();
|
||||
|
||||
if (udiType == null)
|
||||
throw new InvalidOperationException("All Constants listed in UdiEntityType must be attributed with " + typeof(Constants.UdiTypeAttribute));
|
||||
result[fi.GetValue(null).ToString()] = udiType.UdiType;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Scan for unknown UDI types
|
||||
// there is no way we can get the "registered" service connectors, as registration
|
||||
// happens in Deploy, not in Core, and the Udi class belongs to Core - therefore, we
|
||||
// just pick every service connectors - just making sure that not two of them
|
||||
// would register the same entity type, with different udi types (would not make
|
||||
// much sense anyways).
|
||||
var connectors = PluginManager.Current.ResolveTypes<IServiceConnector>();
|
||||
foreach (var connector in connectors)
|
||||
{
|
||||
var attrs = connector.GetCustomAttributes<UdiDefinitionAttribute>(false);
|
||||
foreach (var attr in attrs)
|
||||
{
|
||||
UdiType udiType;
|
||||
if (result.TryGetValue(attr.EntityType, out udiType) && udiType != attr.UdiType)
|
||||
throw new Exception(string.Format("Entity type \"{0}\" is declared by more than one IServiceConnector, with different UdiTypes.", attr.EntityType));
|
||||
result[attr.EntityType] = attr.UdiType;
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
});
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -105,8 +126,8 @@ namespace Umbraco.Core
|
||||
udi = null;
|
||||
Uri uri;
|
||||
|
||||
if (!Uri.IsWellFormedUriString(s, UriKind.Absolute)
|
||||
|| !Uri.TryCreate(s, UriKind.Absolute, out uri))
|
||||
if (Uri.IsWellFormedUriString(s, UriKind.Absolute) == false
|
||||
|| Uri.TryCreate(s, UriKind.Absolute, out uri) == false)
|
||||
{
|
||||
if (tryParse) return false;
|
||||
throw new FormatException(string.Format("String \"{0}\" is not a valid udi.", s));
|
||||
@@ -114,7 +135,7 @@ namespace Umbraco.Core
|
||||
|
||||
var entityType = uri.Host;
|
||||
UdiType udiType;
|
||||
if (!UdiTypes.TryGetValue(entityType, out udiType))
|
||||
if (UdiTypes.Value.TryGetValue(entityType, out udiType) == false)
|
||||
{
|
||||
if (tryParse) return false;
|
||||
throw new FormatException(string.Format("Unknown entity type \"{0}\".", entityType));
|
||||
@@ -128,7 +149,7 @@ namespace Umbraco.Core
|
||||
return true;
|
||||
}
|
||||
Guid guid;
|
||||
if (!Guid.TryParse(path, out guid))
|
||||
if (Guid.TryParse(path, out guid) == false)
|
||||
{
|
||||
if (tryParse) return false;
|
||||
throw new FormatException(string.Format("String \"{0}\" is not a valid udi.", s));
|
||||
@@ -150,7 +171,7 @@ namespace Umbraco.Core
|
||||
return RootUdis.GetOrAdd(entityType, x =>
|
||||
{
|
||||
UdiType udiType;
|
||||
if (!UdiTypes.TryGetValue(x, out udiType))
|
||||
if (UdiTypes.Value.TryGetValue(x, out udiType) == false)
|
||||
throw new ArgumentException(string.Format("Unknown entity type \"{0}\".", entityType));
|
||||
return udiType == UdiType.StringUdi
|
||||
? (Udi)new StringUdi(entityType, string.Empty)
|
||||
@@ -177,7 +198,7 @@ namespace Umbraco.Core
|
||||
public static Udi Create(string entityType, string id)
|
||||
{
|
||||
UdiType udiType;
|
||||
if (!UdiTypes.TryGetValue(entityType, out udiType))
|
||||
if (UdiTypes.Value.TryGetValue(entityType, out udiType) == false)
|
||||
throw new ArgumentException(string.Format("Unknown entity type \"{0}\".", entityType), "entityType");
|
||||
if (string.IsNullOrWhiteSpace(id))
|
||||
throw new ArgumentException("Value cannot be null or whitespace.", "id");
|
||||
@@ -196,7 +217,7 @@ namespace Umbraco.Core
|
||||
public static Udi Create(string entityType, Guid id)
|
||||
{
|
||||
UdiType udiType;
|
||||
if (!UdiTypes.TryGetValue(entityType, out udiType))
|
||||
if (UdiTypes.Value.TryGetValue(entityType, out udiType) == false)
|
||||
throw new ArgumentException(string.Format("Unknown entity type \"{0}\".", entityType), "entityType");
|
||||
if (udiType != UdiType.GuidUdi)
|
||||
throw new InvalidOperationException(string.Format("Entity type \"{0}\" does not have guid udis.", entityType));
|
||||
@@ -208,7 +229,7 @@ namespace Umbraco.Core
|
||||
internal static Udi Create(Uri uri)
|
||||
{
|
||||
UdiType udiType;
|
||||
if (!UdiTypes.TryGetValue(uri.Host, out udiType))
|
||||
if (UdiTypes.Value.TryGetValue(uri.Host, out udiType) == false)
|
||||
throw new ArgumentException(string.Format("Unknown entity type \"{0}\".", uri.Host), "uri");
|
||||
if (udiType == UdiType.GuidUdi)
|
||||
return new GuidUdi(uri);
|
||||
@@ -219,7 +240,7 @@ namespace Umbraco.Core
|
||||
|
||||
public void EnsureType(params string[] validTypes)
|
||||
{
|
||||
if (!validTypes.Contains(EntityType))
|
||||
if (validTypes.Contains(EntityType) == false)
|
||||
throw new Exception(string.Format("Unexpected entity type \"{0}\".", EntityType));
|
||||
}
|
||||
|
||||
@@ -260,7 +281,7 @@ namespace Umbraco.Core
|
||||
|
||||
public static bool operator !=(Udi udi1, Udi udi2)
|
||||
{
|
||||
return !(udi1 == udi2);
|
||||
return (udi1 == udi2) == false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -7,52 +7,82 @@ namespace Umbraco.Core
|
||||
|
||||
public static partial class Constants
|
||||
{
|
||||
|
||||
/// <summary>
|
||||
/// Defines well-known entity types.
|
||||
/// </summary>
|
||||
/// <remarks>Well-known entity types are those that Deploy already knows about,
|
||||
/// but entity types are strings and so can be extended beyond what is defined here.</remarks>
|
||||
public static class DeployEntityType
|
||||
public static class UdiEntityType
|
||||
{
|
||||
[UdiType(UdiType.Unknown)]
|
||||
public const string Unknown = "unknown";
|
||||
|
||||
// guid entity types
|
||||
|
||||
[UdiType(UdiType.GuidUdi)]
|
||||
public const string AnyGuid = "any-guid"; // that one is for tests
|
||||
|
||||
[UdiType(UdiType.GuidUdi)]
|
||||
public const string Document = "document";
|
||||
[UdiType(UdiType.GuidUdi)]
|
||||
public const string Media = "media";
|
||||
[UdiType(UdiType.GuidUdi)]
|
||||
public const string Member = "member";
|
||||
|
||||
[UdiType(UdiType.GuidUdi)]
|
||||
public const string DictionaryItem = "dictionary-item";
|
||||
[UdiType(UdiType.GuidUdi)]
|
||||
public const string Macro = "macro";
|
||||
[UdiType(UdiType.GuidUdi)]
|
||||
public const string Template = "template";
|
||||
|
||||
[UdiType(UdiType.GuidUdi)]
|
||||
public const string DocumentType = "document-type";
|
||||
[UdiType(UdiType.GuidUdi)]
|
||||
public const string DocumentTypeContainer = "document-type-container";
|
||||
[UdiType(UdiType.GuidUdi)]
|
||||
public const string MediaType = "media-type";
|
||||
[UdiType(UdiType.GuidUdi)]
|
||||
public const string MediaTypeContainer = "media-type-container";
|
||||
[UdiType(UdiType.GuidUdi)]
|
||||
public const string DataType = "data-type";
|
||||
[UdiType(UdiType.GuidUdi)]
|
||||
public const string DataTypeContainer = "data-type-container";
|
||||
[UdiType(UdiType.GuidUdi)]
|
||||
public const string MemberType = "member-type";
|
||||
[UdiType(UdiType.GuidUdi)]
|
||||
public const string MemberGroup = "member-group";
|
||||
|
||||
[UdiType(UdiType.GuidUdi)]
|
||||
public const string RelationType = "relation-type";
|
||||
|
||||
|
||||
// forms
|
||||
|
||||
[UdiType(UdiType.GuidUdi)]
|
||||
public const string FormsForm = "forms-form";
|
||||
[UdiType(UdiType.GuidUdi)]
|
||||
public const string FormsPreValue = "forms-prevalue";
|
||||
[UdiType(UdiType.GuidUdi)]
|
||||
public const string FormsDataSource = "forms-datasource";
|
||||
|
||||
// string entity types
|
||||
|
||||
[UdiType(UdiType.StringUdi)]
|
||||
public const string AnyString = "any-string"; // that one is for tests
|
||||
|
||||
[UdiType(UdiType.StringUdi)]
|
||||
public const string MediaFile = "media-file";
|
||||
[UdiType(UdiType.StringUdi)]
|
||||
public const string TemplateFile = "template-file";
|
||||
[UdiType(UdiType.StringUdi)]
|
||||
public const string Script = "script";
|
||||
[UdiType(UdiType.StringUdi)]
|
||||
public const string Stylesheet = "stylesheet";
|
||||
[UdiType(UdiType.StringUdi)]
|
||||
public const string PartialView = "partial-view";
|
||||
[UdiType(UdiType.StringUdi)]
|
||||
public const string PartialViewMacro = "partial-view-macro";
|
||||
[UdiType(UdiType.StringUdi)]
|
||||
public const string Xslt = "xslt";
|
||||
|
||||
public static string FromUmbracoObjectType(UmbracoObjectTypes umbracoObjectType)
|
||||
@@ -141,6 +171,15 @@ namespace Umbraco.Core
|
||||
}
|
||||
}
|
||||
|
||||
[AttributeUsage(AttributeTargets.Field)]
|
||||
internal class UdiTypeAttribute : Attribute
|
||||
{
|
||||
public UdiType UdiType { get; private set; }
|
||||
|
||||
public UdiTypeAttribute(UdiType udiType)
|
||||
{
|
||||
UdiType = udiType;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -17,7 +17,7 @@ namespace Umbraco.Core
|
||||
public static GuidUdi GetUdi(this ITemplate entity)
|
||||
{
|
||||
if (entity == null) throw new ArgumentNullException("entity");
|
||||
return new GuidUdi(Constants.DeployEntityType.Template, entity.Key).EnsureClosed();
|
||||
return new GuidUdi(Constants.UdiEntityType.Template, entity.Key).EnsureClosed();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -28,7 +28,7 @@ namespace Umbraco.Core
|
||||
public static GuidUdi GetUdi(this IContentType entity)
|
||||
{
|
||||
if (entity == null) throw new ArgumentNullException("entity");
|
||||
return new GuidUdi(Constants.DeployEntityType.DocumentType, entity.Key).EnsureClosed();
|
||||
return new GuidUdi(Constants.UdiEntityType.DocumentType, entity.Key).EnsureClosed();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -39,7 +39,7 @@ namespace Umbraco.Core
|
||||
public static GuidUdi GetUdi(this IMediaType entity)
|
||||
{
|
||||
if (entity == null) throw new ArgumentNullException("entity");
|
||||
return new GuidUdi(Constants.DeployEntityType.MediaType, entity.Key).EnsureClosed();
|
||||
return new GuidUdi(Constants.UdiEntityType.MediaType, entity.Key).EnsureClosed();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -50,7 +50,7 @@ namespace Umbraco.Core
|
||||
public static GuidUdi GetUdi(this IMemberType entity)
|
||||
{
|
||||
if (entity == null) throw new ArgumentNullException("entity");
|
||||
return new GuidUdi(Constants.DeployEntityType.MemberType, entity.Key).EnsureClosed();
|
||||
return new GuidUdi(Constants.UdiEntityType.MemberType, entity.Key).EnsureClosed();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -61,7 +61,7 @@ namespace Umbraco.Core
|
||||
public static GuidUdi GetUdi(this IMemberGroup entity)
|
||||
{
|
||||
if (entity == null) throw new ArgumentNullException("entity");
|
||||
return new GuidUdi(Constants.DeployEntityType.MemberGroup, entity.Key).EnsureClosed();
|
||||
return new GuidUdi(Constants.UdiEntityType.MemberGroup, entity.Key).EnsureClosed();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -74,9 +74,9 @@ namespace Umbraco.Core
|
||||
if (entity == null) throw new ArgumentNullException("entity");
|
||||
|
||||
string type;
|
||||
if (entity is IContentType) type = Constants.DeployEntityType.DocumentType;
|
||||
else if (entity is IMediaType) type = Constants.DeployEntityType.MediaType;
|
||||
else if (entity is IMemberType) type = Constants.DeployEntityType.MemberType;
|
||||
if (entity is IContentType) type = Constants.UdiEntityType.DocumentType;
|
||||
else if (entity is IMediaType) type = Constants.UdiEntityType.MediaType;
|
||||
else if (entity is IMemberType) type = Constants.UdiEntityType.MemberType;
|
||||
else throw new NotSupportedException(string.Format("Composition type {0} is not supported.", entity.GetType().FullName));
|
||||
return new GuidUdi(type, entity.Key).EnsureClosed();
|
||||
}
|
||||
@@ -89,7 +89,7 @@ namespace Umbraco.Core
|
||||
public static GuidUdi GetUdi(this IDataTypeDefinition entity)
|
||||
{
|
||||
if (entity == null) throw new ArgumentNullException("entity");
|
||||
return new GuidUdi(Constants.DeployEntityType.DataType, entity.Key).EnsureClosed();
|
||||
return new GuidUdi(Constants.UdiEntityType.DataType, entity.Key).EnsureClosed();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -103,11 +103,11 @@ namespace Umbraco.Core
|
||||
|
||||
string entityType;
|
||||
if (entity.ContainedObjectType == Constants.ObjectTypes.DataTypeGuid)
|
||||
entityType = Constants.DeployEntityType.DataTypeContainer;
|
||||
entityType = Constants.UdiEntityType.DataTypeContainer;
|
||||
else if (entity.ContainedObjectType == Constants.ObjectTypes.DocumentTypeGuid)
|
||||
entityType = Constants.DeployEntityType.DocumentTypeContainer;
|
||||
entityType = Constants.UdiEntityType.DocumentTypeContainer;
|
||||
else if (entity.ContainedObjectType == Constants.ObjectTypes.MediaTypeGuid)
|
||||
entityType = Constants.DeployEntityType.MediaTypeContainer;
|
||||
entityType = Constants.UdiEntityType.MediaTypeContainer;
|
||||
else
|
||||
throw new NotSupportedException(string.Format("Contained object type {0} is not supported.", entity.ContainedObjectType));
|
||||
return new GuidUdi(entityType, entity.Key).EnsureClosed();
|
||||
@@ -121,7 +121,7 @@ namespace Umbraco.Core
|
||||
public static GuidUdi GetUdi(this IMedia entity)
|
||||
{
|
||||
if (entity == null) throw new ArgumentNullException("entity");
|
||||
return new GuidUdi(Constants.DeployEntityType.Media, entity.Key).EnsureClosed();
|
||||
return new GuidUdi(Constants.UdiEntityType.Media, entity.Key).EnsureClosed();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -132,7 +132,7 @@ namespace Umbraco.Core
|
||||
public static GuidUdi GetUdi(this IContent entity)
|
||||
{
|
||||
if (entity == null) throw new ArgumentNullException("entity");
|
||||
return new GuidUdi(Constants.DeployEntityType.Document, entity.Key).EnsureClosed();
|
||||
return new GuidUdi(Constants.UdiEntityType.Document, entity.Key).EnsureClosed();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -143,7 +143,7 @@ namespace Umbraco.Core
|
||||
public static GuidUdi GetUdi(this IMember entity)
|
||||
{
|
||||
if (entity == null) throw new ArgumentNullException("entity");
|
||||
return new GuidUdi(Constants.DeployEntityType.Member, entity.Key).EnsureClosed();
|
||||
return new GuidUdi(Constants.UdiEntityType.Member, entity.Key).EnsureClosed();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -154,7 +154,7 @@ namespace Umbraco.Core
|
||||
public static StringUdi GetUdi(this Stylesheet entity)
|
||||
{
|
||||
if (entity == null) throw new ArgumentNullException("entity");
|
||||
return new StringUdi(Constants.DeployEntityType.Stylesheet, entity.Path.TrimStart('/')).EnsureClosed();
|
||||
return new StringUdi(Constants.UdiEntityType.Stylesheet, entity.Path.TrimStart('/')).EnsureClosed();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -165,7 +165,7 @@ namespace Umbraco.Core
|
||||
public static StringUdi GetUdi(this Script entity)
|
||||
{
|
||||
if (entity == null) throw new ArgumentNullException("entity");
|
||||
return new StringUdi(Constants.DeployEntityType.Script, entity.Path.TrimStart('/')).EnsureClosed();
|
||||
return new StringUdi(Constants.UdiEntityType.Script, entity.Path.TrimStart('/')).EnsureClosed();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -176,7 +176,7 @@ namespace Umbraco.Core
|
||||
public static GuidUdi GetUdi(this IDictionaryItem entity)
|
||||
{
|
||||
if (entity == null) throw new ArgumentNullException("entity");
|
||||
return new GuidUdi(Constants.DeployEntityType.DictionaryItem, entity.Key).EnsureClosed();
|
||||
return new GuidUdi(Constants.UdiEntityType.DictionaryItem, entity.Key).EnsureClosed();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -187,7 +187,7 @@ namespace Umbraco.Core
|
||||
public static GuidUdi GetUdi(this IMacro entity)
|
||||
{
|
||||
if (entity == null) throw new ArgumentNullException("entity");
|
||||
return new GuidUdi(Constants.DeployEntityType.Macro, entity.Key).EnsureClosed();
|
||||
return new GuidUdi(Constants.UdiEntityType.Macro, entity.Key).EnsureClosed();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -198,7 +198,7 @@ namespace Umbraco.Core
|
||||
public static StringUdi GetUdi(this IPartialView entity)
|
||||
{
|
||||
if (entity == null) throw new ArgumentNullException("entity");
|
||||
return new StringUdi(Constants.DeployEntityType.PartialView, entity.Path.TrimStart('/')).EnsureClosed();
|
||||
return new StringUdi(Constants.UdiEntityType.PartialView, entity.Path.TrimStart('/')).EnsureClosed();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -209,7 +209,7 @@ namespace Umbraco.Core
|
||||
public static StringUdi GetUdi(this IXsltFile entity)
|
||||
{
|
||||
if (entity == null) throw new ArgumentNullException("entity");
|
||||
return new StringUdi(Constants.DeployEntityType.Xslt, entity.Path.TrimStart('/')).EnsureClosed();
|
||||
return new StringUdi(Constants.UdiEntityType.Xslt, entity.Path.TrimStart('/')).EnsureClosed();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -222,9 +222,9 @@ namespace Umbraco.Core
|
||||
if (entity == null) throw new ArgumentNullException("entity");
|
||||
|
||||
string type;
|
||||
if (entity is IContent) type = Constants.DeployEntityType.Document;
|
||||
else if (entity is IMedia) type = Constants.DeployEntityType.Media;
|
||||
else if (entity is IMember) type = Constants.DeployEntityType.Member;
|
||||
if (entity is IContent) type = Constants.UdiEntityType.Document;
|
||||
else if (entity is IMedia) type = Constants.UdiEntityType.Media;
|
||||
else if (entity is IMember) type = Constants.UdiEntityType.Member;
|
||||
else throw new NotSupportedException(string.Format("ContentBase type {0} is not supported.", entity.GetType().FullName));
|
||||
return new GuidUdi(type, entity.Key).EnsureClosed();
|
||||
}
|
||||
@@ -237,7 +237,7 @@ namespace Umbraco.Core
|
||||
public static GuidUdi GetUdi(this IRelationType entity)
|
||||
{
|
||||
if (entity == null) throw new ArgumentNullException("entity");
|
||||
return new GuidUdi(Constants.DeployEntityType.RelationType, entity.Key).EnsureClosed();
|
||||
return new GuidUdi(Constants.UdiEntityType.RelationType, entity.Key).EnsureClosed();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -0,0 +1,37 @@
|
||||
using System;
|
||||
using System.ComponentModel;
|
||||
using System.Globalization;
|
||||
|
||||
namespace Umbraco.Core
|
||||
{
|
||||
/// <summary>
|
||||
/// A custom type converter for UDI
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Primarily this is used so that WebApi can auto-bind a string parameter to a UDI instance
|
||||
/// </remarks>
|
||||
internal class UdiTypeConverter : TypeConverter
|
||||
{
|
||||
public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType)
|
||||
{
|
||||
if (sourceType == typeof(string))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
return base.CanConvertFrom(context, sourceType);
|
||||
}
|
||||
|
||||
public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, object value)
|
||||
{
|
||||
if (value is string)
|
||||
{
|
||||
Udi udi;
|
||||
if (Udi.TryParse((string)value, out udi))
|
||||
{
|
||||
return udi;
|
||||
}
|
||||
}
|
||||
return base.ConvertFrom(context, culture, value);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -163,6 +163,7 @@
|
||||
<Compile Include="Cache\DeepCloneRuntimeCacheProvider.cs" />
|
||||
<Compile Include="CodeAnnotations\FriendlyNameAttribute.cs" />
|
||||
<Compile Include="CodeAnnotations\UmbracoObjectTypeAttribute.cs" />
|
||||
<Compile Include="CodeAnnotations\UmbracoUdiTypeAttribute.cs" />
|
||||
<Compile Include="CodeAnnotations\UmbracoWillObsoleteAttribute.cs" />
|
||||
<Compile Include="CodeAnnotations\UmbracoExperimentalFeatureAttribute.cs" />
|
||||
<Compile Include="CodeAnnotations\UmbracoProposedPublicAttribute.cs" />
|
||||
@@ -289,7 +290,6 @@
|
||||
<Compile Include="Configuration\UmbracoSettings\WebRoutingElement.cs" />
|
||||
<Compile Include="Configuration\UmbracoVersion.cs" />
|
||||
<Compile Include="Attempt.cs" />
|
||||
<Compile Include="Constants-DeployEntityType.cs" />
|
||||
<Compile Include="Constants-DeploySelector.cs" />
|
||||
<Compile Include="Constants-Examine.cs" />
|
||||
<Compile Include="Constants-Icons.cs" />
|
||||
@@ -311,10 +311,13 @@
|
||||
<Compile Include="Deploy\ArtifactSignature.cs" />
|
||||
<Compile Include="Deploy\Difference.cs" />
|
||||
<Compile Include="Deploy\Direction.cs" />
|
||||
<Compile Include="Deploy\IFileStore.cs" />
|
||||
<Compile Include="Deploy\IFileType.cs" />
|
||||
<Compile Include="Deploy\IFileTypeCollection.cs" />
|
||||
<Compile Include="Events\EventDefinitionFilter.cs" />
|
||||
<Compile Include="Events\IDeletingMediaFilesEventArgs.cs" />
|
||||
<Compile Include="Events\ScopeEventDispatcherBase.cs" />
|
||||
<Compile Include="Events\ScopeLifespanMessagesFactory.cs" />
|
||||
<Compile Include="IHttpContextAccessor.cs" />
|
||||
<Compile Include="OrderedHashSet.cs" />
|
||||
<Compile Include="Events\UninstallPackageEventArgs.cs" />
|
||||
<Compile Include="Models\GridValue.cs" />
|
||||
@@ -326,7 +329,6 @@
|
||||
<Compile Include="Deploy\IImageSourceParser.cs" />
|
||||
<Compile Include="Deploy\ILocalLinkParser.cs" />
|
||||
<Compile Include="Deploy\IMacroParser.cs" />
|
||||
<Compile Include="Deploy\IPrettyArtifact.cs" />
|
||||
<Compile Include="Deploy\IPreValueConnector.cs" />
|
||||
<Compile Include="Deploy\IServiceConnector.cs" />
|
||||
<Compile Include="Deploy\IValueConnector.cs" />
|
||||
@@ -485,6 +487,7 @@
|
||||
<Compile Include="Persistence\Migrations\Upgrades\TargetVersionSevenSixZero\AddIndexToCmsMemberLoginName.cs" />
|
||||
<Compile Include="Persistence\Migrations\Upgrades\TargetVersionSevenSixZero\AddIndexesToUmbracoRelationTables.cs" />
|
||||
<Compile Include="Persistence\Migrations\Upgrades\TargetVersionSevenSixZero\AddIndexToUmbracoNodePath.cs" />
|
||||
<Compile Include="Persistence\Migrations\Upgrades\TargetVersionSevenSixZero\AddIndexToUser2NodePermission.cs" />
|
||||
<Compile Include="Persistence\Migrations\Upgrades\TargetVersionSevenSixZero\AddRelationTypeUniqueIdColumn.cs" />
|
||||
<Compile Include="Persistence\Migrations\Upgrades\TargetVersionSevenSixZero\AddMacroUniqueIdColumn.cs" />
|
||||
<Compile Include="Persistence\Migrations\Upgrades\TargetVersionSevenSixZero\RemovePropertyDataIdIndex.cs" />
|
||||
@@ -1440,9 +1443,11 @@
|
||||
<Compile Include="TypeHelper.cs" />
|
||||
<Compile Include="Udi.cs" />
|
||||
<Compile Include="UdiDefinitionAttribute.cs" />
|
||||
<Compile Include="UdiEntityType.cs" />
|
||||
<Compile Include="UdiGetterExtensions.cs" />
|
||||
<Compile Include="UdiRange.cs" />
|
||||
<Compile Include="UdiType.cs" />
|
||||
<Compile Include="UdiTypeConverter.cs" />
|
||||
<Compile Include="UmbracoApplicationBase.cs" />
|
||||
<Compile Include="Constants.cs" />
|
||||
<Compile Include="Constants-Applications.cs">
|
||||
|
||||
@@ -336,8 +336,9 @@ namespace Umbraco.Tests.IO
|
||||
using (var ms = new MemoryStream(Encoding.UTF8.GetBytes("foo")))
|
||||
ss.AddFile("path/to/some/dir/f1.txt", ms);
|
||||
|
||||
// file is only written to the shadow fs
|
||||
Assert.IsTrue(File.Exists(path + "/ShadowSystem/path/to/some/dir/f1.txt"));
|
||||
|
||||
Assert.IsFalse(File.Exists(path + "/ShadowTests/path/to/some/dir/f1.txt"));
|
||||
// let the shadow fs die
|
||||
}
|
||||
|
||||
@@ -382,7 +383,7 @@ namespace Umbraco.Tests.IO
|
||||
|
||||
var fs = new PhysicalFileSystem(path, "ignore");
|
||||
var sw = new ShadowWrapper(fs, "shadow", scopeProvider);
|
||||
var swa = new[] { sw };
|
||||
var swa = new[] {sw};
|
||||
|
||||
using (var ms = new MemoryStream(Encoding.UTF8.GetBytes("foo")))
|
||||
sw.AddFile("sub/f1.txt", ms);
|
||||
@@ -463,7 +464,7 @@ namespace Umbraco.Tests.IO
|
||||
|
||||
var fs = new PhysicalFileSystem(path, "ignore");
|
||||
var sw = new ShadowWrapper(fs, "shadow", scopeProvider);
|
||||
var swa = new[] { sw };
|
||||
var swa = new[] {sw};
|
||||
|
||||
using (var ms = new MemoryStream(Encoding.UTF8.GetBytes("foo")))
|
||||
sw.AddFile("sub/f1.txt", ms);
|
||||
@@ -512,7 +513,7 @@ namespace Umbraco.Tests.IO
|
||||
|
||||
var fs = new PhysicalFileSystem(path, "ignore");
|
||||
var sw = new ShadowWrapper(fs, "shadow", scopeProvider);
|
||||
var swa = new[] { sw };
|
||||
var swa = new[] {sw};
|
||||
|
||||
using (var ms = new MemoryStream(Encoding.UTF8.GetBytes("foo")))
|
||||
sw.AddFile("sub/f1.txt", ms);
|
||||
@@ -623,5 +624,385 @@ namespace Umbraco.Tests.IO
|
||||
providerMock.Setup(x => x.AmbientScope).Returns(scopeMock.Object);
|
||||
return providerMock.Object;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Check that GetFiles will return all files on the shadow, while returning
|
||||
/// just one on each of the filesystems used by the shadow.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void ShadowGetFiles()
|
||||
{
|
||||
// Arrange
|
||||
var path = IOHelper.MapPath("FileSysTests");
|
||||
Directory.CreateDirectory(path);
|
||||
Directory.CreateDirectory(path + "/ShadowTests");
|
||||
Directory.CreateDirectory(path + "/ShadowSystem");
|
||||
|
||||
var fs = new PhysicalFileSystem(path + "/ShadowTests/", "ignore");
|
||||
var sfs = new PhysicalFileSystem(path + "/ShadowSystem/", "ignore");
|
||||
var ss = new ShadowFileSystem(fs, sfs);
|
||||
|
||||
// Act
|
||||
File.WriteAllText(path + "/ShadowTests/f2.txt", "foo");
|
||||
using (var ms = new MemoryStream(Encoding.UTF8.GetBytes("foo")))
|
||||
ss.AddFile("f1.txt", ms);
|
||||
|
||||
// Assert
|
||||
// ensure we get 2 files from the shadow
|
||||
var getFiles = ss.GetFiles(string.Empty);
|
||||
Assert.AreEqual(2, getFiles.Count());
|
||||
|
||||
var fsFiles = fs.GetFiles(string.Empty).ToArray();
|
||||
Assert.AreEqual(1, fsFiles.Length);
|
||||
var sfsFiles = sfs.GetFiles(string.Empty).ToArray();
|
||||
Assert.AreEqual(1, sfsFiles.Length);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Check that GetFiles using the filter function with empty string will return expected results
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void ShadowGetFilesUsingEmptyFilter()
|
||||
{
|
||||
// Arrange
|
||||
var path = IOHelper.MapPath("FileSysTests");
|
||||
Directory.CreateDirectory(path);
|
||||
Directory.CreateDirectory(path + "/ShadowTests");
|
||||
Directory.CreateDirectory(path + "/ShadowSystem");
|
||||
|
||||
var fs = new PhysicalFileSystem(path + "/ShadowTests/", "ignore");
|
||||
var sfs = new PhysicalFileSystem(path + "/ShadowSystem/", "ignore");
|
||||
var ss = new ShadowFileSystem(fs, sfs);
|
||||
|
||||
// Act
|
||||
File.WriteAllText(path + "/ShadowTests/f2.txt", "foo");
|
||||
using (var ms = new MemoryStream(Encoding.UTF8.GetBytes("foo")))
|
||||
ss.AddFile("f1.txt", ms);
|
||||
|
||||
// Assert
|
||||
// ensure we get 2 files from the shadow
|
||||
var getFiles = ss.GetFiles(string.Empty);
|
||||
Assert.AreEqual(2, getFiles.Count());
|
||||
// ensure we get 0 files when using a empty filter
|
||||
var getFilesWithEmptyFilter = ss.GetFiles(string.Empty, "");
|
||||
Assert.AreEqual(0, getFilesWithEmptyFilter.Count());
|
||||
|
||||
var fsFiles = fs.GetFiles(string.Empty).ToArray();
|
||||
Assert.AreEqual(1, fsFiles.Length);
|
||||
var sfsFiles = sfs.GetFiles(string.Empty).ToArray();
|
||||
Assert.AreEqual(1, sfsFiles.Length);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Check that GetFiles using the filter function with null will return expected results
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void ShadowGetFilesUsingNullFilter()
|
||||
{
|
||||
// Arrange
|
||||
var path = IOHelper.MapPath("FileSysTests");
|
||||
Directory.CreateDirectory(path);
|
||||
Directory.CreateDirectory(path + "/ShadowTests");
|
||||
Directory.CreateDirectory(path + "/ShadowSystem");
|
||||
|
||||
var fs = new PhysicalFileSystem(path + "/ShadowTests/", "ignore");
|
||||
var sfs = new PhysicalFileSystem(path + "/ShadowSystem/", "ignore");
|
||||
var ss = new ShadowFileSystem(fs, sfs);
|
||||
|
||||
// Act
|
||||
File.WriteAllText(path + "/ShadowTests/f2.txt", "foo");
|
||||
using (var ms = new MemoryStream(Encoding.UTF8.GetBytes("foo")))
|
||||
ss.AddFile("f1.txt", ms);
|
||||
|
||||
// Assert
|
||||
// ensure we get 2 files from the shadow
|
||||
var getFiles = ss.GetFiles(string.Empty);
|
||||
Assert.AreEqual(2, getFiles.Count());
|
||||
// ensure we get 2 files when using null in filter parameter
|
||||
var getFilesWithNullFilter = ss.GetFiles(string.Empty, null);
|
||||
Assert.AreEqual(2, getFilesWithNullFilter.Count());
|
||||
|
||||
var fsFiles = fs.GetFiles(string.Empty).ToArray();
|
||||
Assert.AreEqual(1, fsFiles.Length);
|
||||
var sfsFiles = sfs.GetFiles(string.Empty).ToArray();
|
||||
Assert.AreEqual(1, sfsFiles.Length);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void ShadowGetFilesUsingWildcardFilter()
|
||||
{
|
||||
// Arrange
|
||||
var path = IOHelper.MapPath("FileSysTests");
|
||||
Directory.CreateDirectory(path);
|
||||
Directory.CreateDirectory(path + "/ShadowTests");
|
||||
Directory.CreateDirectory(path + "/ShadowSystem");
|
||||
|
||||
var fs = new PhysicalFileSystem(path + "/ShadowTests/", "ignore");
|
||||
var sfs = new PhysicalFileSystem(path + "/ShadowSystem/", "ignore");
|
||||
var ss = new ShadowFileSystem(fs, sfs);
|
||||
|
||||
// Act
|
||||
File.WriteAllText(path + "/ShadowTests/f2.txt", "foo");
|
||||
File.WriteAllText(path + "/ShadowTests/f2.doc", "foo");
|
||||
using (var ms = new MemoryStream(Encoding.UTF8.GetBytes("foo")))
|
||||
ss.AddFile("f1.txt", ms);
|
||||
using (var ms = new MemoryStream(Encoding.UTF8.GetBytes("foo")))
|
||||
ss.AddFile("f1.doc", ms);
|
||||
|
||||
// Assert
|
||||
// ensure we get 4 files from the shadow
|
||||
var getFiles = ss.GetFiles(string.Empty);
|
||||
Assert.AreEqual(4, getFiles.Count());
|
||||
// ensure we get only 2 of 4 files from the shadow when using filter
|
||||
var getFilesWithWildcardFilter = ss.GetFiles(string.Empty, "*.doc");
|
||||
Assert.AreEqual(2, getFilesWithWildcardFilter.Count());
|
||||
|
||||
var fsFiles = fs.GetFiles(string.Empty).ToArray();
|
||||
Assert.AreEqual(2, fsFiles.Length);
|
||||
var sfsFiles = sfs.GetFiles(string.Empty).ToArray();
|
||||
Assert.AreEqual(2, sfsFiles.Length);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void ShadowGetFilesUsingSingleCharacterFilter()
|
||||
{
|
||||
// Arrange
|
||||
var path = IOHelper.MapPath("FileSysTests");
|
||||
Directory.CreateDirectory(path);
|
||||
Directory.CreateDirectory(path + "/ShadowTests");
|
||||
Directory.CreateDirectory(path + "/ShadowSystem");
|
||||
|
||||
var fs = new PhysicalFileSystem(path + "/ShadowTests/", "ignore");
|
||||
var sfs = new PhysicalFileSystem(path + "/ShadowSystem/", "ignore");
|
||||
var ss = new ShadowFileSystem(fs, sfs);
|
||||
|
||||
// Act
|
||||
File.WriteAllText(path + "/ShadowTests/f2.txt", "foo");
|
||||
File.WriteAllText(path + "/ShadowTests/f2.doc", "foo");
|
||||
File.WriteAllText(path + "/ShadowTests/f2.docx", "foo");
|
||||
using (var ms = new MemoryStream(Encoding.UTF8.GetBytes("foo")))
|
||||
ss.AddFile("f1.txt", ms);
|
||||
using (var ms = new MemoryStream(Encoding.UTF8.GetBytes("foo")))
|
||||
ss.AddFile("f1.doc", ms);
|
||||
using (var ms = new MemoryStream(Encoding.UTF8.GetBytes("foo")))
|
||||
ss.AddFile("f1.docx", ms);
|
||||
|
||||
// Assert
|
||||
// ensure we get 6 files from the shadow
|
||||
var getFiles = ss.GetFiles(string.Empty);
|
||||
Assert.AreEqual(6, getFiles.Count());
|
||||
// ensure we get only 2 of 6 files from the shadow when using filter on shadow
|
||||
var getFilesWithWildcardSinglecharFilter = ss.GetFiles(string.Empty, "f1.d?c");
|
||||
Assert.AreEqual(1, getFilesWithWildcardSinglecharFilter.Count());
|
||||
// ensure we get only 2 of 6 files from the shadow when using filter on disk
|
||||
var getFilesWithWildcardSinglecharFilter2 = ss.GetFiles(string.Empty, "f2.d?c");
|
||||
Assert.AreEqual(1, getFilesWithWildcardSinglecharFilter2.Count());
|
||||
|
||||
var fsFiles = fs.GetFiles(string.Empty).ToArray();
|
||||
Assert.AreEqual(3, fsFiles.Length);
|
||||
var sfsFiles = sfs.GetFiles(string.Empty).ToArray();
|
||||
Assert.AreEqual(3, sfsFiles.Length);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void ShadowGetFilesUsingWildcardAndSingleCharacterFilter()
|
||||
{
|
||||
// Arrange
|
||||
var path = IOHelper.MapPath("FileSysTests");
|
||||
Directory.CreateDirectory(path);
|
||||
Directory.CreateDirectory(path + "/ShadowTests");
|
||||
Directory.CreateDirectory(path + "/ShadowSystem");
|
||||
|
||||
var fs = new PhysicalFileSystem(path + "/ShadowTests/", "ignore");
|
||||
var sfs = new PhysicalFileSystem(path + "/ShadowSystem/", "ignore");
|
||||
var ss = new ShadowFileSystem(fs, sfs);
|
||||
|
||||
// Act
|
||||
File.WriteAllText(path + "/ShadowTests/f2.txt", "foo");
|
||||
File.WriteAllText(path + "/ShadowTests/f2.doc", "foo");
|
||||
File.WriteAllText(path + "/ShadowTests/f2.docx", "foo");
|
||||
using (var ms = new MemoryStream(Encoding.UTF8.GetBytes("foo")))
|
||||
ss.AddFile("f1.txt", ms);
|
||||
using (var ms = new MemoryStream(Encoding.UTF8.GetBytes("foo")))
|
||||
ss.AddFile("f1.doc", ms);
|
||||
using (var ms = new MemoryStream(Encoding.UTF8.GetBytes("foo")))
|
||||
ss.AddFile("f1.docx", ms);
|
||||
|
||||
// Assert
|
||||
// ensure we get 6 files from the shadow
|
||||
var getFiles = ss.GetFiles(string.Empty);
|
||||
Assert.AreEqual(6, getFiles.Count());
|
||||
var getFilesWithWildcardSinglecharFilter = ss.GetFiles(string.Empty, "*.d?c");
|
||||
|
||||
Assert.AreEqual(4, getFilesWithWildcardSinglecharFilter.Count());
|
||||
var getFilesWithWildcardSinglecharFilter2 = ss.GetFiles(string.Empty, "*.d?cx");
|
||||
Assert.AreEqual(2, getFilesWithWildcardSinglecharFilter2.Count());
|
||||
|
||||
var fsFiles = fs.GetFiles(string.Empty).ToArray();
|
||||
Assert.AreEqual(3, fsFiles.Length);
|
||||
var sfsFiles = sfs.GetFiles(string.Empty).ToArray();
|
||||
Assert.AreEqual(3, sfsFiles.Length);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void ShadowFileSystemFilterIsAsBrokenAsRealFileSystemFilter()
|
||||
{
|
||||
// Arrange
|
||||
var path = IOHelper.MapPath("FileSysTests");
|
||||
Directory.CreateDirectory(path);
|
||||
Directory.CreateDirectory(path + "/filter");
|
||||
// create files on disk and create a "fake" list of files to verify filters against
|
||||
File.WriteAllText(path + "/filter/f1.txt", "foo");
|
||||
File.WriteAllText(path + "/filter/f1.doc", "foo");
|
||||
File.WriteAllText(path + "/filter/f1.docx", "foo");
|
||||
var files = new string[]
|
||||
{
|
||||
"f1.txt",
|
||||
"f1.doc",
|
||||
"f1.docx",
|
||||
};
|
||||
var filter1 = "";
|
||||
var filter2 = "*";
|
||||
var filter3 = "*.doc";
|
||||
var filter4 = "*.d?c";
|
||||
var filter5 = "f1.doc";
|
||||
var filter6 = "f1.d?c";
|
||||
var filter7 = "**.d?c";
|
||||
var filter8 = "f*.doc";
|
||||
|
||||
// Act & Assert
|
||||
var result1Disk = Directory.GetFiles(path + "/filter/", filter1).Select(Path.GetFileName).OrderBy(x => x).ToArray();
|
||||
var result1Fake = files.Where(x => ShadowFileSystem.FilterByRegex(x, ShadowFileSystem.FilterToRegex(filter1))).OrderBy(x => x).ToArray();
|
||||
Assert.AreEqual(result1Disk, result1Fake);
|
||||
var result2Disk = Directory.GetFiles(path + "/filter/", filter2).Select(Path.GetFileName).OrderBy(x => x).ToArray();
|
||||
var result2Fake = files.Where(x => ShadowFileSystem.FilterByRegex(x, ShadowFileSystem.FilterToRegex(filter2))).OrderBy(x => x).ToArray();
|
||||
Assert.AreEqual(result2Disk, result2Fake);
|
||||
var result3Disk = Directory.GetFiles(path + "/filter/", filter3).Select(Path.GetFileName).OrderBy(x => x).ToArray();
|
||||
var result3Fake = files.Where(x => ShadowFileSystem.FilterByRegex(x, ShadowFileSystem.FilterToRegex(filter3))).OrderBy(x => x).ToArray();
|
||||
Assert.AreEqual(result3Disk, result3Fake);
|
||||
var result4Disk = Directory.GetFiles(path + "/filter/", filter4).Select(Path.GetFileName).OrderBy(x => x).ToArray();
|
||||
var result4Fake = files.Where(x => ShadowFileSystem.FilterByRegex(x, ShadowFileSystem.FilterToRegex(filter4))).OrderBy(x => x).ToArray();
|
||||
Assert.AreEqual(result4Disk, result4Fake);
|
||||
var result5Disk = Directory.GetFiles(path + "/filter/", filter5).Select(Path.GetFileName).OrderBy(x => x).ToArray();
|
||||
var result5Fake = files.Where(x => ShadowFileSystem.FilterByRegex(x, ShadowFileSystem.FilterToRegex(filter5))).OrderBy(x => x).ToArray();
|
||||
Assert.AreEqual(result5Disk, result5Fake);
|
||||
var result6Disk = Directory.GetFiles(path + "/filter/", filter6).Select(Path.GetFileName).OrderBy(x => x).ToArray();
|
||||
var result6Fake = files.Where(x => ShadowFileSystem.FilterByRegex(x, ShadowFileSystem.FilterToRegex(filter6))).OrderBy(x => x).ToArray();
|
||||
Assert.AreEqual(result6Disk, result6Fake);
|
||||
var result7Disk = Directory.GetFiles(path + "/filter/", filter7).Select(Path.GetFileName).OrderBy(x => x).ToArray();
|
||||
var result7Fake = files.Where(x => ShadowFileSystem.FilterByRegex(x, ShadowFileSystem.FilterToRegex(filter7))).OrderBy(x => x).ToArray();
|
||||
Assert.AreEqual(result7Disk, result7Fake);
|
||||
var result8Disk = Directory.GetFiles(path + "/filter/", filter8).Select(Path.GetFileName).OrderBy(x => x).ToArray();
|
||||
var result8Fake = files.Where(x => ShadowFileSystem.FilterByRegex(x, ShadowFileSystem.FilterToRegex(filter8))).OrderBy(x => x).ToArray();
|
||||
Assert.AreEqual(result8Disk, result8Fake);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the full paths of the files on the disk.
|
||||
/// Note that this will be the *actual* path of the file, meaning a file existing on the initialized FS
|
||||
/// will be in one location, while a file written after initializing the shadow, will exist at the
|
||||
/// shadow location directory.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void ShadowGetFullPath()
|
||||
{
|
||||
// Arrange
|
||||
var path = IOHelper.MapPath("FileSysTests");
|
||||
Directory.CreateDirectory(path);
|
||||
Directory.CreateDirectory(path + "/ShadowTests");
|
||||
Directory.CreateDirectory(path + "/ShadowSystem");
|
||||
|
||||
var fs = new PhysicalFileSystem(path + "/ShadowTests/", "ignore");
|
||||
var sfs = new PhysicalFileSystem(path + "/ShadowSystem/", "ignore");
|
||||
var ss = new ShadowFileSystem(fs, sfs);
|
||||
|
||||
// Act
|
||||
File.WriteAllText(path + "/ShadowTests/f1.txt", "foo");
|
||||
using (var ms = new MemoryStream(Encoding.UTF8.GetBytes("foo")))
|
||||
ss.AddFile("f2.txt", ms);
|
||||
|
||||
// Assert
|
||||
var f1FullPath = ss.GetFullPath("f1.txt");
|
||||
var f2FullPath = ss.GetFullPath("f2.txt");
|
||||
Assert.AreEqual(Path.Combine(path, "ShadowTests", "f1.txt"), f1FullPath);
|
||||
Assert.AreEqual(Path.Combine(path, "ShadowSystem", "f2.txt"), f2FullPath);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the path relative to the filesystem root
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This file stuff in this test is kinda irrelevant with the current implementation.
|
||||
/// We do tests that the files are written to the correct places and the relative path is returned correct,
|
||||
/// but GetRelativePath is currently really just string manipulation so files are not actually hit by the code.
|
||||
/// Leaving the file stuff in here for now in case the method becomes more clever at some point.
|
||||
/// </remarks>
|
||||
[Test]
|
||||
public void ShadowGetRelativePath()
|
||||
{
|
||||
// Arrange
|
||||
var path = IOHelper.MapPath("FileSysTests");
|
||||
Directory.CreateDirectory(path);
|
||||
Directory.CreateDirectory(path + "/ShadowTests");
|
||||
Directory.CreateDirectory(path + "/ShadowSystem");
|
||||
|
||||
var fs = new PhysicalFileSystem(path + "/ShadowTests/", "ignore");
|
||||
var sfs = new PhysicalFileSystem(path + "/ShadowSystem/", "ignore");
|
||||
var ss = new ShadowFileSystem(fs, sfs);
|
||||
|
||||
// Act
|
||||
File.WriteAllText(path + "/ShadowTests/f1.txt", "foo");
|
||||
using (var ms = new MemoryStream(Encoding.UTF8.GetBytes("foo")))
|
||||
ss.AddFile("f2.txt", ms);
|
||||
|
||||
// Assert
|
||||
var f1RelativePath = ss.GetRelativePath("f1.txt");
|
||||
var f2RelativePath = ss.GetRelativePath("f2.txt");
|
||||
Assert.AreEqual("f1.txt", f1RelativePath);
|
||||
Assert.AreEqual("f2.txt", f2RelativePath);
|
||||
Assert.IsTrue(File.Exists(Path.Combine(path, "ShadowTests", "f1.txt")));
|
||||
Assert.IsFalse(File.Exists(Path.Combine(path, "ShadowTests", "f2.txt")));
|
||||
Assert.IsTrue(File.Exists(Path.Combine(path, "ShadowSystem", "f2.txt")));
|
||||
Assert.IsFalse(File.Exists(Path.Combine(path, "ShadowSystem", "f1.txt")));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Ensure the url returned contains the path relative to the FS root,
|
||||
/// but including the rootUrl the FS was initialized with.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This file stuff in this test is kinda irrelevant with the current implementation.
|
||||
/// We do tests that the files are written to the correct places and the url is returned correct,
|
||||
/// but GetUrl is currently really just string manipulation so files are not actually hit by the code.
|
||||
/// Leaving the file stuff in here for now in case the method becomes more clever at some point.
|
||||
/// </remarks>
|
||||
[Test]
|
||||
public void ShadowGetUrl()
|
||||
{
|
||||
// Arrange
|
||||
var path = IOHelper.MapPath("FileSysTests");
|
||||
Directory.CreateDirectory(path);
|
||||
Directory.CreateDirectory(path + "/ShadowTests");
|
||||
Directory.CreateDirectory(path + "/ShadowSystem");
|
||||
|
||||
var fs = new PhysicalFileSystem(path + "/ShadowTests/", "rootUrl");
|
||||
var sfs = new PhysicalFileSystem(path + "/ShadowSystem/", "rootUrl");
|
||||
var ss = new ShadowFileSystem(fs, sfs);
|
||||
|
||||
// Act
|
||||
File.WriteAllText(path + "/ShadowTests/f1.txt", "foo");
|
||||
using (var ms = new MemoryStream(Encoding.UTF8.GetBytes("foo")))
|
||||
ss.AddFile("f2.txt", ms);
|
||||
|
||||
// Assert
|
||||
var f1Url = ss.GetUrl("f1.txt");
|
||||
var f2Url = ss.GetUrl("f2.txt");
|
||||
Assert.AreEqual("rootUrl/f1.txt", f1Url);
|
||||
Assert.AreEqual("rootUrl/f2.txt", f2Url);
|
||||
Assert.IsTrue(File.Exists(Path.Combine(path, "ShadowTests", "f1.txt")));
|
||||
Assert.IsFalse(File.Exists(Path.Combine(path, "ShadowTests", "f2.txt")));
|
||||
Assert.IsTrue(File.Exists(Path.Combine(path, "ShadowSystem", "f2.txt")));
|
||||
Assert.IsFalse(File.Exists(Path.Combine(path, "ShadowSystem", "f1.txt")));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -441,7 +441,7 @@ namespace Umbraco.Tests.Persistence.Repositories
|
||||
{
|
||||
|
||||
// Act
|
||||
var exists = repository.Exists(1034); //Content picker
|
||||
var exists = repository.Exists(1046); //Content picker
|
||||
var doesntExist = repository.Exists(-80);
|
||||
|
||||
// Assert
|
||||
|
||||
@@ -1343,6 +1343,69 @@ namespace Umbraco.Tests.Services
|
||||
Assert.That(contents.Any(), Is.False);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Can_Empty_RecycleBin_With_Content_That_Has_All_Related_Data()
|
||||
{
|
||||
// Arrange
|
||||
//need to:
|
||||
// * add relations
|
||||
// * add permissions
|
||||
// * add notifications
|
||||
// * public access
|
||||
// * tags
|
||||
// * domain
|
||||
// * published & preview data
|
||||
// * multiple versions
|
||||
|
||||
var contentType = MockedContentTypes.CreateAllTypesContentType("test", "test");
|
||||
ServiceContext.ContentTypeService.Save(contentType, 0);
|
||||
|
||||
object obj =
|
||||
new
|
||||
{
|
||||
tags = "Hello,World"
|
||||
};
|
||||
var content1 = MockedContent.CreateBasicContent(contentType);
|
||||
content1.PropertyValues(obj);
|
||||
content1.ResetDirtyProperties(false);
|
||||
ServiceContext.ContentService.Save(content1, 0);
|
||||
Assert.IsTrue(ServiceContext.ContentService.PublishWithStatus(content1, 0).Success);
|
||||
var content2 = MockedContent.CreateBasicContent(contentType);
|
||||
content2.PropertyValues(obj);
|
||||
content2.ResetDirtyProperties(false);
|
||||
ServiceContext.ContentService.Save(content2, 0);
|
||||
Assert.IsTrue(ServiceContext.ContentService.PublishWithStatus(content2, 0).Success);
|
||||
|
||||
ServiceContext.RelationService.Save(new RelationType(Constants.ObjectTypes.DocumentGuid, Constants.ObjectTypes.DocumentGuid, "test"));
|
||||
Assert.IsNotNull(ServiceContext.RelationService.Relate(content1, content2, "test"));
|
||||
|
||||
ServiceContext.PublicAccessService.Save(new PublicAccessEntry(content1, content2, content2, new List<PublicAccessRule>
|
||||
{
|
||||
new PublicAccessRule
|
||||
{
|
||||
RuleType = "test",
|
||||
RuleValue = "test"
|
||||
}
|
||||
}));
|
||||
Assert.IsTrue(ServiceContext.PublicAccessService.AddRule(content1, "test2", "test2").Success);
|
||||
|
||||
Assert.IsNotNull(ServiceContext.NotificationService.CreateNotification(ServiceContext.UserService.GetUserById(0), content1, "test"));
|
||||
|
||||
ServiceContext.ContentService.AssignContentPermission(content1, 'A', new[] {0});
|
||||
|
||||
Assert.IsTrue(ServiceContext.DomainService.Save(new UmbracoDomain("www.test.com", "en-AU")
|
||||
{
|
||||
RootContentId = content1.Id
|
||||
}).Success);
|
||||
|
||||
// Act
|
||||
ServiceContext.ContentService.EmptyRecycleBin();
|
||||
var contents = ServiceContext.ContentService.GetContentInRecycleBin();
|
||||
|
||||
// Assert
|
||||
Assert.That(contents.Any(), Is.False);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Can_Move_Content()
|
||||
{
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using NUnit.Framework;
|
||||
using Umbraco.Core;
|
||||
@@ -25,8 +26,368 @@ namespace Umbraco.Tests.Services
|
||||
public override void TearDown()
|
||||
{
|
||||
base.TearDown();
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void EntityService_Can_Get_Paged_Content_Children()
|
||||
{
|
||||
|
||||
var contentType = ServiceContext.ContentTypeService.GetContentType("umbTextpage");
|
||||
|
||||
var root = MockedContent.CreateSimpleContent(contentType);
|
||||
ServiceContext.ContentService.Save(root);
|
||||
for (int i = 0; i < 10; i++)
|
||||
{
|
||||
var c1 = MockedContent.CreateSimpleContent(contentType, Guid.NewGuid().ToString(), root);
|
||||
ServiceContext.ContentService.Save(c1);
|
||||
}
|
||||
|
||||
var service = ServiceContext.EntityService;
|
||||
|
||||
long total;
|
||||
var entities = service.GetPagedChildren(root.Id, UmbracoObjectTypes.Document, 0, 6, out total).ToArray();
|
||||
Assert.That(entities.Length, Is.EqualTo(6));
|
||||
Assert.That(total, Is.EqualTo(10));
|
||||
entities = service.GetPagedChildren(root.Id, UmbracoObjectTypes.Document, 1, 6, out total).ToArray();
|
||||
Assert.That(entities.Length, Is.EqualTo(4));
|
||||
Assert.That(total, Is.EqualTo(10));
|
||||
}
|
||||
|
||||
|
||||
[Test]
|
||||
public void EntityService_Can_Get_Paged_Content_Descendants()
|
||||
{
|
||||
var contentType = ServiceContext.ContentTypeService.GetContentType("umbTextpage");
|
||||
|
||||
var root = MockedContent.CreateSimpleContent(contentType);
|
||||
ServiceContext.ContentService.Save(root);
|
||||
var count = 0;
|
||||
for (int i = 0; i < 10; i++)
|
||||
{
|
||||
var c1 = MockedContent.CreateSimpleContent(contentType, Guid.NewGuid().ToString(), root);
|
||||
ServiceContext.ContentService.Save(c1);
|
||||
count++;
|
||||
|
||||
for (int j = 0; j < 5; j++)
|
||||
{
|
||||
var c2 = MockedContent.CreateSimpleContent(contentType, Guid.NewGuid().ToString(), c1);
|
||||
ServiceContext.ContentService.Save(c2);
|
||||
count++;
|
||||
}
|
||||
}
|
||||
|
||||
var service = ServiceContext.EntityService;
|
||||
|
||||
long total;
|
||||
var entities = service.GetPagedDescendants(root.Id, UmbracoObjectTypes.Document, 0, 31, out total).ToArray();
|
||||
Assert.That(entities.Length, Is.EqualTo(31));
|
||||
Assert.That(total, Is.EqualTo(60));
|
||||
entities = service.GetPagedDescendants(root.Id, UmbracoObjectTypes.Document, 1, 31, out total).ToArray();
|
||||
Assert.That(entities.Length, Is.EqualTo(29));
|
||||
Assert.That(total, Is.EqualTo(60));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void EntityService_Can_Get_Paged_Content_Descendants_Including_Recycled()
|
||||
{
|
||||
var contentType = ServiceContext.ContentTypeService.GetContentType("umbTextpage");
|
||||
|
||||
var root = MockedContent.CreateSimpleContent(contentType);
|
||||
ServiceContext.ContentService.Save(root);
|
||||
var toDelete = new List<IContent>();
|
||||
for (int i = 0; i < 10; i++)
|
||||
{
|
||||
var c1 = MockedContent.CreateSimpleContent(contentType, Guid.NewGuid().ToString(), root);
|
||||
ServiceContext.ContentService.Save(c1);
|
||||
|
||||
if (i % 2 == 0)
|
||||
{
|
||||
toDelete.Add(c1);
|
||||
}
|
||||
|
||||
for (int j = 0; j < 5; j++)
|
||||
{
|
||||
var c2 = MockedContent.CreateSimpleContent(contentType, Guid.NewGuid().ToString(), c1);
|
||||
ServiceContext.ContentService.Save(c2);
|
||||
}
|
||||
}
|
||||
|
||||
foreach (var content in toDelete)
|
||||
{
|
||||
ServiceContext.ContentService.MoveToRecycleBin(content);
|
||||
}
|
||||
|
||||
var service = ServiceContext.EntityService;
|
||||
|
||||
long total;
|
||||
//search at root to see if it returns recycled
|
||||
var entities = service.GetPagedDescendants(-1, UmbracoObjectTypes.Document, 0, 1000, out total)
|
||||
.Select(x => x.Id)
|
||||
.ToArray();
|
||||
|
||||
foreach (var c in toDelete)
|
||||
{
|
||||
Assert.True(entities.Contains(c.Id));
|
||||
}
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void EntityService_Can_Get_Paged_Content_Descendants_Without_Recycled()
|
||||
{
|
||||
var contentType = ServiceContext.ContentTypeService.GetContentType("umbTextpage");
|
||||
|
||||
var root = MockedContent.CreateSimpleContent(contentType);
|
||||
ServiceContext.ContentService.Save(root);
|
||||
var toDelete = new List<IContent>();
|
||||
for (int i = 0; i < 10; i++)
|
||||
{
|
||||
var c1 = MockedContent.CreateSimpleContent(contentType, Guid.NewGuid().ToString(), root);
|
||||
ServiceContext.ContentService.Save(c1);
|
||||
|
||||
if (i % 2 == 0)
|
||||
{
|
||||
toDelete.Add(c1);
|
||||
}
|
||||
|
||||
for (int j = 0; j < 5; j++)
|
||||
{
|
||||
var c2 = MockedContent.CreateSimpleContent(contentType, Guid.NewGuid().ToString(), c1);
|
||||
ServiceContext.ContentService.Save(c2);
|
||||
}
|
||||
}
|
||||
|
||||
foreach (var content in toDelete)
|
||||
{
|
||||
ServiceContext.ContentService.MoveToRecycleBin(content);
|
||||
}
|
||||
|
||||
var service = ServiceContext.EntityService;
|
||||
|
||||
long total;
|
||||
//search at root to see if it returns recycled
|
||||
var entities = service.GetPagedDescendantsFromRoot(UmbracoObjectTypes.Document, 0, 1000, out total, includeTrashed:false)
|
||||
.Select(x => x.Id)
|
||||
.ToArray();
|
||||
|
||||
foreach (var c in toDelete)
|
||||
{
|
||||
Assert.IsFalse(entities.Contains(c.Id));
|
||||
}
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void EntityService_Can_Get_Paged_Content_Descendants_With_Search()
|
||||
{
|
||||
var contentType = ServiceContext.ContentTypeService.GetContentType("umbTextpage");
|
||||
|
||||
var root = MockedContent.CreateSimpleContent(contentType);
|
||||
ServiceContext.ContentService.Save(root);
|
||||
|
||||
for (int i = 0; i < 10; i++)
|
||||
{
|
||||
var c1 = MockedContent.CreateSimpleContent(contentType, "ssss" + Guid.NewGuid(), root);
|
||||
ServiceContext.ContentService.Save(c1);
|
||||
|
||||
for (int j = 0; j < 5; j++)
|
||||
{
|
||||
var c2 = MockedContent.CreateSimpleContent(contentType, "tttt" + Guid.NewGuid(), c1);
|
||||
ServiceContext.ContentService.Save(c2);
|
||||
}
|
||||
}
|
||||
|
||||
var service = ServiceContext.EntityService;
|
||||
|
||||
long total;
|
||||
var entities = service.GetPagedDescendants(root.Id, UmbracoObjectTypes.Document, 0, 10, out total, filter: "ssss").ToArray();
|
||||
Assert.That(entities.Length, Is.EqualTo(10));
|
||||
Assert.That(total, Is.EqualTo(10));
|
||||
entities = service.GetPagedDescendants(root.Id, UmbracoObjectTypes.Document, 0, 50, out total, filter: "tttt").ToArray();
|
||||
Assert.That(entities.Length, Is.EqualTo(50));
|
||||
Assert.That(total, Is.EqualTo(50));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void EntityService_Can_Get_Paged_Media_Children()
|
||||
{
|
||||
var folderType = ServiceContext.ContentTypeService.GetMediaType(1031);
|
||||
var imageMediaType = ServiceContext.ContentTypeService.GetMediaType(1032);
|
||||
|
||||
var root = MockedMedia.CreateMediaFolder(folderType, -1);
|
||||
ServiceContext.MediaService.Save(root);
|
||||
for (int i = 0; i < 10; i++)
|
||||
{
|
||||
var c1 = MockedMedia.CreateMediaImage(imageMediaType, root.Id);
|
||||
ServiceContext.MediaService.Save(c1);
|
||||
}
|
||||
|
||||
var service = ServiceContext.EntityService;
|
||||
|
||||
long total;
|
||||
var entities = service.GetPagedChildren(root.Id, UmbracoObjectTypes.Media, 0, 6, out total).ToArray();
|
||||
Assert.That(entities.Length, Is.EqualTo(6));
|
||||
Assert.That(total, Is.EqualTo(10));
|
||||
entities = service.GetPagedChildren(root.Id, UmbracoObjectTypes.Media, 1, 6, out total).ToArray();
|
||||
Assert.That(entities.Length, Is.EqualTo(4));
|
||||
Assert.That(total, Is.EqualTo(10));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void EntityService_Can_Get_Paged_Media_Descendants()
|
||||
{
|
||||
var folderType = ServiceContext.ContentTypeService.GetMediaType(1031);
|
||||
var imageMediaType = ServiceContext.ContentTypeService.GetMediaType(1032);
|
||||
|
||||
var root = MockedMedia.CreateMediaFolder(folderType, -1);
|
||||
ServiceContext.MediaService.Save(root);
|
||||
var count = 0;
|
||||
for (int i = 0; i < 10; i++)
|
||||
{
|
||||
var c1 = MockedMedia.CreateMediaImage(imageMediaType, root.Id);
|
||||
ServiceContext.MediaService.Save(c1);
|
||||
count++;
|
||||
|
||||
for (int j = 0; j < 5; j++)
|
||||
{
|
||||
var c2 = MockedMedia.CreateMediaImage(imageMediaType, c1.Id);
|
||||
ServiceContext.MediaService.Save(c2);
|
||||
count++;
|
||||
}
|
||||
}
|
||||
|
||||
var service = ServiceContext.EntityService;
|
||||
|
||||
long total;
|
||||
var entities = service.GetPagedDescendants(root.Id, UmbracoObjectTypes.Media, 0, 31, out total).ToArray();
|
||||
Assert.That(entities.Length, Is.EqualTo(31));
|
||||
Assert.That(total, Is.EqualTo(60));
|
||||
entities = service.GetPagedDescendants(root.Id, UmbracoObjectTypes.Media, 1, 31, out total).ToArray();
|
||||
Assert.That(entities.Length, Is.EqualTo(29));
|
||||
Assert.That(total, Is.EqualTo(60));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void EntityService_Can_Get_Paged_Media_Descendants_Including_Recycled()
|
||||
{
|
||||
var folderType = ServiceContext.ContentTypeService.GetMediaType(1031);
|
||||
var imageMediaType = ServiceContext.ContentTypeService.GetMediaType(1032);
|
||||
|
||||
var root = MockedMedia.CreateMediaFolder(folderType, -1);
|
||||
ServiceContext.MediaService.Save(root);
|
||||
var toDelete = new List<IMedia>();
|
||||
for (int i = 0; i < 10; i++)
|
||||
{
|
||||
var c1 = MockedMedia.CreateMediaImage(imageMediaType, root.Id);
|
||||
ServiceContext.MediaService.Save(c1);
|
||||
|
||||
if (i % 2 == 0)
|
||||
{
|
||||
toDelete.Add(c1);
|
||||
}
|
||||
|
||||
for (int j = 0; j < 5; j++)
|
||||
{
|
||||
var c2 = MockedMedia.CreateMediaImage(imageMediaType, c1.Id);
|
||||
ServiceContext.MediaService.Save(c2);
|
||||
}
|
||||
}
|
||||
|
||||
foreach (var content in toDelete)
|
||||
{
|
||||
ServiceContext.MediaService.MoveToRecycleBin(content);
|
||||
}
|
||||
|
||||
var service = ServiceContext.EntityService;
|
||||
|
||||
long total;
|
||||
//search at root to see if it returns recycled
|
||||
var entities = service.GetPagedDescendants(-1, UmbracoObjectTypes.Media, 0, 1000, out total)
|
||||
.Select(x => x.Id)
|
||||
.ToArray();
|
||||
|
||||
foreach (var media in toDelete)
|
||||
{
|
||||
Assert.IsTrue(entities.Contains(media.Id));
|
||||
}
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void EntityService_Can_Get_Paged_Media_Descendants_Without_Recycled()
|
||||
{
|
||||
var folderType = ServiceContext.ContentTypeService.GetMediaType(1031);
|
||||
var imageMediaType = ServiceContext.ContentTypeService.GetMediaType(1032);
|
||||
|
||||
var root = MockedMedia.CreateMediaFolder(folderType, -1);
|
||||
ServiceContext.MediaService.Save(root);
|
||||
var toDelete = new List<IMedia>();
|
||||
for (int i = 0; i < 10; i++)
|
||||
{
|
||||
var c1 = MockedMedia.CreateMediaImage(imageMediaType, root.Id);
|
||||
ServiceContext.MediaService.Save(c1);
|
||||
|
||||
if (i % 2 == 0)
|
||||
{
|
||||
toDelete.Add(c1);
|
||||
}
|
||||
|
||||
for (int j = 0; j < 5; j++)
|
||||
{
|
||||
var c2 = MockedMedia.CreateMediaImage(imageMediaType, c1.Id);
|
||||
ServiceContext.MediaService.Save(c2);
|
||||
}
|
||||
}
|
||||
|
||||
foreach (var content in toDelete)
|
||||
{
|
||||
ServiceContext.MediaService.MoveToRecycleBin(content);
|
||||
}
|
||||
|
||||
var service = ServiceContext.EntityService;
|
||||
|
||||
long total;
|
||||
//search at root to see if it returns recycled
|
||||
var entities = service.GetPagedDescendantsFromRoot(UmbracoObjectTypes.Media, 0, 1000, out total, includeTrashed:false)
|
||||
.Select(x => x.Id)
|
||||
.ToArray();
|
||||
|
||||
foreach (var media in toDelete)
|
||||
{
|
||||
Assert.IsFalse(entities.Contains(media.Id));
|
||||
}
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void EntityService_Can_Get_Paged_Media_Descendants_With_Search()
|
||||
{
|
||||
var folderType = ServiceContext.ContentTypeService.GetMediaType(1031);
|
||||
var imageMediaType = ServiceContext.ContentTypeService.GetMediaType(1032);
|
||||
|
||||
var root = MockedMedia.CreateMediaFolder(folderType, -1);
|
||||
ServiceContext.MediaService.Save(root);
|
||||
|
||||
for (int i = 0; i < 10; i++)
|
||||
{
|
||||
var c1 = MockedMedia.CreateMediaImage(imageMediaType, root.Id);
|
||||
c1.Name = "ssss" + Guid.NewGuid();
|
||||
ServiceContext.MediaService.Save(c1);
|
||||
|
||||
for (int j = 0; j < 5; j++)
|
||||
{
|
||||
var c2 = MockedMedia.CreateMediaImage(imageMediaType, c1.Id);
|
||||
c2.Name = "tttt" + Guid.NewGuid();
|
||||
ServiceContext.MediaService.Save(c2);
|
||||
}
|
||||
}
|
||||
|
||||
var service = ServiceContext.EntityService;
|
||||
|
||||
long total;
|
||||
var entities = service.GetPagedDescendants(root.Id, UmbracoObjectTypes.Media, 0, 10, out total, filter: "ssss").ToArray();
|
||||
Assert.That(entities.Length, Is.EqualTo(10));
|
||||
Assert.That(total, Is.EqualTo(10));
|
||||
entities = service.GetPagedDescendants(root.Id, UmbracoObjectTypes.Media, 0, 50, out total, filter: "tttt").ToArray();
|
||||
Assert.That(entities.Length, Is.EqualTo(50));
|
||||
Assert.That(total, Is.EqualTo(50));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void EntityService_Can_Find_All_Content_By_UmbracoObjectTypes()
|
||||
{
|
||||
|
||||
@@ -358,9 +358,9 @@ namespace Umbraco.Tests.TestHelpers.Entities
|
||||
contentCollection.Add(new PropertyType(Constants.PropertyEditors.DateAlias, DataTypeDatabaseType.Date) { Alias = "date", Name = "Date", Mandatory = false, SortOrder = 13, DataTypeDefinitionId = -41 });
|
||||
contentCollection.Add(new PropertyType(Constants.PropertyEditors.DropDownListAlias, DataTypeDatabaseType.Integer) { Alias = "ddl", Name = "Dropdown List", Mandatory = false, SortOrder = 14, DataTypeDefinitionId = -42 });
|
||||
contentCollection.Add(new PropertyType(Constants.PropertyEditors.CheckBoxListAlias, DataTypeDatabaseType.Nvarchar) { Alias = "chklist", Name = "Checkbox List", Mandatory = false, SortOrder = 15, DataTypeDefinitionId = -43 });
|
||||
contentCollection.Add(new PropertyType(Constants.PropertyEditors.ContentPickerAlias, DataTypeDatabaseType.Integer) { Alias = "contentPicker", Name = "Content Picker", Mandatory = false, SortOrder = 16, DataTypeDefinitionId = 1034 });
|
||||
contentCollection.Add(new PropertyType(Constants.PropertyEditors.MediaPickerAlias, DataTypeDatabaseType.Integer) { Alias = "mediaPicker", Name = "Media Picker", Mandatory = false, SortOrder = 17, DataTypeDefinitionId = 1035 });
|
||||
contentCollection.Add(new PropertyType(Constants.PropertyEditors.MemberPickerAlias, DataTypeDatabaseType.Integer) { Alias = "memberPicker", Name = "Member Picker", Mandatory = false, SortOrder = 18, DataTypeDefinitionId = 1036 });
|
||||
contentCollection.Add(new PropertyType(Constants.PropertyEditors.ContentPicker2Alias, DataTypeDatabaseType.Integer) { Alias = "contentPicker", Name = "Content Picker", Mandatory = false, SortOrder = 16, DataTypeDefinitionId = 1046 });
|
||||
contentCollection.Add(new PropertyType(Constants.PropertyEditors.MediaPicker2Alias, DataTypeDatabaseType.Integer) { Alias = "mediaPicker", Name = "Media Picker", Mandatory = false, SortOrder = 17, DataTypeDefinitionId = 1048 });
|
||||
contentCollection.Add(new PropertyType(Constants.PropertyEditors.MemberPicker2Alias, DataTypeDatabaseType.Integer) { Alias = "memberPicker", Name = "Member Picker", Mandatory = false, SortOrder = 18, DataTypeDefinitionId = 1047 });
|
||||
contentCollection.Add(new PropertyType(Constants.PropertyEditors.RelatedLinksAlias, DataTypeDatabaseType.Ntext) { Alias = "relatedLinks", Name = "Related Links", Mandatory = false, SortOrder = 21, DataTypeDefinitionId = 1040 });
|
||||
contentCollection.Add(new PropertyType(Constants.PropertyEditors.TagsAlias, DataTypeDatabaseType.Ntext) { Alias = "tags", Name = "Tags", Mandatory = false, SortOrder = 22, DataTypeDefinitionId = 1041 });
|
||||
|
||||
|
||||
@@ -13,41 +13,41 @@ namespace Umbraco.Tests
|
||||
[Test]
|
||||
public void StringEntityCtorTest()
|
||||
{
|
||||
var udi = new StringUdi(Constants.DeployEntityType.AnyString, "test-id");
|
||||
Assert.AreEqual(Constants.DeployEntityType.AnyString, udi.EntityType);
|
||||
var udi = new StringUdi(Constants.UdiEntityType.AnyString, "test-id");
|
||||
Assert.AreEqual(Constants.UdiEntityType.AnyString, udi.EntityType);
|
||||
Assert.AreEqual("test-id", udi.Id);
|
||||
Assert.AreEqual("umb://" + Constants.DeployEntityType.AnyString + "/test-id", udi.ToString());
|
||||
Assert.AreEqual("umb://" + Constants.UdiEntityType.AnyString + "/test-id", udi.ToString());
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void StringEntityParseTest()
|
||||
{
|
||||
var udi = Udi.Parse("umb://" + Constants.DeployEntityType.AnyString + "/test-id");
|
||||
Assert.AreEqual(Constants.DeployEntityType.AnyString, udi.EntityType);
|
||||
var udi = Udi.Parse("umb://" + Constants.UdiEntityType.AnyString + "/test-id");
|
||||
Assert.AreEqual(Constants.UdiEntityType.AnyString, udi.EntityType);
|
||||
Assert.IsInstanceOf<StringUdi>(udi);
|
||||
var stringEntityId = udi as StringUdi;
|
||||
Assert.IsNotNull(stringEntityId);
|
||||
Assert.AreEqual("test-id", stringEntityId.Id);
|
||||
Assert.AreEqual("umb://" + Constants.DeployEntityType.AnyString + "/test-id", udi.ToString());
|
||||
Assert.AreEqual("umb://" + Constants.UdiEntityType.AnyString + "/test-id", udi.ToString());
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void GuidEntityCtorTest()
|
||||
{
|
||||
var guid = Guid.NewGuid();
|
||||
var udi = new GuidUdi(Constants.DeployEntityType.AnyGuid, guid);
|
||||
Assert.AreEqual(Constants.DeployEntityType.AnyGuid, udi.EntityType);
|
||||
var udi = new GuidUdi(Constants.UdiEntityType.AnyGuid, guid);
|
||||
Assert.AreEqual(Constants.UdiEntityType.AnyGuid, udi.EntityType);
|
||||
Assert.AreEqual(guid, udi.Guid);
|
||||
Assert.AreEqual("umb://" + Constants.DeployEntityType.AnyGuid + "/" + guid.ToString("N"), udi.ToString());
|
||||
Assert.AreEqual("umb://" + Constants.UdiEntityType.AnyGuid + "/" + guid.ToString("N"), udi.ToString());
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void GuidEntityParseTest()
|
||||
{
|
||||
var guid = Guid.NewGuid();
|
||||
var s = "umb://" + Constants.DeployEntityType.AnyGuid + "/" + guid.ToString("N");
|
||||
var s = "umb://" + Constants.UdiEntityType.AnyGuid + "/" + guid.ToString("N");
|
||||
var udi = Udi.Parse(s);
|
||||
Assert.AreEqual(Constants.DeployEntityType.AnyGuid, udi.EntityType);
|
||||
Assert.AreEqual(Constants.UdiEntityType.AnyGuid, udi.EntityType);
|
||||
Assert.IsInstanceOf<GuidUdi>(udi);
|
||||
var gudi = udi as GuidUdi;
|
||||
Assert.IsNotNull(gudi);
|
||||
@@ -82,9 +82,9 @@ namespace Umbraco.Tests
|
||||
var guid1 = Guid.NewGuid();
|
||||
var entities = new[]
|
||||
{
|
||||
new GuidUdi(Constants.DeployEntityType.AnyGuid, guid1),
|
||||
new GuidUdi(Constants.DeployEntityType.AnyGuid, guid1),
|
||||
new GuidUdi(Constants.DeployEntityType.AnyGuid, guid1),
|
||||
new GuidUdi(Constants.UdiEntityType.AnyGuid, guid1),
|
||||
new GuidUdi(Constants.UdiEntityType.AnyGuid, guid1),
|
||||
new GuidUdi(Constants.UdiEntityType.AnyGuid, guid1),
|
||||
};
|
||||
Assert.AreEqual(1, entities.Distinct().Count());
|
||||
}
|
||||
@@ -93,12 +93,12 @@ namespace Umbraco.Tests
|
||||
public void CreateTest()
|
||||
{
|
||||
var guid = Guid.NewGuid();
|
||||
var udi = Udi.Create(Constants.DeployEntityType.AnyGuid, guid);
|
||||
Assert.AreEqual(Constants.DeployEntityType.AnyGuid, udi.EntityType);
|
||||
var udi = Udi.Create(Constants.UdiEntityType.AnyGuid, guid);
|
||||
Assert.AreEqual(Constants.UdiEntityType.AnyGuid, udi.EntityType);
|
||||
Assert.AreEqual(guid, ((GuidUdi)udi).Guid);
|
||||
|
||||
Assert.Throws<InvalidOperationException>(() => Udi.Create(Constants.DeployEntityType.AnyString, guid));
|
||||
Assert.Throws<InvalidOperationException>(() => Udi.Create(Constants.DeployEntityType.AnyGuid, "foo"));
|
||||
Assert.Throws<InvalidOperationException>(() => Udi.Create(Constants.UdiEntityType.AnyString, guid));
|
||||
Assert.Throws<InvalidOperationException>(() => Udi.Create(Constants.UdiEntityType.AnyGuid, "foo"));
|
||||
Assert.Throws<ArgumentException>(() => Udi.Create("barf", "foo"));
|
||||
}
|
||||
|
||||
@@ -106,13 +106,13 @@ namespace Umbraco.Tests
|
||||
public void RangeTest()
|
||||
{
|
||||
// can parse open string udi
|
||||
var stringUdiString = "umb://" + Constants.DeployEntityType.AnyString;
|
||||
var stringUdiString = "umb://" + Constants.UdiEntityType.AnyString;
|
||||
Udi stringUdi;
|
||||
Assert.IsTrue(Udi.TryParse(stringUdiString, out stringUdi));
|
||||
Assert.AreEqual(string.Empty, ((StringUdi)stringUdi).Id);
|
||||
|
||||
// can parse open guid udi
|
||||
var guidUdiString = "umb://" + Constants.DeployEntityType.AnyGuid;
|
||||
var guidUdiString = "umb://" + Constants.UdiEntityType.AnyGuid;
|
||||
Udi guidUdi;
|
||||
Assert.IsTrue(Udi.TryParse(guidUdiString, out guidUdi));
|
||||
Assert.AreEqual(Guid.Empty, ((GuidUdi)guidUdi).Guid);
|
||||
@@ -134,12 +134,12 @@ namespace Umbraco.Tests
|
||||
|
||||
|
||||
var guid = Guid.NewGuid();
|
||||
var udi = new GuidUdi(Constants.DeployEntityType.AnyGuid, guid);
|
||||
var udi = new GuidUdi(Constants.UdiEntityType.AnyGuid, guid);
|
||||
var json = JsonConvert.SerializeObject(udi, settings);
|
||||
Assert.AreEqual(string.Format("\"umb://any-guid/{0:N}\"", guid), json);
|
||||
|
||||
var dudi = JsonConvert.DeserializeObject<Udi>(json, settings);
|
||||
Assert.AreEqual(Constants.DeployEntityType.AnyGuid, dudi.EntityType);
|
||||
Assert.AreEqual(Constants.UdiEntityType.AnyGuid, dudi.EntityType);
|
||||
Assert.AreEqual(guid, ((GuidUdi)dudi).Guid);
|
||||
|
||||
var range = new UdiRange(udi, Constants.DeploySelector.ChildrenOfThis);
|
||||
|
||||
+11
-14
@@ -1,7 +1,7 @@
|
||||
(function () {
|
||||
'use strict';
|
||||
|
||||
function MiniListViewDirective(contentResource, memberResource, mediaResource) {
|
||||
function MiniListViewDirective(entityResource) {
|
||||
|
||||
function link(scope, el, attr, ctrl) {
|
||||
|
||||
@@ -52,22 +52,19 @@
|
||||
|
||||
// start loading animation list view
|
||||
miniListView.loading = true;
|
||||
|
||||
// setup the correct resource depending on section
|
||||
var resource = "";
|
||||
|
||||
if (scope.entityType === "Member") {
|
||||
resource = memberResource.getPagedResults;
|
||||
} else if (scope.entityType === "Media") {
|
||||
resource = mediaResource.getChildren;
|
||||
} else {
|
||||
resource = contentResource.getChildren;
|
||||
}
|
||||
|
||||
resource(miniListView.node.id, miniListView.pagination)
|
||||
|
||||
entityResource.getPagedChildren(miniListView.node.id, scope.entityType, miniListView.pagination)
|
||||
.then(function (data) {
|
||||
// update children
|
||||
miniListView.children = data.items;
|
||||
_.each(miniListView.children, function(c) {
|
||||
if (c.metaData) {
|
||||
c.hasChildren = c.metaData.HasChildren;
|
||||
if(scope.entityType === "Document") {
|
||||
c.published = c.metaData.IsPublished;
|
||||
}
|
||||
}
|
||||
});
|
||||
// update pagination
|
||||
miniListView.pagination.totalItems = data.totalItems;
|
||||
miniListView.pagination.totalPages = data.totalPages;
|
||||
|
||||
@@ -477,20 +477,20 @@ function contentResource($q, $http, umbDataFormatter, umbRequestHelper) {
|
||||
}
|
||||
|
||||
return umbRequestHelper.resourcePromise(
|
||||
$http.get(
|
||||
umbRequestHelper.getApiUrl(
|
||||
"contentApiBaseUrl",
|
||||
"GetChildren",
|
||||
[
|
||||
{ id: parentId },
|
||||
{ pageNumber: options.pageNumber },
|
||||
{ pageSize: options.pageSize },
|
||||
{ orderBy: options.orderBy },
|
||||
{ orderDirection: options.orderDirection },
|
||||
{ orderBySystemField: toBool(options.orderBySystemField) },
|
||||
{ filter: options.filter }
|
||||
])),
|
||||
'Failed to retrieve children for content item ' + parentId);
|
||||
$http.get(
|
||||
umbRequestHelper.getApiUrl(
|
||||
"contentApiBaseUrl",
|
||||
"GetChildren",
|
||||
{
|
||||
id: parentId,
|
||||
pageNumber: options.pageNumber,
|
||||
pageSize: options.pageSize,
|
||||
orderBy: options.orderBy,
|
||||
orderDirection: options.orderDirection,
|
||||
orderBySystemField: toBool(options.orderBySystemField),
|
||||
filter: options.filter
|
||||
})),
|
||||
'Failed to retrieve children for content item ' + parentId);
|
||||
},
|
||||
|
||||
/**
|
||||
|
||||
@@ -38,6 +38,10 @@ function entityResource($q, $http, umbRequestHelper) {
|
||||
|
||||
getSafeAlias: function (value, camelCase) {
|
||||
|
||||
if (!value) {
|
||||
return "";
|
||||
}
|
||||
|
||||
return umbRequestHelper.resourcePromise(
|
||||
$http.get(
|
||||
umbRequestHelper.getApiUrl(
|
||||
@@ -68,6 +72,11 @@ function entityResource($q, $http, umbRequestHelper) {
|
||||
*
|
||||
*/
|
||||
getPath: function (id, type) {
|
||||
|
||||
if (id === -1 || id === "-1") {
|
||||
return "-1";
|
||||
}
|
||||
|
||||
return umbRequestHelper.resourcePromise(
|
||||
$http.get(
|
||||
umbRequestHelper.getApiUrl(
|
||||
@@ -98,7 +107,12 @@ function entityResource($q, $http, umbRequestHelper) {
|
||||
* @returns {Promise} resourcePromise object containing the url.
|
||||
*
|
||||
*/
|
||||
getUrl: function(id, type) {
|
||||
getUrl: function (id, type) {
|
||||
|
||||
if (id === -1 || id === "-1") {
|
||||
return "";
|
||||
}
|
||||
|
||||
return umbRequestHelper.resourcePromise(
|
||||
$http.get(
|
||||
umbRequestHelper.getApiUrl(
|
||||
@@ -131,7 +145,12 @@ function entityResource($q, $http, umbRequestHelper) {
|
||||
* @returns {Promise} resourcePromise object containing the entity.
|
||||
*
|
||||
*/
|
||||
getById: function (id, type) {
|
||||
getById: function (id, type) {
|
||||
|
||||
if (id === -1 || id === "-1") {
|
||||
return null;
|
||||
}
|
||||
|
||||
return umbRequestHelper.resourcePromise(
|
||||
$http.get(
|
||||
umbRequestHelper.getApiUrl(
|
||||
@@ -166,24 +185,17 @@ function entityResource($q, $http, umbRequestHelper) {
|
||||
*/
|
||||
getByIds: function (ids, type) {
|
||||
|
||||
var query = "";
|
||||
_.each(ids, function(item) {
|
||||
query += "ids=" + item + "&";
|
||||
});
|
||||
|
||||
// if ids array is empty we need a empty variable in the querystring otherwise the service returns a error
|
||||
if (ids.length === 0) {
|
||||
query += "ids=&";
|
||||
}
|
||||
|
||||
query += "type=" + type;
|
||||
var query = "type=" + type;
|
||||
|
||||
return umbRequestHelper.resourcePromise(
|
||||
$http.get(
|
||||
$http.post(
|
||||
umbRequestHelper.getApiUrl(
|
||||
"entityApiBaseUrl",
|
||||
"GetByIds",
|
||||
query)),
|
||||
query),
|
||||
{
|
||||
ids: ids
|
||||
}),
|
||||
'Failed to retrieve entity data for ids ' + ids);
|
||||
},
|
||||
|
||||
@@ -292,18 +304,19 @@ function entityResource($q, $http, umbRequestHelper) {
|
||||
|
||||
/**
|
||||
* @ngdoc method
|
||||
* @name umbraco.resources.entityResource#getAncestors
|
||||
* @name umbraco.resources.entityResource#getChildren
|
||||
* @methodOf umbraco.resources.entityResource
|
||||
*
|
||||
* @description
|
||||
* Gets children entities for a given item
|
||||
*
|
||||
*
|
||||
* @param {Int} parentid id of content item to return children of
|
||||
* @param {string} type Object type name
|
||||
* @returns {Promise} resourcePromise object containing the entity.
|
||||
*
|
||||
*/
|
||||
getChildren: function (id, type) {
|
||||
|
||||
return umbRequestHelper.resourcePromise(
|
||||
$http.get(
|
||||
umbRequestHelper.getApiUrl(
|
||||
@@ -312,6 +325,146 @@ function entityResource($q, $http, umbRequestHelper) {
|
||||
[{ id: id }, { type: type }])),
|
||||
'Failed to retrieve child data for id ' + id);
|
||||
},
|
||||
|
||||
/**
|
||||
* @ngdoc method
|
||||
* @name umbraco.resources.entityResource#getPagedChildren
|
||||
* @methodOf umbraco.resources.entityResource
|
||||
*
|
||||
* @description
|
||||
* Gets paged children of a content item with a given id
|
||||
*
|
||||
* ##usage
|
||||
* <pre>
|
||||
* entityResource.getPagedChildren(1234, "Content", {pageSize: 10, pageNumber: 2})
|
||||
* .then(function(contentArray) {
|
||||
* var children = contentArray;
|
||||
* alert('they are here!');
|
||||
* });
|
||||
* </pre>
|
||||
*
|
||||
* @param {Int} parentid id of content item to return children of
|
||||
* @param {string} type Object type name
|
||||
* @param {Object} options optional options object
|
||||
* @param {Int} options.pageSize if paging data, number of nodes per page, default = 1
|
||||
* @param {Int} options.pageNumber if paging data, current page index, default = 100
|
||||
* @param {String} options.filter if provided, query will only return those with names matching the filter
|
||||
* @param {String} options.orderDirection can be `Ascending` or `Descending` - Default: `Ascending`
|
||||
* @param {String} options.orderBy property to order items by, default: `SortOrder`
|
||||
* @returns {Promise} resourcePromise object containing an array of content items.
|
||||
*
|
||||
*/
|
||||
getPagedChildren: function (parentId, type, options) {
|
||||
|
||||
var defaults = {
|
||||
pageSize: 1,
|
||||
pageNumber: 100,
|
||||
filter: '',
|
||||
orderDirection: "Ascending",
|
||||
orderBy: "SortOrder"
|
||||
};
|
||||
if (options === undefined) {
|
||||
options = {};
|
||||
}
|
||||
//overwrite the defaults if there are any specified
|
||||
angular.extend(defaults, options);
|
||||
//now copy back to the options we will use
|
||||
options = defaults;
|
||||
//change asc/desct
|
||||
if (options.orderDirection === "asc") {
|
||||
options.orderDirection = "Ascending";
|
||||
}
|
||||
else if (options.orderDirection === "desc") {
|
||||
options.orderDirection = "Descending";
|
||||
}
|
||||
|
||||
return umbRequestHelper.resourcePromise(
|
||||
$http.get(
|
||||
umbRequestHelper.getApiUrl(
|
||||
"entityApiBaseUrl",
|
||||
"GetPagedChildren",
|
||||
{
|
||||
id: parentId,
|
||||
type: type,
|
||||
pageNumber: options.pageNumber,
|
||||
pageSize: options.pageSize,
|
||||
orderBy: options.orderBy,
|
||||
orderDirection: options.orderDirection,
|
||||
filter: encodeURIComponent(options.filter)
|
||||
}
|
||||
)),
|
||||
'Failed to retrieve child data for id ' + parentId);
|
||||
},
|
||||
|
||||
/**
|
||||
* @ngdoc method
|
||||
* @name umbraco.resources.entityResource#getPagedDescendants
|
||||
* @methodOf umbraco.resources.entityResource
|
||||
*
|
||||
* @description
|
||||
* Gets paged descendants of a content item with a given id
|
||||
*
|
||||
* ##usage
|
||||
* <pre>
|
||||
* entityResource.getPagedDescendants(1234, "Content", {pageSize: 10, pageNumber: 2})
|
||||
* .then(function(contentArray) {
|
||||
* var children = contentArray;
|
||||
* alert('they are here!');
|
||||
* });
|
||||
* </pre>
|
||||
*
|
||||
* @param {Int} parentid id of content item to return descendants of
|
||||
* @param {string} type Object type name
|
||||
* @param {Object} options optional options object
|
||||
* @param {Int} options.pageSize if paging data, number of nodes per page, default = 1
|
||||
* @param {Int} options.pageNumber if paging data, current page index, default = 100
|
||||
* @param {String} options.filter if provided, query will only return those with names matching the filter
|
||||
* @param {String} options.orderDirection can be `Ascending` or `Descending` - Default: `Ascending`
|
||||
* @param {String} options.orderBy property to order items by, default: `SortOrder`
|
||||
* @returns {Promise} resourcePromise object containing an array of content items.
|
||||
*
|
||||
*/
|
||||
getPagedDescendants: function (parentId, type, options) {
|
||||
|
||||
var defaults = {
|
||||
pageSize: 1,
|
||||
pageNumber: 100,
|
||||
filter: '',
|
||||
orderDirection: "Ascending",
|
||||
orderBy: "SortOrder"
|
||||
};
|
||||
if (options === undefined) {
|
||||
options = {};
|
||||
}
|
||||
//overwrite the defaults if there are any specified
|
||||
angular.extend(defaults, options);
|
||||
//now copy back to the options we will use
|
||||
options = defaults;
|
||||
//change asc/desct
|
||||
if (options.orderDirection === "asc") {
|
||||
options.orderDirection = "Ascending";
|
||||
}
|
||||
else if (options.orderDirection === "desc") {
|
||||
options.orderDirection = "Descending";
|
||||
}
|
||||
|
||||
return umbRequestHelper.resourcePromise(
|
||||
$http.get(
|
||||
umbRequestHelper.getApiUrl(
|
||||
"entityApiBaseUrl",
|
||||
"GetPagedDescendants",
|
||||
{
|
||||
id: parentId,
|
||||
type: type,
|
||||
pageNumber: options.pageNumber,
|
||||
pageSize: options.pageSize,
|
||||
orderBy: options.orderBy,
|
||||
orderDirection: options.orderDirection,
|
||||
filter: encodeURIComponent(options.filter)
|
||||
}
|
||||
)),
|
||||
'Failed to retrieve child data for id ' + parentId);
|
||||
},
|
||||
|
||||
/**
|
||||
* @ngdoc method
|
||||
|
||||
@@ -482,7 +482,49 @@ function mediaResource($q, $http, umbDataFormatter, umbRequestHelper) {
|
||||
"mediaApiBaseUrl",
|
||||
"EmptyRecycleBin")),
|
||||
'Failed to empty the recycle bin');
|
||||
},
|
||||
|
||||
/**
|
||||
* @ngdoc method
|
||||
* @name umbraco.resources.mediaResource#search
|
||||
* @methodOf umbraco.resources.mediaResource
|
||||
*
|
||||
* @description
|
||||
* Empties the media recycle bin
|
||||
*
|
||||
* ##usage
|
||||
* <pre>
|
||||
* mediaResource.search("my search", 1, 100, -1)
|
||||
* .then(function(searchResult) {
|
||||
* alert('it's here!');
|
||||
* });
|
||||
* </pre>
|
||||
*
|
||||
* @param {string} query The search query
|
||||
* @param {int} pageNumber The page number
|
||||
* @param {int} pageSize The number of media items on a page
|
||||
* @param {int} searchFrom Id to search from
|
||||
* @returns {Promise} resourcePromise object.
|
||||
*
|
||||
*/
|
||||
search: function (query, pageNumber, pageSize, searchFrom) {
|
||||
|
||||
var args = [
|
||||
{ "query": query },
|
||||
{ "pageNumber": pageNumber },
|
||||
{ "pageSize": pageSize },
|
||||
{ "searchFrom": searchFrom }
|
||||
];
|
||||
|
||||
return umbRequestHelper.resourcePromise(
|
||||
$http.get(
|
||||
umbRequestHelper.getApiUrl(
|
||||
"mediaApiBaseUrl",
|
||||
"Search",
|
||||
args)),
|
||||
'Failed to retrieve media items for search: ' + query);
|
||||
}
|
||||
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -26,10 +26,35 @@ app.run(['userService', '$log', '$rootScope', '$location', 'navigationService',
|
||||
/** execute code on each successful route */
|
||||
$rootScope.$on('$routeChangeSuccess', function(event, current, previous) {
|
||||
|
||||
if(current.params.section){
|
||||
$rootScope.locationTitle = current.params.section + " - " + $location.$$host;
|
||||
var deployConfig = Umbraco.Sys.ServerVariables.deploy;
|
||||
var deployEnv, deployEnvTitle;
|
||||
if (deployConfig) {
|
||||
deployEnv = Umbraco.Sys.ServerVariables.deploy.CurrentWorkspace;
|
||||
deployEnvTitle = "(" + deployEnv + ") ";
|
||||
}
|
||||
|
||||
if(current.params.section) {
|
||||
|
||||
//Uppercase the current section, content, media, settings, developer, forms
|
||||
var currentSection = current.params.section.charAt(0).toUpperCase() + current.params.section.slice(1);
|
||||
|
||||
var baseTitle = currentSection + " - " + $location.$$host;
|
||||
|
||||
//Check deploy for Global Umbraco.Sys obj workspace
|
||||
if(deployEnv){
|
||||
$rootScope.locationTitle = deployEnvTitle + baseTitle;
|
||||
}
|
||||
else {
|
||||
$rootScope.locationTitle = baseTitle;
|
||||
}
|
||||
|
||||
}
|
||||
else {
|
||||
|
||||
if(deployEnv) {
|
||||
$rootScope.locationTitle = deployEnvTitle + "Umbraco - " + $location.$$host;
|
||||
}
|
||||
|
||||
$rootScope.locationTitle = "Umbraco - " + $location.$$host;
|
||||
}
|
||||
|
||||
|
||||
@@ -288,6 +288,10 @@ input.umb-table__input {
|
||||
color: @black;
|
||||
}
|
||||
|
||||
.umb-table__row-expand--hidden {
|
||||
visibility: hidden;
|
||||
}
|
||||
|
||||
.umb-table--condensed {
|
||||
|
||||
.umb-table-cell:first-of-type:not(.not-fixed) {
|
||||
|
||||
@@ -156,6 +156,11 @@ h5.-black {
|
||||
margin-left: 0;
|
||||
}
|
||||
|
||||
/* CONTROL VALIDATION */
|
||||
.umb-control-required {
|
||||
color: @controlRequiredColor;
|
||||
}
|
||||
|
||||
.controls-row {
|
||||
padding-bottom: 5px;
|
||||
margin-left: 240px;
|
||||
|
||||
@@ -137,6 +137,7 @@
|
||||
@inputDisabledBackground: @grayLighter;
|
||||
@formActionsBackground: #f5f5f5;
|
||||
@inputHeight: @baseLineHeight + 10px; // base line-height + 8px vertical padding + 2px top/bottom border
|
||||
@controlRequiredColor: #ee5f5b;
|
||||
|
||||
|
||||
// Tabs
|
||||
|
||||
+111
-27
@@ -33,6 +33,14 @@ angular.module("umbraco")
|
||||
$scope.acceptedMediatypes = types;
|
||||
});
|
||||
|
||||
$scope.searchOptions = {
|
||||
pageNumber: 1,
|
||||
pageSize: 100,
|
||||
totalItems: 0,
|
||||
totalPages: 0,
|
||||
filter: '',
|
||||
};
|
||||
|
||||
//preload selected item
|
||||
$scope.target = undefined;
|
||||
if (dialogOptions.currentTarget) {
|
||||
@@ -106,35 +114,9 @@ angular.module("umbraco")
|
||||
$scope.path = [];
|
||||
}
|
||||
|
||||
//mediaResource.rootMedia()
|
||||
mediaResource.getChildren(folder.id)
|
||||
.then(function(data) {
|
||||
$scope.searchTerm = "";
|
||||
$scope.images = data.items ? data.items : [];
|
||||
|
||||
// set already selected images to selected
|
||||
for (var folderImageIndex = 0; folderImageIndex < $scope.images.length; folderImageIndex++) {
|
||||
var folderImage = $scope.images[folderImageIndex];
|
||||
var imageIsSelected = false;
|
||||
|
||||
for (var selectedImageIndex = 0;
|
||||
selectedImageIndex < $scope.model.selectedImages.length;
|
||||
selectedImageIndex++) {
|
||||
var selectedImage = $scope.model.selectedImages[selectedImageIndex];
|
||||
|
||||
if (folderImage.key === selectedImage.key) {
|
||||
imageIsSelected = true;
|
||||
}
|
||||
}
|
||||
if (imageIsSelected) {
|
||||
folderImage.selected = true;
|
||||
}
|
||||
}
|
||||
});
|
||||
getChildren(folder.id);
|
||||
$scope.currentFolder = folder;
|
||||
|
||||
localStorageService.set("umbLastOpenedMediaNodeId", folder.id);
|
||||
|
||||
};
|
||||
|
||||
$scope.clickHandler = function(image, event, index) {
|
||||
@@ -238,4 +220,106 @@ angular.module("umbraco")
|
||||
$scope.mediaPickerDetailsOverlay = null;
|
||||
};
|
||||
};
|
||||
|
||||
$scope.changeSearch = function() {
|
||||
$scope.loading = true;
|
||||
debounceSearchMedia();
|
||||
};
|
||||
|
||||
$scope.changePagination = function(pageNumber) {
|
||||
$scope.loading = true;
|
||||
$scope.searchOptions.pageNumber = pageNumber;
|
||||
searchMedia();
|
||||
};
|
||||
|
||||
var debounceSearchMedia = _.debounce(function () {
|
||||
$scope.$apply(function () {
|
||||
if ($scope.searchOptions.filter) {
|
||||
searchMedia();
|
||||
} else {
|
||||
// reset pagination
|
||||
$scope.searchOptions = {
|
||||
pageNumber: 1,
|
||||
pageSize: 100,
|
||||
totalItems: 0,
|
||||
totalPages: 0,
|
||||
filter: ''
|
||||
};
|
||||
getChildren($scope.currentFolder.id);
|
||||
}
|
||||
});
|
||||
}, 500);
|
||||
|
||||
function searchMedia() {
|
||||
$scope.loading = true;
|
||||
entityResource.getPagedDescendants($scope.startNodeId, "Media", $scope.searchOptions)
|
||||
.then(function (data) {
|
||||
// update image data to work with image grid
|
||||
angular.forEach(data.items, function(mediaItem){
|
||||
// set thumbnail and src
|
||||
mediaItem.thumbnail = mediaHelper.resolveFileFromEntity(mediaItem, true);
|
||||
mediaItem.image = mediaHelper.resolveFileFromEntity(mediaItem, false);
|
||||
// set properties to match a media object
|
||||
if (mediaItem.metaData &&
|
||||
mediaItem.metaData.umbracoWidth &&
|
||||
mediaItem.metaData.umbracoHeight) {
|
||||
|
||||
mediaItem.properties = [
|
||||
{
|
||||
alias: "umbracoWidth",
|
||||
value: mediaItem.metaData.umbracoWidth.Value
|
||||
},
|
||||
{
|
||||
alias: "umbracoHeight",
|
||||
value: mediaItem.metaData.umbracoHeight.Value
|
||||
}
|
||||
];
|
||||
}
|
||||
});
|
||||
// update images
|
||||
$scope.images = data.items ? data.items : [];
|
||||
// update pagination
|
||||
if (data.pageNumber > 0)
|
||||
$scope.searchOptions.pageNumber = data.pageNumber;
|
||||
if (data.pageSize > 0)
|
||||
$scope.searchOptions.pageSize = data.pageSize;
|
||||
$scope.searchOptions.totalItems = data.totalItems;
|
||||
$scope.searchOptions.totalPages = data.totalPages;
|
||||
// set already selected images to selected
|
||||
preSelectImages();
|
||||
$scope.loading = false;
|
||||
});
|
||||
}
|
||||
|
||||
function getChildren(id) {
|
||||
$scope.loading = true;
|
||||
mediaResource.getChildren(id)
|
||||
.then(function(data) {
|
||||
$scope.searchOptions.filter = "";
|
||||
$scope.images = data.items ? data.items : [];
|
||||
// set already selected images to selected
|
||||
preSelectImages();
|
||||
$scope.loading = false;
|
||||
});
|
||||
}
|
||||
|
||||
function preSelectImages() {
|
||||
for (var folderImageIndex = 0; folderImageIndex < $scope.images.length; folderImageIndex++) {
|
||||
var folderImage = $scope.images[folderImageIndex];
|
||||
var imageIsSelected = false;
|
||||
|
||||
for (var selectedImageIndex = 0;
|
||||
selectedImageIndex < $scope.model.selectedImages.length;
|
||||
selectedImageIndex++) {
|
||||
var selectedImage = $scope.model.selectedImages[selectedImageIndex];
|
||||
|
||||
if (folderImage.key === selectedImage.key) {
|
||||
imageIsSelected = true;
|
||||
}
|
||||
}
|
||||
if (imageIsSelected) {
|
||||
folderImage.selected = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
@@ -10,13 +10,18 @@
|
||||
|
||||
<div class="umb-control-group umb-mediapicker-upload">
|
||||
|
||||
<umb-load-indicator
|
||||
ng-if="loading">
|
||||
</umb-load-indicator>
|
||||
|
||||
<div class="form-search">
|
||||
<i class="icon-search"></i>
|
||||
<input
|
||||
class="umb-search-field search-query"
|
||||
ng-model="searchTerm"
|
||||
class="umb-search-field search-query -full-width-input"
|
||||
ng-model="searchOptions.filter"
|
||||
localize="placeholder"
|
||||
placeholder="@placeholders_filter"
|
||||
placeholder="@placeholders_search"
|
||||
ng-change="changeSearch()"
|
||||
type="text">
|
||||
</div>
|
||||
|
||||
@@ -32,7 +37,7 @@
|
||||
|
||||
</div>
|
||||
|
||||
<div class="row umb-control-group">
|
||||
<div class="row umb-control-group" ng-if="!searchOptions.filter">
|
||||
<ul class="umb-breadcrumbs">
|
||||
<li ng-hide="startNodeId != -1" class="umb-breadcrumbs__ancestor">
|
||||
<a href ng-click="gotoFolder()" prevent-default>Media</a>
|
||||
@@ -63,20 +68,20 @@
|
||||
</div>
|
||||
|
||||
<umb-file-dropzone
|
||||
ng-if="acceptedMediatypes.length > 0"
|
||||
ng-if="acceptedMediatypes.length > 0 && !loading"
|
||||
accepted-mediatypes="acceptedMediatypes"
|
||||
parent-id="{{currentFolder.id}}"
|
||||
files-uploaded="onUploadComplete"
|
||||
files-queued="onFilesQueue"
|
||||
accept="{{acceptedFileTypes}}"
|
||||
max-file-size="{{maxFileSize}}"
|
||||
hide-dropzone="{{!activeDrag && images.length > 0 }}"
|
||||
hide-dropzone="{{!activeDrag && images.length > 0 || searchOptions.filter }}"
|
||||
compact="{{ images.length > 0 }}">
|
||||
</umb-file-dropzone>
|
||||
|
||||
<umb-media-grid
|
||||
ng-if="!loading"
|
||||
items="images"
|
||||
filter-by="searchTerm"
|
||||
on-click="clickHandler"
|
||||
on-click-name="clickItemName"
|
||||
item-max-width="150"
|
||||
@@ -86,6 +91,21 @@
|
||||
only-images={{onlyImages}}>
|
||||
</umb-media-grid>
|
||||
|
||||
<div class="flex justify-center">
|
||||
<umb-pagination
|
||||
ng-if="searchOptions.totalPages > 0 && !loading"
|
||||
page-number="searchOptions.pageNumber"
|
||||
total-pages="searchOptions.totalPages"
|
||||
on-change="changePagination(pageNumber)">
|
||||
</umb-pagination>
|
||||
</div>
|
||||
|
||||
<umb-empty-state
|
||||
ng-if="searchOptions.filter && images.length === 0 && !loading"
|
||||
position="center">
|
||||
<localize key="general_searchNoResult"></localize>
|
||||
</umb-empty-state>
|
||||
|
||||
</div>
|
||||
|
||||
<umb-overlay
|
||||
|
||||
+1
-1
@@ -72,7 +72,7 @@ angular.module("umbraco").controller("Umbraco.Overlays.TreePickerController",
|
||||
$scope.enableSearh = true;
|
||||
|
||||
//if a alternative startnode is used, we need to check if it is a container
|
||||
if (dialogOptions.startNodeId && dialogOptions.startNodeId !== -1) {
|
||||
if (dialogOptions.startNodeId && dialogOptions.startNodeId !== -1 && dialogOptions.startNodeId !== "-1") {
|
||||
entityResource.getById(dialogOptions.startNodeId, $scope.entityType).then(function (node) {
|
||||
if (node.metaData.IsContainer) {
|
||||
openMiniListView(node);
|
||||
|
||||
@@ -1,13 +1,16 @@
|
||||
<div class="umb-property">
|
||||
<ng-form name="propertyForm">
|
||||
<div class="control-group umb-control-group" ng-class="{hidelabel:property.hideLabel}" >
|
||||
|
||||
<div class="control-group umb-control-group" ng-class="{hidelabel:property.hideLabel}">
|
||||
|
||||
<val-property-msg property="property"></val-property-msg>
|
||||
|
||||
|
||||
<div class="umb-el-wrap">
|
||||
|
||||
|
||||
<label class="control-label" ng-hide="property.hideLabel" for="{{property.alias}}" ng-attr-title="{{propertyAlias}}">
|
||||
{{property.label}}
|
||||
<span ng-if="property.validation.mandatory">
|
||||
<strong class="umb-control-required">*</strong>
|
||||
</span>
|
||||
<small ng-bind-html="property.description"></small>
|
||||
</label>
|
||||
|
||||
|
||||
@@ -62,14 +62,14 @@
|
||||
ng-repeat="child in miniListView.children"
|
||||
ng-click="selectNode(child)"
|
||||
ng-class="{'-selected':child.selected}">
|
||||
<div class="umb-table-cell umb-table-cell--auto-width" ng-class="{'umb-table-cell--faded':!child.published && entityType === 'Document'}">
|
||||
<div class="umb-table-cell umb-table-cell--auto-width" ng-class="{'umb-table-cell--faded':child.published === false}">
|
||||
<div class="flex items-center">
|
||||
<ins class="icon-navigation-right umb-table__row-expand" ng-click="openNode($event, child)"> </ins>
|
||||
<ins class="icon-navigation-right umb-table__row-expand" ng-click="openNode($event, child)" ng-class="{'umb-table__row-expand--hidden': child.hasChildren !== true}"> </ins>
|
||||
<i class="umb-table-body__icon umb-table-body__fileicon {{child.icon}}"></i>
|
||||
<i class="umb-table-body__icon umb-table-body__checkicon icon-check"></i>
|
||||
</div>
|
||||
</div>
|
||||
<div class="umb-table-cell black" ng-class="{'umb-table-cell--faded':!child.published && entityType === 'Document'}">{{ child.name }}</div>
|
||||
<div class="umb-table-cell black" ng-class="{'umb-table-cell--faded':child.published === false}">{{ child.name }}</div>
|
||||
</div>
|
||||
|
||||
<!-- Load indicator when the list doesn't have items -->
|
||||
|
||||
@@ -27,7 +27,8 @@ function DataTypeEditController($scope, $routeParams, $location, appState, navig
|
||||
description: preVals[i].description,
|
||||
label: preVals[i].label,
|
||||
view: preVals[i].view,
|
||||
value: preVals[i].value
|
||||
value: preVals[i].value,
|
||||
config: preVals[i].config,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,9 +13,15 @@ function mediaPickerController($scope, dialogService, entityResource, $log, icon
|
||||
multiPicker: false,
|
||||
entityType: "Media",
|
||||
section: "media",
|
||||
treeAlias: "media"
|
||||
treeAlias: "media",
|
||||
idType: "int"
|
||||
};
|
||||
|
||||
//combine the dialogOptions with any values returned from the server
|
||||
if ($scope.model.config) {
|
||||
angular.extend(dialogOptions, $scope.model.config);
|
||||
}
|
||||
|
||||
$scope.openContentPicker = function() {
|
||||
$scope.contentPickerOverlay = dialogOptions;
|
||||
$scope.contentPickerOverlay.view = "treePicker";
|
||||
@@ -53,18 +59,21 @@ function mediaPickerController($scope, dialogService, entityResource, $log, icon
|
||||
};
|
||||
|
||||
$scope.add = function (item) {
|
||||
|
||||
var itemId = dialogOptions.idType === "udi" ? item.udi : item.id;
|
||||
|
||||
var currIds = _.map($scope.renderModel, function (i) {
|
||||
return i.id;
|
||||
return dialogOptions.idType === "udi" ? i.udi : i.id;
|
||||
});
|
||||
if (currIds.indexOf(item.id) < 0) {
|
||||
if (currIds.indexOf(itemId) < 0) {
|
||||
item.icon = iconHelper.convertFromLegacyIcon(item.icon);
|
||||
$scope.renderModel.push({name: item.name, id: item.id, icon: item.icon});
|
||||
$scope.renderModel.push({ name: item.name, id: item.id, icon: item.icon, udi: item.udi });
|
||||
}
|
||||
};
|
||||
|
||||
var unsubscribe = $scope.$on("formSubmitting", function (ev, args) {
|
||||
var currIds = _.map($scope.renderModel, function (i) {
|
||||
return i.id;
|
||||
return dialogOptions.idType === "udi" ? i.udi : i.id;
|
||||
});
|
||||
$scope.model.value = trim(currIds.join(), ",");
|
||||
});
|
||||
@@ -76,12 +85,15 @@ function mediaPickerController($scope, dialogService, entityResource, $log, icon
|
||||
|
||||
//load media data
|
||||
var modelIds = $scope.model.value ? $scope.model.value.split(',') : [];
|
||||
entityResource.getByIds(modelIds, dialogOptions.entityType).then(function (data) {
|
||||
_.each(data, function (item, i) {
|
||||
item.icon = iconHelper.convertFromLegacyIcon(item.icon);
|
||||
$scope.renderModel.push({ name: item.name, id: item.id, icon: item.icon });
|
||||
if (modelIds.length > 0) {
|
||||
entityResource.getByIds(modelIds, dialogOptions.entityType).then(function (data) {
|
||||
_.each(data, function (item, i) {
|
||||
item.icon = iconHelper.convertFromLegacyIcon(item.icon);
|
||||
$scope.renderModel.push({ name: item.name, id: item.id, icon: item.icon, udi: item.udi });
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -12,26 +12,30 @@ angular.module('umbraco')
|
||||
multiPicker: false,
|
||||
entityType: "Document",
|
||||
type: "content",
|
||||
treeAlias: "content"
|
||||
};
|
||||
treeAlias: "content",
|
||||
idType: "int"
|
||||
};
|
||||
|
||||
//combine the config with any values returned from the server
|
||||
if ($scope.model.config) {
|
||||
angular.extend(config, $scope.model.config);
|
||||
}
|
||||
|
||||
if($scope.model.value){
|
||||
$scope.ids = $scope.model.value.split(',');
|
||||
entityResource.getByIds($scope.ids, config.entityType).then(function (data) {
|
||||
_.each(data, function (item, i) {
|
||||
item.icon = iconHelper.convertFromLegacyIcon(item.icon);
|
||||
$scope.renderModel.push({name: item.name, id: item.id, icon: item.icon});
|
||||
});
|
||||
$scope.renderModel.push({ name: item.name, id: item.id, icon: item.icon, udi: item.udi });
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
$scope.openContentPicker = function() {
|
||||
$scope.treePickerOverlay = {};
|
||||
$scope.treePickerOverlay.section = config.type;
|
||||
$scope.treePickerOverlay.treeAlias = config.treeAlias;
|
||||
$scope.treePickerOverlay.multiPicker = config.multiPicker;
|
||||
$scope.treePickerOverlay = config;
|
||||
$scope.treePickerOverlay.section = config.type;
|
||||
$scope.treePickerOverlay.view = "treePicker";
|
||||
$scope.treePickerOverlay.show = true;
|
||||
$scope.treePickerOverlay.show = true;
|
||||
|
||||
$scope.treePickerOverlay.submit = function(model) {
|
||||
|
||||
@@ -64,12 +68,15 @@ angular.module('umbraco')
|
||||
$scope.ids = [];
|
||||
};
|
||||
|
||||
$scope.add =function(item){
|
||||
if($scope.ids.indexOf(item.id) < 0){
|
||||
$scope.add = function (item) {
|
||||
|
||||
var itemId = config.idType === "udi" ? item.udi : item.id;
|
||||
|
||||
if ($scope.ids.indexOf(itemId) < 0){
|
||||
item.icon = iconHelper.convertFromLegacyIcon(item.icon);
|
||||
|
||||
$scope.ids.push(item.id);
|
||||
$scope.renderModel.push({name: item.name, id: item.id, icon: item.icon});
|
||||
$scope.ids.push(itemId);
|
||||
$scope.renderModel.push({name: item.name, id: item.id, icon: item.icon, udi: item.udi});
|
||||
$scope.model.value = trim($scope.ids.join(), ",");
|
||||
}
|
||||
};
|
||||
|
||||
@@ -12,7 +12,12 @@ angular.module('umbraco')
|
||||
$scope.model.value = {
|
||||
type: "content"
|
||||
};
|
||||
}
|
||||
}
|
||||
if (!$scope.model.config) {
|
||||
$scope.model.config = {
|
||||
idType: "int"
|
||||
};
|
||||
}
|
||||
|
||||
if($scope.model.value.id && $scope.model.value.type !== "member"){
|
||||
var ent = "Document";
|
||||
@@ -29,7 +34,8 @@ angular.module('umbraco')
|
||||
|
||||
$scope.openContentPicker =function(){
|
||||
$scope.treePickerOverlay = {
|
||||
view: "treepicker",
|
||||
view: "treepicker",
|
||||
idType: $scope.model.config.idType,
|
||||
section: $scope.model.value.type,
|
||||
treeAlias: $scope.model.value.type,
|
||||
multiPicker: false,
|
||||
@@ -67,6 +73,6 @@ angular.module('umbraco')
|
||||
$scope.clear();
|
||||
item.icon = iconHelper.convertFromLegacyIcon(item.icon);
|
||||
$scope.node = item;
|
||||
$scope.model.value.id = item.id;
|
||||
$scope.model.value.id = $scope.model.config.idType === "udi" ? item.udi : item.id;
|
||||
}
|
||||
});
|
||||
+39
-24
@@ -17,11 +17,11 @@ function contentPickerController($scope, entityResource, editorState, iconHelper
|
||||
$scope.$watch(function () {
|
||||
//return the joined Ids as a string to watch
|
||||
return _.map($scope.renderModel, function (i) {
|
||||
return i.id;
|
||||
return $scope.model.config.idType === "udi" ? i.udi : i.id;
|
||||
}).join();
|
||||
}, function (newVal) {
|
||||
var currIds = _.map($scope.renderModel, function (i) {
|
||||
return i.id;
|
||||
return $scope.model.config.idType === "udi" ? i.udi : i.id;
|
||||
});
|
||||
$scope.model.value = trim(currIds.join(), ",");
|
||||
|
||||
@@ -58,7 +58,7 @@ function contentPickerController($scope, entityResource, editorState, iconHelper
|
||||
startNode: {
|
||||
query: "",
|
||||
type: "content",
|
||||
id: $scope.model.config.startNodeId ? $scope.model.config.startNodeId : -1 // get start node for simple Content Picker
|
||||
id: $scope.model.config.startNodeId ? $scope.model.config.startNodeId : -1 // get start node for simple Content Picker
|
||||
}
|
||||
};
|
||||
|
||||
@@ -105,10 +105,11 @@ function contentPickerController($scope, entityResource, editorState, iconHelper
|
||||
$scope.clear();
|
||||
$scope.add(data);
|
||||
}
|
||||
angularHelper.getCurrentForm($scope).$setDirty();
|
||||
angularHelper.getCurrentForm($scope).$setDirty();
|
||||
},
|
||||
treeAlias: $scope.model.config.startNode.type,
|
||||
section: $scope.model.config.startNode.type
|
||||
section: $scope.model.config.startNode.type,
|
||||
idType: "int"
|
||||
};
|
||||
|
||||
//since most of the pre-value config's are used in the dialog options (i.e. maxNumber, minNumber, etc...) we'll merge the
|
||||
@@ -147,9 +148,10 @@ function contentPickerController($scope, entityResource, editorState, iconHelper
|
||||
if ($scope.model.config.startNode.query) {
|
||||
var rootId = $routeParams.id;
|
||||
entityResource.getByQuery($scope.model.config.startNode.query, rootId, "Document").then(function (ent) {
|
||||
dialogOptions.startNodeId = ent.id;
|
||||
dialogOptions.startNodeId = $scope.model.config.idType === "udi" ? ent.udi : ent.id;
|
||||
});
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
dialogOptions.startNodeId = $scope.model.config.startNode.id;
|
||||
}
|
||||
|
||||
@@ -200,10 +202,12 @@ function contentPickerController($scope, entityResource, editorState, iconHelper
|
||||
|
||||
$scope.add = function (item) {
|
||||
var currIds = _.map($scope.renderModel, function (i) {
|
||||
return i.id;
|
||||
return $scope.model.config.idType === "udi" ? i.udi : i.id;
|
||||
});
|
||||
|
||||
if (currIds.indexOf(item.id) < 0) {
|
||||
var itemId = $scope.model.config.idType === "udi" ? item.udi : item.id;
|
||||
|
||||
if (currIds.indexOf(itemId) < 0) {
|
||||
setEntityUrl(item);
|
||||
}
|
||||
};
|
||||
@@ -227,7 +231,7 @@ function contentPickerController($scope, entityResource, editorState, iconHelper
|
||||
|
||||
var unsubscribe = $scope.$on("formSubmitting", function (ev, args) {
|
||||
var currIds = _.map($scope.renderModel, function (i) {
|
||||
return i.id;
|
||||
return $scope.model.config.idType === "udi" ? i.udi : i.id;
|
||||
});
|
||||
$scope.model.value = trim(currIds.join(), ",");
|
||||
});
|
||||
@@ -237,26 +241,36 @@ function contentPickerController($scope, entityResource, editorState, iconHelper
|
||||
unsubscribe();
|
||||
});
|
||||
|
||||
//load current data
|
||||
|
||||
var modelIds = $scope.model.value ? $scope.model.value.split(',') : [];
|
||||
|
||||
entityResource.getByIds(modelIds, entityType).then(function (data) {
|
||||
//load current data if anything selected
|
||||
if (modelIds.length > 0) {
|
||||
entityResource.getByIds(modelIds, entityType).then(function(data) {
|
||||
|
||||
_.each(modelIds, function (id, i) {
|
||||
var entity = _.find(data, function (d) {
|
||||
return d.id == id;
|
||||
});
|
||||
|
||||
if (entity) {
|
||||
setEntityUrl(entity);
|
||||
}
|
||||
|
||||
});
|
||||
_.each(modelIds,
|
||||
function(id, i) {
|
||||
var entity = _.find(data,
|
||||
function(d) {
|
||||
return $scope.model.config.idType === "udi" ? (d.udi == id) : (d.id == id);
|
||||
});
|
||||
|
||||
if (entity) {
|
||||
setEntityUrl(entity);
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
//everything is loaded, start the watch on the model
|
||||
startWatch();
|
||||
|
||||
});
|
||||
}
|
||||
else {
|
||||
//everything is loaded, start the watch on the model
|
||||
startWatch();
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
function setEntityUrl(entity) {
|
||||
|
||||
@@ -304,6 +318,7 @@ function contentPickerController($scope, entityResource, editorState, iconHelper
|
||||
$scope.renderModel.push({
|
||||
"name": item.name,
|
||||
"id": item.id,
|
||||
"udi": item.udi,
|
||||
"icon": item.icon,
|
||||
"path": item.path,
|
||||
"url": item.url,
|
||||
|
||||
@@ -483,7 +483,7 @@ function listViewController($rootScope, $scope, $routeParams, $injector, $cookie
|
||||
//we need to do a double sync here: first refresh the node where the content was moved,
|
||||
// then refresh the node where the content was moved from
|
||||
navigationService.syncTree({
|
||||
tree: target.nodeType,
|
||||
tree: target.nodeType ? target.nodeType : (target.metaData.treeAlias),
|
||||
path: newPath,
|
||||
forceReload: true,
|
||||
activate: false
|
||||
|
||||
+14
-2
@@ -40,7 +40,13 @@ angular.module('umbraco').controller("Umbraco.PropertyEditors.MediaPickerControl
|
||||
}
|
||||
|
||||
$scope.images.push(media);
|
||||
$scope.ids.push(media.id);
|
||||
|
||||
if ($scope.model.config.idType === "udi") {
|
||||
$scope.ids.push(media.udi);
|
||||
}
|
||||
else {
|
||||
$scope.ids.push(media.id);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
@@ -80,7 +86,13 @@ angular.module('umbraco').controller("Umbraco.PropertyEditors.MediaPickerControl
|
||||
}
|
||||
|
||||
$scope.images.push(media);
|
||||
$scope.ids.push(media.id);
|
||||
|
||||
if ($scope.model.config.idType === "udi") {
|
||||
$scope.ids.push(media.udi);
|
||||
}
|
||||
else {
|
||||
$scope.ids.push(media.id);
|
||||
}
|
||||
});
|
||||
|
||||
$scope.sync();
|
||||
|
||||
+17
-5
@@ -68,12 +68,19 @@ function memberPickerController($scope, dialogService, entityResource, $log, ico
|
||||
|
||||
$scope.add = function (item) {
|
||||
var currIds = _.map($scope.renderModel, function (i) {
|
||||
return i.id;
|
||||
if ($scope.model.config.idType === "udi") {
|
||||
return i.udi;
|
||||
}
|
||||
else {
|
||||
return i.id;
|
||||
}
|
||||
});
|
||||
|
||||
if (currIds.indexOf(item.id) < 0) {
|
||||
var itemId = $scope.model.config.idType === "udi" ? item.udi : item.id;
|
||||
|
||||
if (currIds.indexOf(itemId) < 0) {
|
||||
item.icon = iconHelper.convertFromLegacyIcon(item.icon);
|
||||
$scope.renderModel.push({name: item.name, id: item.id, icon: item.icon});
|
||||
$scope.renderModel.push({ name: item.name, id: item.id, udi: item.udi, icon: item.icon});
|
||||
}
|
||||
};
|
||||
|
||||
@@ -83,7 +90,12 @@ function memberPickerController($scope, dialogService, entityResource, $log, ico
|
||||
|
||||
var unsubscribe = $scope.$on("formSubmitting", function (ev, args) {
|
||||
var currIds = _.map($scope.renderModel, function (i) {
|
||||
return i.id;
|
||||
if ($scope.model.config.idType === "udi") {
|
||||
return i.udi;
|
||||
}
|
||||
else {
|
||||
return i.id;
|
||||
}
|
||||
});
|
||||
$scope.model.value = trim(currIds.join(), ",");
|
||||
});
|
||||
@@ -99,7 +111,7 @@ function memberPickerController($scope, dialogService, entityResource, $log, ico
|
||||
_.each(data, function (item, i) {
|
||||
// set default icon if it's missing
|
||||
item.icon = (item.icon) ? iconHelper.convertFromLegacyIcon(item.icon) : "icon-user";
|
||||
$scope.renderModel.push({ name: item.name, id: item.id, icon: item.icon });
|
||||
$scope.renderModel.push({ name: item.name, id: item.id, udi: item.udi, icon: item.icon });
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
@@ -104,7 +104,8 @@
|
||||
|
||||
<!-- Defines the default document type property used when adding properties in the back-office (if missing or empty, defaults to Textstring -->
|
||||
<defaultDocumentTypeProperty>Textstring</defaultDocumentTypeProperty>
|
||||
|
||||
|
||||
<showDeprecatedPropertyEditors>true</showDeprecatedPropertyEditors>
|
||||
</content>
|
||||
|
||||
<security>
|
||||
|
||||
@@ -27,6 +27,10 @@
|
||||
<key alias="unpublish">Depubliceren</key>
|
||||
<key alias="refreshNode">Nodes opnieuw inladen</key>
|
||||
<key alias="republish">Herpubliceer de site</key>
|
||||
<key alias="SetPermissionsForThePage">Stel rechten voor pagina %0% in</key>
|
||||
<key alias="chooseWhereToMove">Waarheen verplaatsen/</key>
|
||||
<key alias="toInTheTreeStructureBelow">Naar de onderstaande boomstructuur</key>
|
||||
<key alias="restore" version="7.3.0">Herstellen</key>
|
||||
<key alias="rights">Rechten</key>
|
||||
<key alias="rollback">Vorige versies</key>
|
||||
<key alias="sendtopublish">Klaar voor publicatie</key>
|
||||
@@ -64,10 +68,10 @@
|
||||
<key alias="atViewingFor">Tonen voor</key>
|
||||
</area>
|
||||
<area alias="buttons">
|
||||
<key alias="clearSelection">Selectie ongedaan maken</key>
|
||||
<key alias="select">Selecteren</key>
|
||||
<key alias="selectCurrentFolder">Selecteer huidige map</key>
|
||||
<key alias="somethingElse">Doe iets anders</key>
|
||||
|
||||
<key alias="bold">Vet</key>
|
||||
<key alias="deindent">Paragraaf uitspringen</key>
|
||||
<key alias="formFieldInsert">Voeg formulierveld in</key>
|
||||
@@ -89,11 +93,14 @@
|
||||
<key alias="save">Opslaan</key>
|
||||
<key alias="saveAndPublish">Opslaan en publiceren</key>
|
||||
<key alias="saveToPublish">Opslaan en verzenden voor goedkeuring</key>
|
||||
<key alias="saveListView">Sla list view op</key>
|
||||
<key alias="showPage">voorbeeld bekijken</key>
|
||||
<key alias="showPageDisabled">Voorbeeld bekijken is uitgeschakeld omdat er geen template is geselecteerd</key>
|
||||
<key alias="styleChoose">Stijl kiezen</key>
|
||||
<key alias="styleShow">Stijlen tonen</key>
|
||||
<key alias="tableInsert">Tabel invoegen</key>
|
||||
<key alias="generateModels">Genereer models</key>
|
||||
<key alias="saveAndGenerateModels">Opslaan en models genereren</key>
|
||||
</area>
|
||||
<area alias="changeDocType">
|
||||
<key alias="changeDocTypeInstruction">Om het documenttype voor de geselecteerde inhoud te wijzigen, selecteert u eerst uit de lijst van geldige types voor deze locatie.</key>
|
||||
@@ -133,7 +140,8 @@
|
||||
<key alias="itemChanged">Dit item is gewijzigd na publicatie</key>
|
||||
<key alias="itemNotPublished">Dit item is niet gepubliceerd</key>
|
||||
<key alias="lastPublished">Laatst gepubliceerd op</key>
|
||||
<key alias="listViewNoItems" version="7.1.5">Nog geen items om weer te geven.</key>
|
||||
<key alias="noItemsToShow">Er zijn geen items om weer te geven</key>
|
||||
<key alias="listViewNoItems" version="7.1.5">Er zijn geen items om weer te geven.</key>
|
||||
<key alias="mediatype">Mediatype</key>
|
||||
<key alias="mediaLinks">Link naar media item(s)</key>
|
||||
<key alias="membergroup">Ledengroep</key>
|
||||
@@ -143,7 +151,9 @@
|
||||
<key alias="nodeName">Pagina Titel</key>
|
||||
<key alias="otherElements">Eigenschappen</key>
|
||||
<key alias="parentNotPublished">Dit document is gepubliceerd maar niet zichtbaar omdat de bovenliggende node '%0%' niet gepubliceerd is</key>
|
||||
<key alias="parentNotPublishedAnomaly">Oeps: dit document is gepubliceerd, maar het is niet in de cache (interne serverfout)</key>
|
||||
<key alias="parentNotPublishedAnomaly">Dit document is gepubliceerd, maar het is niet in de cache (interne serverfout)</key>
|
||||
<key alias="getUrlException">Kan de Url niet ophalen</key>
|
||||
<key alias="routeError">Dit document is gepubliceerd, maar de Url conflicteert met %0%</key>
|
||||
<key alias="publish">Publiceren</key>
|
||||
<key alias="publishStatus">Publicatiestatus</key>
|
||||
<key alias="releaseDate">Publiceren op</key>
|
||||
@@ -161,23 +171,34 @@
|
||||
<key alias="uploadClear">Bestand(en) verwijderen</key>
|
||||
<key alias="urls">Link naar het document</key>
|
||||
<key alias="memberof">Lid van groep(en)</key>
|
||||
<key alias="notmemberof">Geen lid van groep(en)</key>
|
||||
|
||||
<key alias="notmemberof">Geen lid van groep(en)</key>
|
||||
<key alias="childItems" version="7.0">Kinderen</key>
|
||||
<key alias="target" version="7.0">Doel</key>
|
||||
<key alias="scheduledPublishServerTime">Dit betekend de volgende tijd op de server:</key>
|
||||
<key alias="scheduledPublishDocumentation"><![CDATA[<a href="https://our.umbraco.org/documentation/Getting-Started/Data/Scheduled-Publishing/#timezones" target="_blank">Wat houd dit in?</a>]]></key>
|
||||
</area>
|
||||
<area alias="media">
|
||||
<key alias="clickToUpload">Klik om te uploaden</key>
|
||||
<key alias="dropFilesHere">Plaats je bestanden hier...</key>
|
||||
<key alias="urls">Link naar media</key>
|
||||
<key alias="orClickHereToUpload">Of klik hier om bestanden te kiezen</key>
|
||||
<key alias="onlyAllowedFiles">De toegestane bestandtypen zijn</key>
|
||||
<key alias="disallowedFileType">Dit bestand heeft niet het juiste file-type. Dit bestand kan niet geupload worden.</key>
|
||||
<key alias="maxFileSize">Max file size is</key>
|
||||
</area>
|
||||
<area alias="member">
|
||||
<key alias="createNewMember">Maak nieuwe member aan</key>
|
||||
<key alias="allMembers">Alle Members</key>
|
||||
</area>
|
||||
<area alias="create">
|
||||
<key alias="chooseNode">Waar wil je de nieuwe %0% aanmaken?</key>
|
||||
<key alias="createUnder">Aanmaken onder</key>
|
||||
<key alias="updateData">Kies een type en een titel</key>
|
||||
|
||||
<key alias="noDocumentTypes" version="7.0"><![CDATA[Er zijn geen toegestane documenttypes beschikbaar. Je moet deze inschakelen in de Instellingen sectie onder <strong>"Documenttypes"</ strong>.]]></key>
|
||||
|
||||
<key alias="noMediaTypes" version="7.0"><![CDATA[Er zijn geen toegestande mediatypes beschikbaar. Je moet deze in schakelen in de Instellingen sectie onder <strong>"Mediatypes"</strong>.]]></key>
|
||||
<key alias="documentTypeWithoutTemplate">Document Type zonder template</key>
|
||||
<key alias="newFolder">Nieuwe folder</key>
|
||||
<key alias="newDataType">Nieuw data type</key>
|
||||
</area>
|
||||
<area alias="dashboard">
|
||||
<key alias="browser">Open je website</key>
|
||||
@@ -189,38 +210,38 @@
|
||||
<key alias="welcome">Welkom</key>
|
||||
</area>
|
||||
<area alias="prompt">
|
||||
<key alias="stay">Stay</key>
|
||||
<key alias="discardChanges">Discard changes</key>
|
||||
<key alias="unsavedChanges">You have unsaved changes</key>
|
||||
<key alias="unsavedChangesWarning">Are you sure you want to navigate away from this page? - you have unsaved changes</key>
|
||||
<key alias="stay">Blijf op deze pagina</key>
|
||||
<key alias="discardChanges">Negeer wijzigingen</key>
|
||||
<key alias="unsavedChanges">Wijzigingen niet opgeslagen</key>
|
||||
<key alias="unsavedChangesWarning">Weet je zeker dat deze pagina wilt verlaten? - er zijn onopgeslagen wijzigingen</key>
|
||||
</area>
|
||||
<area alias="bulk">
|
||||
<key alias="done">Done</key>
|
||||
|
||||
<key alias="deletedItem">Deleted %0% item</key>
|
||||
<key alias="deletedItems">Deleted %0% items</key>
|
||||
<key alias="deletedItemOfItem">Deleted %0% out of %1% item</key>
|
||||
<key alias="deletedItemOfItems">Deleted %0% out of %1% items</key>
|
||||
|
||||
<key alias="publishedItem">Published %0% item</key>
|
||||
<key alias="publishedItems">Published %0% items</key>
|
||||
<key alias="publishedItemOfItem">Published %0% out of %1% item</key>
|
||||
<key alias="publishedItemOfItems">Published %0% out of %1% items</key>
|
||||
|
||||
<key alias="unpublishedItem">Unpublished %0% item</key>
|
||||
<key alias="unpublishedItems">Unpublished %0% items</key>
|
||||
<key alias="unpublishedItemOfItem">Unpublished %0% out of %1% item</key>
|
||||
<key alias="unpublishedItemOfItems">Unpublished %0% out of %1% items</key>
|
||||
|
||||
<key alias="movedItem">Moved %0% item</key>
|
||||
<key alias="movedItems">Moved %0% items</key>
|
||||
<key alias="movedItemOfItem">Moved %0% out of %1% item</key>
|
||||
<key alias="movedItemOfItems">Moved %0% out of %1% items</key>
|
||||
|
||||
<key alias="copiedItem">Copied %0% item</key>
|
||||
<key alias="copiedItems">Copied %0% items</key>
|
||||
<key alias="copiedItemOfItem">Copied %0% out of %1% item</key>
|
||||
<key alias="copiedItemOfItems">Copied %0% out of %1% items</key>
|
||||
|
||||
<key alias="deletedItem">%0% item verwijderd</key>
|
||||
<key alias="deletedItems">%0% items verwijderd</key>
|
||||
<key alias="deletedItemOfItem">Item %0% van de %1% verwijderd</key>
|
||||
<key alias="deletedItemOfItems">Items %0% van de %1% verwijderd</key>
|
||||
|
||||
<key alias="publishedItem">%0% item gepubliceerd</key>
|
||||
<key alias="publishedItems">%0% items gepubliceerd</key>
|
||||
<key alias="publishedItemOfItem">Item %0% van de %1% gepubliceerd</key>
|
||||
<key alias="publishedItemOfItems">Items %0% van de %1% gepubliceerd</key>
|
||||
|
||||
<key alias="unpublishedItem">%0% item gedepubliceerd</key>
|
||||
<key alias="unpublishedItems">%0% items gedepubliceerd</key>
|
||||
<key alias="unpublishedItemOfItem">Item %0% van de %1% gedepubliceerd</key>
|
||||
<key alias="unpublishedItemOfItems">Items %0% van de %1% gedepubliceerd</key>
|
||||
|
||||
<key alias="movedItem">%0% item verplaatst</key>
|
||||
<key alias="movedItems">%0% items verplaatst</key>
|
||||
<key alias="movedItemOfItem">item %0% van de %1% verplaatst</key>
|
||||
<key alias="movedItemOfItems">items %0% van de %1% verplaatst</key>
|
||||
|
||||
<key alias="copiedItem">%0% item gekopieerd</key>
|
||||
<key alias="copiedItems">%0% items gekopieerd</key>
|
||||
<key alias="copiedItemOfItem">item %0% van de %1% gekopieerd</key>
|
||||
<key alias="copiedItemOfItems">item %0% van de %1% gekopieerd</key>
|
||||
</area>
|
||||
<area alias="defaultdialogs">
|
||||
<key alias="anchorInsert">Naam</key>
|
||||
@@ -269,21 +290,55 @@
|
||||
<key alias="thumbnailimageclickfororiginal">Klik op de afbeelding voor volledige grootte</key>
|
||||
<key alias="treepicker">Kies een item</key>
|
||||
<key alias="viewCacheItem">Toon cache item</key>
|
||||
<key alias="createFolder">Maak folder aan...</key>
|
||||
<key alias="relateToOriginalLabel">Relateer aan origineel</key>
|
||||
<key alias="includeDescendants">Descendants meenemen</key>
|
||||
<key alias="theFriendliestCommunity">De vriendelijkste community</key>
|
||||
<key alias="linkToPage">Link naar pagina</key>
|
||||
<key alias="openInNewWindow">Opent het gelinkte document in een nieuw venster of tab</key>
|
||||
<key alias="linkToMedia">Link naar media</key>
|
||||
<key alias="selectMedia">Selecteer media</key>
|
||||
<key alias="selectIcon">Selecteer icoon</key>
|
||||
<key alias="selectItem">Selecteer item</key>
|
||||
<key alias="selectLink">Selecteer link</key>
|
||||
<key alias="selectMacro">Selecteer macro</key>
|
||||
<key alias="selectContent">Selecteer content</key>
|
||||
<key alias="selectMember">Selecteer member</key>
|
||||
<key alias="selectMemberGroup">Selecteer member group</key>
|
||||
<key alias="noMacroParams">Er zijn geen parameters voor deze macro</key>
|
||||
<key alias="externalLoginProviders">Externe login providers</key>
|
||||
<key alias="exceptionDetail">Error details</key>
|
||||
<key alias="stacktrace">Stacktrace</key>
|
||||
<key alias="innerException">Inner Exception</key>
|
||||
<key alias="linkYour">Link je</key>
|
||||
<key alias="unLinkYour">De-Link je</key>
|
||||
<key alias="account">account</key>
|
||||
<key alias="selectEditor">Selecteer editor</key>
|
||||
</area>
|
||||
<area alias="dictionaryItem">
|
||||
<key alias="description"><![CDATA[
|
||||
Wijzig de verschillende taalversies voor het woordenboek item '%0%'. Je kunt extra talen toevoegen bij 'talen' in het menu links
|
||||
]]></key>
|
||||
<key alias="displayName">Cultuurnaam</key>
|
||||
<key alias="changeKey">Verander de key van het dictionary item.</key>
|
||||
<key alias="changeKeyError">
|
||||
<![CDATA[
|
||||
De key '%0%' bestaat al.
|
||||
]]>
|
||||
</key>
|
||||
</area>
|
||||
<area alias="placeholders">
|
||||
<key alias="username">Typ je gebruikersnaam</key>
|
||||
<key alias="password">Typ je wachtwoord</key>
|
||||
<key alias="username">Typ jouw gebruikersnaam</key>
|
||||
<key alias="password">Typ jouw wachtwoord</key>
|
||||
<key alias="confirmPassword">Bevestig jouw wachtwoord</key>
|
||||
<key alias="nameentity">Benoem de %0%...</key>
|
||||
<key alias="entername">Typ een naam...</key>
|
||||
<key alias="label">Label...</key>
|
||||
<key alias="enterDescription">Voer een omschrijving in...</key>
|
||||
<key alias="search">Typ om te zoeken...</key>
|
||||
<key alias="filter">Typ om te filteren...</key>
|
||||
<key alias="enterTags">Typ om tags toe te voegen (druk op enter na elke tag)...</key>
|
||||
<key alias="email">Voer jouw email in</key>
|
||||
</area>
|
||||
|
||||
<area alias="editcontenttype">
|
||||
@@ -331,10 +386,17 @@
|
||||
<key alias="errorRegExpWithoutTab">%0% is niet in het correcte formaat</key>
|
||||
</area>
|
||||
<area alias="errors">
|
||||
<key alias="receivedErrorFromServer">Een error ontvangen van de server</key>
|
||||
<key alias="dissallowedMediaType">Het opgegeven bestandstype is niet toegestaan door de beheerder</key>
|
||||
<key alias="codemirroriewarning">OPMERKING! Ondanks dat CodeMiror is ingeschakeld, is het uitgeschakeld in Internet Explorer omdat het niet stabiel genoeg is.</key>
|
||||
<key alias="contentTypeAliasAndNameNotNull">Zowel de alias als de naam van het nieuwe eigenschappen type moeten worden ingevuld!</key>
|
||||
<key alias="filePermissionsError">Er is een probleem met de lees/schrijf rechten op een bestand of map</key>
|
||||
<key alias="macroErrorLoadingPartialView">Error bij het laden van Partial View script (file: %0%)</key>
|
||||
<key alias="macroErrorLoadingUsercontrol">Error bij het laden van userControl '%0%'</key>
|
||||
<key alias="macroErrorLoadingCustomControl">Error bij het laden van customControl (Assembly: %0%, Type: '%1%')</key>
|
||||
<key alias="macroErrorLoadingMacroEngineScript">Error bij het laden van MacroEngine script (file: %0%)</key>
|
||||
<key alias="macroErrorParsingXSLTFile">"Error bij het parsen van XSLT file: %0%</key>
|
||||
<key alias="macroErrorReadingXSLTFile">"Error bij het laden van XSLT file: %0%</key>
|
||||
<key alias="missingTitle">Vul een titel in</key>
|
||||
<key alias="missingType">Selecteer een type</key>
|
||||
<key alias="pictureResizeBiggerThanOrg">U wilt een afbeelding groter maken dan de originele afmetingen. Weet je zeker dat je wilt doorgaan?</key>
|
||||
@@ -355,102 +417,142 @@
|
||||
<key alias="actions">Acties</key>
|
||||
<key alias="add">Toevoegen</key>
|
||||
<key alias="alias">Alias</key>
|
||||
<key alias="all">Alles</key>
|
||||
<key alias="areyousure">Weet je het zeker?</key>
|
||||
<key alias="border">Rand</key>
|
||||
<key alias="by">of</key>
|
||||
<key alias="cancel">Annuleren</key>
|
||||
<key alias="back">Terug</key>
|
||||
<key alias="border">Border</key>
|
||||
<key alias="by">bij</key>
|
||||
<key alias="cancel">Cancel</key>
|
||||
<key alias="cellMargin">Cel marge</key>
|
||||
<key alias="choose">Kiezen</key>
|
||||
<key alias="close">Sluiten</key>
|
||||
<key alias="closewindow">Venster sluiten</key>
|
||||
<key alias="comment">Opmerking</key>
|
||||
<key alias="confirm">Bevestigen</key>
|
||||
<key alias="constrainProportions">Verhouding behouden</key>
|
||||
<key alias="continue">Doorgaan</key>
|
||||
<key alias="copy">Kopiëren</key>
|
||||
<key alias="choose">Kies</key>
|
||||
<key alias="close">Sluit</key>
|
||||
<key alias="closewindow">Sluit venster</key>
|
||||
<key alias="comment">Comment</key>
|
||||
<key alias="confirm">Bevestig</key>
|
||||
<key alias="constrainProportions">Verhoudingen behouden</key>
|
||||
<key alias="continue">Ga verder</key>
|
||||
<key alias="copy">Copy</key>
|
||||
<key alias="create">Aanmaken</key>
|
||||
<key alias="database">Databank</key>
|
||||
<key alias="database">Database</key>
|
||||
<key alias="date">Datum</key>
|
||||
<key alias="default">Standaard</key>
|
||||
<key alias="delete">Verwijderen</key>
|
||||
<key alias="delete">Verwijder</key>
|
||||
<key alias="deleted">Verwijderd</key>
|
||||
<key alias="deleting">Verwijderen...</key>
|
||||
<key alias="deleting">Aan het verwijderen...</key>
|
||||
<key alias="design">Ontwerp</key>
|
||||
<key alias="dimensions">Afmetingen</key>
|
||||
<key alias="down">Beneden</key>
|
||||
<key alias="down">Omlaag</key>
|
||||
<key alias="download">Download</key>
|
||||
<key alias="edit">Aanpassen</key>
|
||||
<key alias="edited">Aangepast</key>
|
||||
<key alias="edit">Bewerk</key>
|
||||
<key alias="edited">Bewerkt</key>
|
||||
<key alias="elements">Elementen</key>
|
||||
<key alias="email">E-mail</key>
|
||||
<key alias="email">Email</key>
|
||||
<key alias="error">Fout</key>
|
||||
<key alias="findDocument">Zoeken</key>
|
||||
<key alias="height">Hoogte</key>
|
||||
<key alias="findDocument">Vind</key>
|
||||
<key alias="height">Hogte</key>
|
||||
<key alias="help">Help</key>
|
||||
<key alias="icon">Icoon</key>
|
||||
<key alias="import">Importeren</key>
|
||||
<key alias="innerMargin">Binnenmarge</key>
|
||||
<key alias="import">Import</key>
|
||||
<key alias="innerMargin">Binnenste marge</key>
|
||||
<key alias="insert">Invoegen</key>
|
||||
<key alias="install">Installeren</key>
|
||||
<key alias="justify">Uitvullen</key>
|
||||
<key alias="invalid">Ongeldig</key>
|
||||
<key alias="justify">Justify</key>
|
||||
<key alias="label">Label</key>
|
||||
<key alias="language">Taal</key>
|
||||
<key alias="layout">Lay-out</key>
|
||||
<key alias="loading">Bezig met laden</key>
|
||||
<key alias="locked">Geblokkeerd</key>
|
||||
<key alias="layout">Layout</key>
|
||||
<key alias="loading">Aan het laden</key>
|
||||
<key alias="locked">Gesloten</key>
|
||||
<key alias="login">Inloggen</key>
|
||||
<key alias="logoff">Afmelden</key>
|
||||
<key alias="logout">Afmelden</key>
|
||||
<key alias="logoff">Uitloggen</key>
|
||||
<key alias="logout">Uitloggen</key>
|
||||
<key alias="macro">Macro</key>
|
||||
<key alias="move">Verplaatsen</key>
|
||||
<key alias="more">Meer</key>
|
||||
<key alias="mandatory">Verplicht</key>
|
||||
<key alias="move">Verplaats</key>
|
||||
<key alias="more">meer</key>
|
||||
<key alias="name">Naam</key>
|
||||
<key alias="new">Nieuw</key>
|
||||
<key alias="next">Volgende</key>
|
||||
<key alias="no">Nee</key>
|
||||
<key alias="of">van</key>
|
||||
<key alias="ok">Ok</key>
|
||||
<key alias="open">Openen</key>
|
||||
<key alias="of">of</key>
|
||||
<key alias="ok">OK</key>
|
||||
<key alias="open">Open</key>
|
||||
<key alias="or">of</key>
|
||||
<key alias="password">Wachtwoord</key>
|
||||
<key alias="path">Pad</key>
|
||||
<key alias="placeHolderID">Placeholder ID</key>
|
||||
<key alias="pleasewait">Een ogenblik geduld a.u.b.</key>
|
||||
<key alias="pleasewait">Een ogenblik geduld aub...</key>
|
||||
<key alias="previous">Vorige</key>
|
||||
<key alias="properties">Eigenschappen</key>
|
||||
<key alias="reciept">E-mail om formulier te ontvangen</key>
|
||||
<key alias="reciept">Email om formulier resultaten te ontvangen</key>
|
||||
<key alias="recycleBin">Prullenbak</key>
|
||||
<key alias="remaining">Overgebleven</key>
|
||||
<key alias="rename">Hernoemen</key>
|
||||
<key alias="recycleBinEmpty">De prullenbak is leeg</key>
|
||||
<key alias="remaining">Overblijvend</key>
|
||||
<key alias="rename">Hernoem</key>
|
||||
<key alias="renew">Vernieuw</key>
|
||||
<key alias="required" version="7.0">Verplicht</key>
|
||||
<key alias="retry">Opnieuw proberen</key>
|
||||
<key alias="rights">Rechten</key>
|
||||
<key alias="search">Zoek</key>
|
||||
<key alias="search">Zoeken</key>
|
||||
<key alias="searchNoResult">We konden helaas niet vinden wat je zocht</key>
|
||||
<key alias="server">Server</key>
|
||||
<key alias="show">Tonen</key>
|
||||
<key alias="showPageOnSend">Toon pagina bij versturen</key>
|
||||
<key alias="size">Formaat</key>
|
||||
<key alias="sort">Sorteren</key>
|
||||
<key alias="submit">Submit</key> <!-- TODO: Translate this -->
|
||||
<key alias="type">Type</key>
|
||||
<key alias="typeToSearch">Type om te zoeken...</key>
|
||||
<key alias="show">Toon</key>
|
||||
<key alias="showPageOnSend">Toon pagina na verzenden</key>
|
||||
<key alias="size">Grootte</key>
|
||||
<key alias="sort">Sorteer</key>
|
||||
<key alias="submit">Verstuur</key>
|
||||
<key alias="type">Typen</key>
|
||||
<key alias="typeToSearch">Typ om te zoeken...</key>
|
||||
<key alias="up">Omhoog</key>
|
||||
<key alias="update">Bijwerken</key>
|
||||
<key alias="update">Update</key>
|
||||
<key alias="upgrade">Upgrade</key>
|
||||
<key alias="upload">Upload</key>
|
||||
<key alias="url">Url</key>
|
||||
<key alias="user">Gebruiker</key>
|
||||
<key alias="username">Gebruikersnaam</key>
|
||||
<key alias="value">Waarde</key>
|
||||
<key alias="view">Toon</key>
|
||||
<key alias="view">Bekijk</key>
|
||||
<key alias="welcome">Welkom...</key>
|
||||
<key alias="width">Breedte</key>
|
||||
<key alias="yes">Ja</key>
|
||||
<key alias="folder">Map</key>
|
||||
<key alias="reorder">Reorder</key>
|
||||
<key alias="reorderDone">I am done reordering</key>
|
||||
|
||||
<key alias="searchResults">Zoekresultaten</key>
|
||||
<key alias="reorder">Herschik</key>
|
||||
<key alias="reorderDone">Ik ben klaar met herschikken</key>
|
||||
<key alias="preview">Voorvertoning</key>
|
||||
<key alias="changePassword">Wachtwoord veranderen</key>
|
||||
<key alias="to">naar</key>
|
||||
<key alias="listView">Lijstweergave</key>
|
||||
<key alias="saving">Aan het opslaan...</key>
|
||||
<key alias="current">huidig</key>
|
||||
<key alias="embed">Embed</key>
|
||||
<key alias="selected">geselecteerd</key>
|
||||
</area>
|
||||
<area alias="colors">
|
||||
<key alias="black">Zwart</key>
|
||||
<key alias="green">Groen</key>
|
||||
<key alias="yellow">Geel</key>
|
||||
<key alias="orange">Oranje</key>
|
||||
<key alias="blue">Blauw</key>
|
||||
<key alias="red">Rood</key>
|
||||
</area>
|
||||
<area alias="shortcuts">
|
||||
<key alias="addTab">Tab toevoegen</key>
|
||||
<key alias="addProperty">Property toevoegen</key>
|
||||
<key alias="addEditor">Editor toevoegen</key>
|
||||
<key alias="addTemplate">Template toevoegen</key>
|
||||
<key alias="addChildNode">Child node toevoegen</key>
|
||||
<key alias="addChild">Child toevoegen</key>
|
||||
|
||||
<key alias="editDataType">Data type bewerken</key>
|
||||
|
||||
<key alias="navigateSections">Secties navigeren</key>
|
||||
|
||||
<key alias="shortcut">Shortcuts</key>
|
||||
<key alias="showShortcuts">Toon shortcuts</key>
|
||||
|
||||
<key alias="toggleListView">Toggle lijstweergave</key>
|
||||
<key alias="toggleAllowAsRoot">Toggle toestaan op root-niveau</key>
|
||||
</area>
|
||||
<area alias="graphicheadline">
|
||||
<key alias="backgroundcolor">Achtergrondkleur</key>
|
||||
@@ -528,6 +630,57 @@ Echter, Runway biedt een gemakkelijke basis om je snel op weg te helpen. Als je
|
||||
<key alias="watch">Bekijken</key>
|
||||
<key alias="welcomeIntro"><![CDATA[Deze wizard helpt u met het configureren van <strong>Umbraco %0%</strong> voor een nieuwe installatie of een upgrade van versie 3.0. <br /><br /> Druk op <strong>"volgende"</strong> om de wizard te starten.]]></key>
|
||||
</area>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<area alias="language">
|
||||
<key alias="cultureCode">Cultuurcode</key>
|
||||
<key alias="displayName">Cultuurnaam</key>
|
||||
@@ -543,12 +696,22 @@ Echter, Runway biedt een gemakkelijke basis om je snel op weg te helpen. Als je
|
||||
<key alias="greeting3">Fijne woensdag</key>
|
||||
<key alias="greeting4">Fijne donderdag</key>
|
||||
<key alias="greeting5">Fijne vrijdag</key>
|
||||
<key alias="greeting6">Fijne zaterdag</key>
|
||||
|
||||
<key alias="greeting6">Fijne zaterdag</key>
|
||||
<key alias="instruction">log hieronder in</key>
|
||||
<key alias="signInWith">Inloggen met</key>
|
||||
<key alias="timeout">Sessie is verlopen</key>
|
||||
|
||||
<key alias="bottomText"><![CDATA[<p style="text-align:right;">© 2001 - %0% <br /><a href="http://umbraco.com" style="text-decoration: none" target="_blank">umbraco.com</a></p>]]></key>
|
||||
<key alias="forgottenPassword">Wachtwoord vergeten?</key>
|
||||
<key alias="forgottenPasswordInstruction">Er zal een email worden gestuurd naar het emailadres van jouw account. Hierin staat een link om je wachtwoord te resetten</key>
|
||||
<key alias="requestPasswordResetConfirmation">Een email met daarin de wachtwoord reset uitleg zal worden gestuurd als het emailadres in onze database voorkomt.</key>
|
||||
<key alias="returnToLogin">Terug naar loginformulier</key>
|
||||
<key alias="setPasswordInstruction">Geeft alsjeblieft een nieuw wachtwoord op</key>
|
||||
<key alias="setPasswordConfirmation">Je wachtwoord is aangepast</key>
|
||||
<key alias="resetCodeExpired">De link die je hebt aangeklikt is niet (meer) geldig.</key>
|
||||
<key alias="resetPasswordEmailCopySubject">Umbraco: Wachtwoord Reset</key>
|
||||
<key alias="resetPasswordEmailCopyFormat">
|
||||
<![CDATA[<p>De gebruikersnaam om in te loggen bij jouw Umbraco omgeving is: <strong>%0%</strong></p><p>Klik <a href="%1%"><strong>hier</strong></a> om je wachtwoord te resetten of knip/plak deze URL in je browser:</p><p><em>%1%</em></p>]]>
|
||||
</key>
|
||||
</area>
|
||||
<area alias="main">
|
||||
<key alias="dashboard">Dashboard</key>
|
||||
@@ -646,6 +809,15 @@ Echter, Runway biedt een gemakkelijke basis om je snel op weg te helpen. Als je
|
||||
<key alias="packageVersion">Package versie</key>
|
||||
<key alias="packageVersionHistory">Package versiehistorie</key>
|
||||
<key alias="viewPackageWebsite">Bekijk de package website</key>
|
||||
<key alias="packageAlreadyInstalled">Package reeds geinstalleerd</key>
|
||||
<key alias="targetVersionMismatch">Deze package kan niet worden geinstalleerd omdat minimaal Umbraco versie %0% benodigd is.</key>
|
||||
<key alias="installStateUninstalling">Aan het deinstalleren...</key>
|
||||
<key alias="installStateDownloading">Aan het downloaden...</key>
|
||||
<key alias="installStateImporting">Aan het importeren...</key>
|
||||
<key alias="installStateInstalling">Aan het installeren...</key>
|
||||
<key alias="installStateRestarting">Aan het herstarten, een ongenblik geduld aub...</key>
|
||||
<key alias="installStateComplete">Geinstalleerd! Je browser zal nu automatisch ververst worden...</key>
|
||||
<key alias="installStateCompleted">Kruk op "finish" om de installate te voltooien en de pagina te verversen.</key>
|
||||
</area>
|
||||
<area alias="paste">
|
||||
<key alias="doNothing">Plakken met alle opmaak (Niet aanbevolen)</key>
|
||||
@@ -677,13 +849,18 @@ Echter, Runway biedt een gemakkelijke basis om je snel op weg te helpen. Als je
|
||||
%0% kan niet worden gepubliceerd omdat het item is gepland voor release.
|
||||
]]>
|
||||
</key>
|
||||
<key alias="contentPublishedFailedExpired"><![CDATA[
|
||||
%0% kon niet gepubliceerd worden omdat het item niet meer geldig is.
|
||||
]]></key>
|
||||
<key alias="contentPublishedFailedInvalid"><![CDATA[
|
||||
%0% kan niet worden gepubliceerd, omdat de eigenschappen:%1% de validatieregels niet hebben doorstaan.
|
||||
]]></key>
|
||||
<key alias="contentPublishedFailedByEvent"><![CDATA[
|
||||
%0% kon niet worden gepubliceerd doordat een 3rd party extensie het heeft geannuleerd.
|
||||
|
||||
%0% kon niet worden gepubliceerd doordat een 3rd party extensie het heeft geannuleerd.
|
||||
]]></key>
|
||||
<key alias="contentPublishedFailedByParent"><![CDATA[
|
||||
%0% kon niet gepubliceerd worden, omdat de parent pagina niet gepubliceerd is.
|
||||
]]></key>
|
||||
<key alias="includeUnpublished">Inclusief ongepubliceerde kinderen</key>
|
||||
<key alias="inProgress">Publicatie in uitvoering - even geduld...</key>
|
||||
<key alias="inProgressCounter">%0% van %1% pagina’s zijn gepubliceerd...</key>
|
||||
@@ -698,16 +875,13 @@ Echter, Runway biedt een gemakkelijke basis om je snel op weg te helpen. Als je
|
||||
<key alias="noColors">Je hebt geen goedgekeurde kleuren geconfigureerd</key>
|
||||
</area>
|
||||
<area alias="relatedlinks">
|
||||
<key alias="addExternal">Externe link toevoegen</key>
|
||||
<key alias="addInternal">Interne link toevoegen</key>
|
||||
<key alias="addlink">Toevoegen</key>
|
||||
<key alias="caption">Bijschrift</key>
|
||||
<key alias="internalPage">Interne pagina</key>
|
||||
<key alias="linkurl">URL</key>
|
||||
<key alias="modeDown">Verplaats omlaag</key>
|
||||
<key alias="modeUp">Verplaats omhoog</key>
|
||||
<key alias="newWindow">Open in nieuw venster</key>
|
||||
<key alias="removeLink">Verwijder link</key>
|
||||
<key alias="enterExternal">Externe link toevoegen</key>
|
||||
<key alias="chooseInternal">Interne link toevoegen</key>
|
||||
<key alias="caption">Bijschrift</key>
|
||||
<key alias="link">Link</key>
|
||||
<key alias="newWindow">In een nieuw venster openen</key>
|
||||
<key alias="captionPlaceholder">Voer het bijschrijft in</key>
|
||||
<key alias="externalLinkPlaceholder">Voer de link in</key>
|
||||
</area>
|
||||
<area alias="imagecropper">
|
||||
<key alias="reset">Reset</key>
|
||||
@@ -736,13 +910,17 @@ Echter, Runway biedt een gemakkelijke basis om je snel op weg te helpen. Als je
|
||||
<key alias="settings">Instellingen</key>
|
||||
<key alias="statistics">Statistieken</key>
|
||||
<key alias="translation">Vertaling</key>
|
||||
<key alias="users">Gebruikers</key>
|
||||
<key alias="contour" version="4.0">Umbraco Contour</key>
|
||||
|
||||
<key alias="users">Gebruikers</key>
|
||||
<key alias="help" version="7.0">Help</key>
|
||||
<key alias="forms">Formulieren</key>
|
||||
<key alias="analytics">Analytics</key>
|
||||
</area>
|
||||
<area alias="help">
|
||||
<key alias="goTo">ga naar</key>
|
||||
<key alias="helpTopicsFor">Help onderwerpen voor</key>
|
||||
<key alias="videoChaptersFor">Video's voor</key>
|
||||
<key alias="theBestUmbracoVideoTutorials">De beste Umbraco video tutorials</key>
|
||||
</area>
|
||||
<area alias="settings">
|
||||
<key alias="defaulttemplate">Standaard template</key>
|
||||
<key alias="dictionary editor egenskab">Woordenboek sleutel</key>
|
||||
@@ -762,6 +940,7 @@ Echter, Runway biedt een gemakkelijke basis om je snel op weg te helpen. Als je
|
||||
<key alias="noPropertiesDefinedOnTab">Geen eigenschappen gedefinieerd op dit tabblad. Klik op de link "voeg een nieuwe eigenschap" aan de bovenkant om een nieuwe eigenschap te creëren.</key>
|
||||
<key alias="masterDocumentType">Master Document Type</key>
|
||||
<key alias="createMatchingTemplate">Maak een bijbehorend template</key>
|
||||
<key alias="addIcon">Icon toevoegen</key>
|
||||
</area>
|
||||
<area alias="sort">
|
||||
<key alias="sortOrder">Sort order</key>
|
||||
@@ -771,7 +950,13 @@ Echter, Runway biedt een gemakkelijke basis om je snel op weg te helpen. Als je
|
||||
<key alias="sortPleaseWait"><![CDATA[Een ogenblik geduld. Paginas worden gesorteerd, dit kan even duren.<br/> <br/> Sluit dit venster niet tijdens het sorteren]]></key>
|
||||
</area>
|
||||
<area alias="speechBubbles">
|
||||
<key alias="contentPublishedFailedByEvent">Publicatie werd geannuleerd door een 3rd party plug-in</key>
|
||||
<key alias="validationFailedHeader">Validatie</key>
|
||||
<key alias="validationFailedMessage">Validatiefouten moeten worden opgelost voor dit item kan worden opgeslagen</key>
|
||||
<key alias="operationFailedHeader">Mislukt</key>
|
||||
<key alias="invalidUserPermissionsText">Wegens onvoldoende rechten kon deze handeling kon niet worden uitegevoerd </key>
|
||||
<key alias="operationCancelledHeader">Geannuleerd</key>
|
||||
<key alias="operationCancelledText">Uitvoering is g eannuleerd door de plugin van een 3e partij</key>
|
||||
<key alias="contentPublishedFailedByEvent">Publicatie werd geannuleerd doordeeen plugin van een 3e partij</key>
|
||||
<key alias="contentTypeDublicatePropertyType">Eigenschappen type bestaat al</key>
|
||||
<key alias="contentTypePropertyTypeCreated">Eigenschappen type aangemaakt</key>
|
||||
<key alias="contentTypePropertyTypeCreatedText"><![CDATA[Naam: %0% <br /> Data type: %1%]]></key>
|
||||
@@ -806,6 +991,8 @@ Echter, Runway biedt een gemakkelijke basis om je snel op weg te helpen. Als je
|
||||
<key alias="fileSavedHeader">Bestand opgeslagen</key>
|
||||
<key alias="fileSavedText">Bestand opgeslagen zonder fouten</key>
|
||||
<key alias="languageSaved">Taal opgeslagen</key>
|
||||
<key alias="mediaTypeSavedHeader">Media Type opgeslagen</key>
|
||||
<key alias="memberTypeSavedHeader">Member Type opgeslagen</key>
|
||||
<key alias="pythonErrorHeader">Python script niet opgeslagen</key>
|
||||
<key alias="pythonErrorText">Python script kon niet worden opgeslagen door een fout</key>
|
||||
<key alias="pythonSavedHeader">Python script opeslagen!</key>
|
||||
@@ -824,6 +1011,11 @@ Echter, Runway biedt een gemakkelijke basis om je snel op weg te helpen. Als je
|
||||
<key alias="partialViewSavedText">Partial view opgeslagen zonder fouten!</key>
|
||||
<key alias="partialViewErrorHeader">Partial view niet opgeslagen</key>
|
||||
<key alias="partialViewErrorText">Er is een fout opgetreden bij het opslaan van het bestand.</key>
|
||||
<key alias="scriptSavedHeader">Script view opgeslagen</key>
|
||||
<key alias="scriptSavedText">Script view opgeslagen zonder fouten!</key>
|
||||
<key alias="scriptErrorHeader">Script view niet opgeslagen</key>
|
||||
<key alias="scriptErrorText">Er is een fout opgetreden bij het opslaan van dit bestand.</key>
|
||||
<key alias="cssErrorText">Er is een fout opgetreden bij het opslaan van dit bestand.</key>
|
||||
</area>
|
||||
<area alias="stylesheet">
|
||||
<key alias="aliasHelp">Gebruik CSS syntax bijv: h1, .redHeader, .blueTex</key>
|
||||
@@ -846,15 +1038,15 @@ Echter, Runway biedt een gemakkelijke basis om je snel op weg te helpen. Als je
|
||||
</area>
|
||||
<area alias="grid">
|
||||
<key alias="insertControl">Item toevoegen</key>
|
||||
<key alias="chooseLayout">Choose a layout</key>
|
||||
<key alias="addRows">Een rij aan de lay-out toevoegen</key>
|
||||
<key alias="addElement"><![CDATA[Klik om te starten op het <i class="icon icon-add blue"></i> teken onderaan en voeg je eerste item toe]]></key>
|
||||
<key alias="chooseLayout">Kies de indeling</key>
|
||||
<key alias="addRows">Kies een indeling voor deze pagina om content toe te kunnen voegen</key>
|
||||
<key alias="addElement"><![CDATA[<i class="icon icon-add blue"></i> Plaats een (extra) content blok]]></key>
|
||||
<key alias="dropElement">Drop content</key>
|
||||
<key alias="settingsApplied">Settings applied</key>
|
||||
|
||||
<key alias="contentNotAllowed">This content is not allowed here</key>
|
||||
<key alias="contentAllowed">This content is allowed here</key>
|
||||
<key alias="settingsApplied">Instellingen toegepast</key>
|
||||
|
||||
<key alias="contentNotAllowed">Deze content is hier niet toegestaan</key>
|
||||
<key alias="contentAllowed">Deze content is hier toegestaan</key>
|
||||
|
||||
<key alias="clickToEmbed">Klik om een item te embedden</key>
|
||||
<key alias="clickToInsertImage">Klik om een afbeelding in te voegen</key>
|
||||
<key alias="placeholderImageCaption">Afbeelding ondertitel...</key>
|
||||
@@ -883,7 +1075,79 @@ Echter, Runway biedt een gemakkelijke basis om je snel op weg te helpen. Als je
|
||||
|
||||
<key alias="allowAllEditors">Alle editors toelaten</key>
|
||||
<key alias="allowAllRowConfigurations">Alle rijconfiguraties toelaten</key>
|
||||
<key alias="setAsDefault">Instellen als standaard</key>
|
||||
<key alias="chooseExtra">Kies extra</key>
|
||||
<key alias="chooseDefault">Kies standaard</key>
|
||||
<key alias="areAdded">zijn toegevoegd</key>
|
||||
</area>
|
||||
|
||||
<area alias="contentTypeEditor">
|
||||
<key alias="compositions">Composities</key>
|
||||
<key alias="noTabs">Er zijn nog geen tabs toegevoegd</key>
|
||||
<key alias="addNewTab">Voeg een nieuwe tab toe</key>
|
||||
<key alias="addAnotherTab">Voeg nog een tab toe</key>
|
||||
<key alias="inheritedFrom">Inherited van</key>
|
||||
<key alias="addProperty">Voeg property toe</key>
|
||||
<key alias="requiredLabel">Verplicht label</key>
|
||||
|
||||
<key alias="enableListViewHeading">Zet list view aan</key>
|
||||
<key alias="enableListViewDescription">Laat de child nodes van het content item zien als een sorteer- en doorzoekbare lijstweergave zien. Deze child nodes worden dan niet in de boomstructuur getoond.</key>
|
||||
|
||||
<key alias="allowedTemplatesHeading">Toegestane Templates</key>
|
||||
<key alias="allowedTemplatesDescription">Kies welke templates toegestaan zijn om door de editors op dit content-type gebruikt te worden</key>
|
||||
<key alias="allowAsRootHeading">Sta toe op root-niveau</key>
|
||||
<key alias="allowAsRootDescription">Sta editors toe om content van dit type aan te maken op root-niveau</key>
|
||||
<key alias="allowAsRootCheckbox">Ja - sta content van dit type toe op root-niveau</key>
|
||||
|
||||
<key alias="childNodesHeading">Toegestane child node types</key>
|
||||
<key alias="childNodesDescription">Sta contetn van een bepaalde type toe om onder dit type aangemaakt te kunnen worden</key>
|
||||
|
||||
<key alias="chooseChildNode">Kies child node</key>
|
||||
<key alias="compositionsDescription">Overerfde tabs en properties van een bestaand document-type. Nieuwe tabs worden toegevoegd aan het huidige document-type of samengevoegd als een tab met de identieke naam al bestaat.</key>
|
||||
<key alias="compositionInUse">Dit content-type wordt gebruikt in een compositie en kan daarom niet zelf een compositie worden.</key>
|
||||
<key alias="noAvailableCompositions">Er zijn geen content-typen beschikbaar om als compositie te gebruiken.</key>
|
||||
|
||||
<key alias="availableEditors">Beschikbare editors</key>
|
||||
<key alias="reuse">Herbruik</key>
|
||||
<key alias="editorSettings">Editor instellingen</key>
|
||||
|
||||
<key alias="configuration">Configuratie</key>
|
||||
|
||||
<key alias="yesDelete">Ja, verwijder</key>
|
||||
|
||||
<key alias="movedUnderneath">is naar onder geplaatst</key>
|
||||
<key alias="copiedUnderneath">is naar onder gecopierd</key>
|
||||
<key alias="folderToMove">Selecteer de map om te verplaatsen</key>
|
||||
<key alias="folderToCopy">Selecteer de map om te kopieren</key>
|
||||
<key alias="structureBelow">naar de boomstructuur onder</key>
|
||||
|
||||
<key alias="allDocumentTypes">Alle Document types</key>
|
||||
<key alias="allDocuments">Alle documenten</key>
|
||||
<key alias="allMediaItems">Alle media items</key>
|
||||
|
||||
<key alias="usingThisDocument">die gebruik maken van dit document type zullen permanent verwijderd worden. Bevestig aub dat je deze ook wilt verwijderen.</key>
|
||||
<key alias="usingThisMedia">die gebruik maken van dit media type zullen permanent verwijderd worden. Bevestig aub dat je deze ook wilt verwijderen.</key>
|
||||
<key alias="usingThisMember">die gebruik maken van dit member type zullen permanent verwijderd worden. Bevestig aub dat je deze ook wilt verwijderen.</key>
|
||||
|
||||
<key alias="andAllDocuments">en alle documenten van dit type</key>
|
||||
<key alias="andAllMediaItems">en alle media items van dit type</key>
|
||||
<key alias="andAllMembers">en alle leden van dit type</key>
|
||||
|
||||
<key alias="thisEditorUpdateSettings">die gebruik maken van deze editor zullen geupdate worden met deze nieuwe instellingen</key>
|
||||
|
||||
<key alias="memberCanEdit">Lid kan bewerken</key>
|
||||
<key alias="showOnMemberProfile">Toon in het profiel van leden</key>
|
||||
<key alias="tabHasNoSortOrder">tab heeft geen sorteervolgorde</key>
|
||||
</area>
|
||||
|
||||
<area alias="modelsBuilder">
|
||||
<key alias="buildingModels">Models aan het gereneren</key>
|
||||
<key alias="waitingMessage">dit kan enige tijd duren, geduld aub</key>
|
||||
<key alias="modelsGenerated">Models gegenereerd</key>
|
||||
<key alias="modelsGeneratedError">Models konden niet gegenereerd worden</key>
|
||||
<key alias="modelsExceptionInUlog">Models generatie is mislukt, kijk in de Umbraco log voor details</key>
|
||||
</area>
|
||||
|
||||
<area alias="templateEditor">
|
||||
<key alias="alternativeField">Alternatief veld</key>
|
||||
<key alias="alternativeText">Alternatieve tekst</key>
|
||||
@@ -916,7 +1180,8 @@ Echter, Runway biedt een gemakkelijke basis om je snel op weg te helpen. Als je
|
||||
</area>
|
||||
<area alias="translation">
|
||||
<key alias="assignedTasks">Taken aan jou toegewezen</key>
|
||||
<key alias="assignedTasksHelp"><![CDATA[Onderstaande lijst toont vertalingstaken aan jou toegewezen. Om een meer gedetailleerd overzicht te zien, met comments, klik op "Details" of de naam van de pagina. Je kan ook de pagina direct downloaden als XML door te klikken op "Download Xml".
|
||||
<key alias="assignedTasksHelp"><![CDATA[Onderstaande lijst toont vertalingstaken aan jou toegewezen. Om een meer gedetailleerd overzicht te zien, met comments, klik op "Details" of de naam van de pagina.
|
||||
Je kan ook de pagina direct downloaden als XML door te klikken op "Download Xml".
|
||||
Om een vertalingstaak te sluiten, ga aub naar het detailoverzicht en klik op de "Sluit" knop.
|
||||
]]></key>
|
||||
<key alias="closeTask">Sluit taak</key>
|
||||
@@ -932,18 +1197,24 @@ Om een vertalingstaak te sluiten, ga aub naar het detailoverzicht en klik op de
|
||||
Dit is een geautomatiseerde mail om u op de hoogte te brengen dat document '%1%'
|
||||
is aangevraagd voor vertaling naar '%5%' door %2%.
|
||||
|
||||
Ga naar http://%3%/Umbraco/translation/default.aspx?id=%4% om te bewerken.
|
||||
Ga naar http://%3%/translation/details.aspx?id=%4% om te bewerken.
|
||||
Of log in bij Umbraco om een overzicht te krijgen van al jouw vertalingen.
|
||||
|
||||
Een prettige dag!
|
||||
|
||||
Met vriendelijke groet!
|
||||
|
||||
Dit is een bericht van uw Content Management Systeem.
|
||||
|
||||
|
||||
De Umbraco Robot
|
||||
]]></key>
|
||||
<key alias="mailSubject">[%0%] Vertaalopdracht voor %1%</key>
|
||||
<key alias="noTranslators">Geen vertaal-gebruikers gevonden. Maak eerst een vertaal-gebruiker aan voordat je pagina's voor vertaling verstuurd</key>
|
||||
<key alias="ownedTasks">Taken aangemaakt door jou</key>
|
||||
<key alias="ownedTasksHelp"><![CDATA[De lijst hieronder toont pagina's <strong>die je aanmaakte</strong>. Om een detailweergave met opmerkingen te zien, klik op "Detail" of op de paginanaam. Je kan ook de pagina in XML-formaat downloaden door op de "Download XML"-link te klikken. Om een vertalingstaak te sluiten, klik je op de "Sluiten"-knop in detailweergave.]]></key>
|
||||
<key alias="ownedTasksHelp"><![CDATA[De lijst hieronder toont pagina's <strong>die je aanmaakte</strong>.
|
||||
Om een detailweergave met opmerkingen te zien, klik op "Detail" of op de paginanaam.
|
||||
Je kan ook de pagina in XML-formaat downloaden door op de "Download XML"-link te klikken.
|
||||
Om een vertalingstaak te sluiten, klik je op de "Sluiten"-knop in detailweergave.]]></key>
|
||||
<key alias="pageHasBeenSendToTranslation">De pagina '%0%' is verstuurd voor vertaling</key>
|
||||
<key alias="noLanguageSelected">Kies de taal waarin deze contetn vertaald moet worden</key>
|
||||
<key alias="sendToTranslate">Stuur voor vertaling</key>
|
||||
<key alias="taskAssignedBy">Toegewezen door</key>
|
||||
<key alias="taskOpened">Taak geopend</key>
|
||||
@@ -973,7 +1244,8 @@ Om een vertalingstaak te sluiten, ga aub naar het detailoverzicht en klik op de
|
||||
<key alias="memberGroups">Ledengroepen</key>
|
||||
<key alias="memberRoles">Rollen</key>
|
||||
<key alias="memberTypes">Ledentypes</key>
|
||||
<key alias="documentTypes">Documenttypes</key>
|
||||
<key alias="documentTypes">Documenttypen</key>
|
||||
<key alias="relationTypes">RelatieTypen</key>
|
||||
<key alias="packager">Packages</key>
|
||||
<key alias="packages">Packages</key>
|
||||
<key alias="python">Python-bestanden</key>
|
||||
@@ -985,6 +1257,7 @@ Om een vertalingstaak te sluiten, ga aub naar het detailoverzicht en klik op de
|
||||
<key alias="stylesheets">Stylesheets</key>
|
||||
<key alias="templates">Sjablonen</key>
|
||||
<key alias="xslt">XSLT Bestanden</key>
|
||||
<key alias="analytics">Analytics</key>
|
||||
</area>
|
||||
<area alias="update">
|
||||
<key alias="updateAvailable">Nieuwe update beschikbaar</key>
|
||||
@@ -1010,6 +1283,7 @@ Om een vertalingstaak te sluiten, ga aub naar het detailoverzicht en klik op de
|
||||
<key alias="mediastartnode">Startnode in Mediabibliotheek</key>
|
||||
<key alias="modules">Secties</key>
|
||||
<key alias="noConsole">Blokkeer Umbraco toegang</key>
|
||||
<key alias="oldPassword">Oude wachtwoord</key>
|
||||
<key alias="password">Wachtwoord</key>
|
||||
<key alias="resetPassword">Reset wachtwoord</key>
|
||||
<key alias="passwordChanged">Je wachtwoord is veranderd!</key>
|
||||
@@ -1030,10 +1304,138 @@ Om een vertalingstaak te sluiten, ga aub naar het detailoverzicht en klik op de
|
||||
<key alias="usertype">Gebruikerstype</key>
|
||||
<key alias="userTypes">Gebruikerstypes</key>
|
||||
<key alias="writer">Auteur</key>
|
||||
<key alias="translator">Vertaler</key>
|
||||
<key alias="change">Wijzig</key>
|
||||
|
||||
<key alias="yourProfile" version="7.0">Je profiel</key>
|
||||
<key alias="yourHistory" version="7.0">Je recente historie</key>
|
||||
<key alias="sessionExpires" version="7.0">Sessie verloopt over</key>
|
||||
</area>
|
||||
<area alias="validation">
|
||||
<key alias="validation">Validatie</key>
|
||||
<key alias="validateAsEmail">Valideer als email</key>
|
||||
<key alias="validateAsNumber">Valideer als nummer</key>
|
||||
<key alias="validateAsUrl">Valideer als Url</key>
|
||||
<key alias="enterCustomValidation">...of gebruik custom validatie</key>
|
||||
<key alias="fieldIsMandatory">Veld is verplicht</key>
|
||||
</area>
|
||||
<area alias="healthcheck">
|
||||
<!-- The following keys get these tokens passed in:
|
||||
0: Current value
|
||||
1: Recommended value
|
||||
2: XPath
|
||||
3: Configuration file path
|
||||
-->
|
||||
<key alias="checkSuccessMessage">Waarde is insteld naar the aanbevolen waarde: '%0%'.</key>
|
||||
<key alias="rectifySuccessMessage">Waarde was '%1%' voor XPath '%2%' in configuratie bestand '%3%'.</key>
|
||||
<key alias="checkErrorMessageDifferentExpectedValue">De verwachtte waarde voor '%2%' is '%1%' in configuratie bestand '%3%', maar is '%0%'.</key>
|
||||
<key alias="checkErrorMessageUnexpectedValue">Onverwachte waarde '%0%' gevonden voor '%2%' in configuratie bestand '%3%'.</key>
|
||||
|
||||
<!-- The following keys get these tokens passed in:
|
||||
0: Current value
|
||||
1: Recommended value
|
||||
-->
|
||||
<key alias="customErrorsCheckSuccessMessage">Custom foutmeldingen zijn ingesteld op '%0%'.</key>
|
||||
<key alias="customErrorsCheckErrorMessage">Custom foutmeldingen zijn momenteel '%0%'. Wij raden aan deze aan te passen naar '%1%' voor livegang.</key>
|
||||
<key alias="customErrorsCheckRectifySuccessMessage">Custom foutmeldingen aangepast naar '%0%'.</key>
|
||||
|
||||
<key alias="macroErrorModeCheckSuccessMessage">Macro foutmeldingen zijn ingesteld op'%0%'.</key>
|
||||
<key alias="macroErrorModeCheckErrorMessage">Macro foutmeldingen zijn ingesteld op '%0%'. Dit zal er voor zorgen dat bepaalde, of alle, pagina's van de website niet geladen kunnen worden als er errors in een Macro zitten. Corrigeren zal deze waarde aanpassen naar '%1%'.</key>
|
||||
<key alias="macroErrorModeCheckRectifySuccessMessage">Macro foutmeldingen zijn aangepast naar '%0%'.</key>
|
||||
|
||||
<!-- The following keys get these tokens passed in:
|
||||
0: Current value
|
||||
1: Recommended value
|
||||
2: Server version
|
||||
-->
|
||||
<key alias="trySkipIisCustomErrorsCheckSuccessMessage">Try Skip IIS Custom foutmeldingen is ingesteld op '%0%'. IIS versie '%1%' wordt gebruikt.</key>
|
||||
<key alias="trySkipIisCustomErrorsCheckErrorMessage">Try Skip IIS Custom foutmeldingen is ingesteld op '%0%'. Het wordt voor de gebruikte IIS versie (%2%) aangeraden deze in te stellen op '%1%'.</key>
|
||||
<key alias="trySkipIisCustomErrorsCheckRectifySuccessMessage">Try Skip IIS Custom foutmeldingen ingesteld op '%0%'.</key>
|
||||
|
||||
<!-- The following keys get predefined tokens passed in that are not all the same, like above -->
|
||||
<key alias="configurationServiceFileNotFound">Het volgende bestand bestaat niet: '%0%'.</key>
|
||||
<key alias="configurationServiceNodeNotFound"><![CDATA[<strong>'%0%'</strong> kon niet gevonden worden in configuratie bestand <strong>'%1%'</strong>.]]></key>
|
||||
<key alias="configurationServiceError">Er is een fout opgetreden. Bekijk de log file voor de volledige fout: %0%.</key>
|
||||
|
||||
<key alias="xmlDataIntegrityCheckMembers">Members - Totaal XML: %0%, Totaal: %1%, Total incorrect: %2%</key>
|
||||
<key alias="xmlDataIntegrityCheckMedia">Media - Totaal XML: %0%, Totaal: %1%, Total incorrect: %2%</key>
|
||||
<key alias="xmlDataIntegrityCheckContent">Content - Totaal XML: %0%, Totaal gepubliceerd: %1%, Total incorrect: %2%</key>
|
||||
|
||||
<key alias="httpsCheckValidCertificate">Het cerficaat van de website is ongeldig.</key>
|
||||
<key alias="httpsCheckInvalidCertificate">Cerficaat validatie foutmelding: '%0%'</key>
|
||||
<key alias="httpsCheckInvalidUrl">Fout bij pingen van URL %0% - '%1%'</key>
|
||||
<key alias="httpsCheckIsCurrentSchemeHttps">De site wordt momenteel %0% bekeken via HTTPS.</key>
|
||||
<key alias="httpsCheckConfigurationRectifyNotPossible">De appSetting 'umbracoUseSSL' in web.config staat op 'false'. Indien HTTPS gebruikt wordt moet deze op 'true' staan.</key>
|
||||
<key alias="httpsCheckConfigurationCheckResult">De appSetting 'umbracoUseSSL' in web.config is ingesteld op '%0%'. Cookies zijn %1% ingesteld als secure.</key>
|
||||
<key alias="httpsCheckEnableHttpsError">De 'umbracoUseSSL' waarde in web.config kon niet aangepast worden. Foutmelding: %0%</key>
|
||||
|
||||
<!-- The following keys don't get tokens passed in -->
|
||||
<key alias="httpsCheckEnableHttpsButton">HTTPS inschakelen</key>
|
||||
<key alias="httpsCheckEnableHttpsDescription">Zet in de appSettings van de web.config de umbracoSSL instelling op 'true'.</key>
|
||||
<key alias="httpsCheckEnableHttpsSuccess">De appSetting 'umbracoUseSSL' is nu ingesteld op 'true', cookies zullen als 'secure' worden aangemerkt.</key>
|
||||
|
||||
<key alias="rectifyButton">Fix</key>
|
||||
<key alias="cannotRectifyShouldNotEqual">Cannot fix a check with a value comparison type of 'ShouldNotEqual'.</key>
|
||||
<key alias="cannotRectifyShouldEqualWithValue">Cannot fix a check with a value comparison type of 'ShouldEqual' with a provided value.</key>
|
||||
<key alias="valueToRectifyNotProvided">Value to fix check not provided.</key>
|
||||
|
||||
<key alias="compilationDebugCheckSuccessMessage">Debug compiliate mode staat uit.</key>
|
||||
<key alias="compilationDebugCheckErrorMessage">Debug compiliate mode staat momenteel aan. Wij raden aan deze instelling uit te zetten voor livegang.</key>
|
||||
<key alias="compilationDebugCheckRectifySuccessMessage">Debug compiliate mode uitgezet.</key>
|
||||
|
||||
<key alias="traceModeCheckSuccessMessage">Trace mode staat uit.</key>
|
||||
<key alias="traceModeCheckErrorMessage">Trace mode staat momenteel aan. Wij raden aan deze instelling uit te zetten voor livegang.</key>
|
||||
<key alias="traceModeCheckRectifySuccessMessage">Trace mode uitgezet.</key>
|
||||
|
||||
<key alias="folderPermissionsCheckMessage">Alle mappen hebben de juiste permissie-instellingen!.</key>
|
||||
<!-- The following keys get these tokens passed in:
|
||||
0: Comma delimitted list of failed folder paths
|
||||
-->
|
||||
<key alias="requiredFolderPermissionFailed"><![CDATA[De volgende bestanden moeten wijzig-rechten krijgen om Umbraco goed te laten werken: <strong>%0%</strong>.]]></key>
|
||||
<key alias="optionalFolderPermissionFailed"><![CDATA[Aangeraden wordt de volgende bestanden wijzig-rechten te geven om Umbraco goed te laten werken: <strong>%0%</strong>. Als deze niet in gebruik zijn voor deze omgeving hoeft er geen actie te worden ondernomen.]]></key>
|
||||
|
||||
<key alias="filePermissionsCheckMessage">All files have the correct permissions set.</key>
|
||||
<!-- The following keys get these tokens passed in:
|
||||
0: Comma delimitted list of failed folder paths
|
||||
-->
|
||||
<key alias="requiredFilePermissionFailed"><![CDATA[De volgende bestanden moeten schrijf-rechten krijgen om Umbraco goed te laten werken: <strong>%0%</strong>.]]></key>
|
||||
<key alias="optionalFilePermissionFailed"><![CDATA[Aangeraden wordt de volgende bestanden schrijf-rechten te geven om Umbraco goed te laten werken: <strong>%0%</strong>. Als deze niet in gebruik zijn voor deze omgeving hoeft er geen actie te worden ondernomen.]]></key>
|
||||
|
||||
<key alias="clickJackingCheckHeaderFound"><![CDATA[De <strong>X-Frame-Options</strong> header of meta-tag om IFRAMEing door andere websites te voorkomen is aanwezig!]]></key>
|
||||
<key alias="clickJackingCheckHeaderNotFound"><![CDATA[De <strong>X-Frame-Options</strong> header of meta-tag om IFRAMEing door andere websites te voorkomen is NIET aanwezig.]]></key>
|
||||
<key alias="clickJackingSetHeaderInConfig">Voorkom IFRAMEing via web.config</key>
|
||||
<key alias="clickJackingSetHeaderInConfigDescription">Voegt de instelling toe aan de httpProtocol/customHeaders section in web.config om IFRAMEing door andere websites te voorkomen.</key>
|
||||
<key alias="clickJackingSetHeaderInConfigSuccess">De instelling om IFRAMEing door andere websites te voorkomen is toegevoegd aan de web.config!</key>
|
||||
<key alias="clickJackingSetHeaderInConfigError">Web.config kon niet aangepast worden door error: %0%</key>
|
||||
|
||||
<!-- The following key get these tokens passed in:
|
||||
0: Comma delimitted list of headers found
|
||||
-->
|
||||
<key alias="excessiveHeadersFound"><![CDATA[De volgende header welke informatie tonen over de gebruikte website technologie zijn aangetroffen: <strong>%0%</strong>.]]></key>
|
||||
<key alias="excessiveHeadersNotFound">Er zijn geen headeres gevonden welke informatie over de gebruikte website technologie prijsgeven!</key>
|
||||
|
||||
<key alias="smtpMailSettingsNotFound">In de Web.config werd system.net/mailsettings niet gevonden</key>
|
||||
<key alias="smtpMailSettingsHostNotConfigured">In de Web.config sectie system.net/mailsettings is de host niet geconfigureerd.</key>
|
||||
<key alias="smtpMailSettingsConnectionSuccess">SMTP instellingen zijn correct ingesteld en werken zoals verwacht.</key>
|
||||
<key alias="smtpMailSettingsConnectionFail">De SMTP server geconfigureerd met host '%0%' en poort '%1%' kon niet gevonden worden. Controleer of de SMTP instellingen in Web.config file system.net/mailsettings correct zijn.</key>
|
||||
|
||||
<key alias="notificationEmailsCheckSuccessMessage"><![CDATA[Notificatie email is verzonden naar <strong>%0%</strong>.]]></key>
|
||||
<key alias="notificationEmailsCheckErrorMessage"><![CDATA[Notificatie email staat nog steeds op de default waarde van <strong>%0%</strong>.]]></key>
|
||||
</area>
|
||||
<area alias="redirectUrls">
|
||||
<key alias="disableUrlTracker">URL tracker uitzetten</key>
|
||||
<key alias="enableUrlTracker">URL tracker aanzetten</key>
|
||||
<key alias="originalUrl">Originele URL</key>
|
||||
<key alias="redirectedTo">Doorgestuurd naar</key>
|
||||
<key alias="noRedirects">Er zijn geen redirects</key>
|
||||
<key alias="noRedirectsDescription">Er wordt automatisch een redirect aangemaakt als een gepubliceerde pagina hernoemd of verplaatst wordt.</key>
|
||||
<key alias="removeButton">Verwijder</key>
|
||||
<key alias="confirmRemove">Weet je zeker dat je de redirect van '%0%' naar '%1%' wilt verwijderen?</key>
|
||||
<key alias="redirectRemoved">Redirect URL verwijderd.</key>
|
||||
<key alias="redirectRemoveError">Fout bij verwijderen redirect URL.</key>
|
||||
<key alias="confirmDisable">Weet je zeker dat je de URL tracker wilt uitzetten?</key>
|
||||
<key alias="disabledConfirm">URL tracker staat nu uit.</key>
|
||||
<key alias="disableError">Fout bij het uitzetten van de URL Tracker. Meer informatie kan gevonden worden in de log file.</key>
|
||||
<key alias="enabledConfirm">URL tracker staat nu aan.</key>
|
||||
<key alias="enableError">Fout bij het aanzetten van de URL tracker. Meer informatie kan gevonden worden in de log file.</key>
|
||||
</area>
|
||||
</language>
|
||||
|
||||
@@ -136,6 +136,7 @@ namespace Umbraco.Web.Editors
|
||||
var display = Mapper.Map<IPartialView, CodeFileDisplay>(view);
|
||||
display.FileType = Core.Constants.Trees.PartialViews;
|
||||
display.Path = Url.GetTreePathFromFilePath(view.Path);
|
||||
display.Id = System.Web.HttpUtility.UrlEncode(view.Path);
|
||||
return display;
|
||||
}
|
||||
return null;
|
||||
@@ -147,6 +148,7 @@ namespace Umbraco.Web.Editors
|
||||
var display = Mapper.Map<IPartialView, CodeFileDisplay>(viewMacro);
|
||||
display.FileType = Core.Constants.Trees.PartialViewMacros;
|
||||
display.Path = Url.GetTreePathFromFilePath(viewMacro.Path);
|
||||
display.Id = System.Web.HttpUtility.UrlEncode(viewMacro.Path);
|
||||
return display;
|
||||
}
|
||||
return null;
|
||||
@@ -158,6 +160,7 @@ namespace Umbraco.Web.Editors
|
||||
var display = Mapper.Map<Script, CodeFileDisplay>(script);
|
||||
display.FileType = Core.Constants.Trees.Scripts;
|
||||
display.Path = Url.GetTreePathFromFilePath(script.Path);
|
||||
display.Id = System.Web.HttpUtility.UrlEncode(script.Path);
|
||||
return display;
|
||||
}
|
||||
return null;
|
||||
@@ -341,6 +344,7 @@ namespace Umbraco.Web.Editors
|
||||
{
|
||||
display = Mapper.Map(partialViewResult.Result, display);
|
||||
display.Path = Url.GetTreePathFromFilePath(partialViewResult.Result.Path);
|
||||
display.Id = System.Web.HttpUtility.UrlEncode(partialViewResult.Result.Path);
|
||||
return display;
|
||||
}
|
||||
|
||||
@@ -355,6 +359,7 @@ namespace Umbraco.Web.Editors
|
||||
{
|
||||
display = Mapper.Map(partialViewMacroResult.Result, display);
|
||||
display.Path = Url.GetTreePathFromFilePath(partialViewMacroResult.Result.Path);
|
||||
display.Id = System.Web.HttpUtility.UrlEncode(partialViewMacroResult.Result.Path);
|
||||
return display;
|
||||
}
|
||||
|
||||
@@ -371,6 +376,7 @@ namespace Umbraco.Web.Editors
|
||||
script.Path = display.Name;
|
||||
display = Mapper.Map(script, display);
|
||||
display.Path = Url.GetTreePathFromFilePath(script.Path);
|
||||
display.Id = System.Web.HttpUtility.UrlEncode(script.Path);
|
||||
return display;
|
||||
|
||||
}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel;
|
||||
using System.Globalization;
|
||||
using System.Net;
|
||||
using System.Text;
|
||||
@@ -29,6 +30,8 @@ using Examine.SearchCriteria;
|
||||
using Umbraco.Web.Dynamics;
|
||||
using umbraco;
|
||||
using System.Text.RegularExpressions;
|
||||
using Umbraco.Core.Persistence.DatabaseModelDefinitions;
|
||||
using System.Web.Http.Controllers;
|
||||
using Umbraco.Core.Xml;
|
||||
|
||||
namespace Umbraco.Web.Editors
|
||||
@@ -43,6 +46,25 @@ namespace Umbraco.Web.Editors
|
||||
[PluginController("UmbracoApi")]
|
||||
public class EntityController : UmbracoAuthorizedJsonController
|
||||
{
|
||||
|
||||
/// <summary>
|
||||
/// Configures this controller with a custom action selector
|
||||
/// </summary>
|
||||
private class EntityControllerConfigurationAttribute : Attribute, IControllerConfiguration
|
||||
{
|
||||
public void Initialize(HttpControllerSettings controllerSettings, HttpControllerDescriptor controllerDescriptor)
|
||||
{
|
||||
controllerSettings.Services.Replace(typeof(IHttpActionSelector), new ParameterSwapControllerActionSelector(
|
||||
|
||||
//This is a special case, we'll accept a String here so that we can get page members when the special "all-members"
|
||||
//id is passed in eventually we'll probably want to support GUID + Udi too
|
||||
new ParameterSwapControllerActionSelector.ParameterSwapInfo("GetPagedChildren", "id", typeof(int), typeof(string)),
|
||||
|
||||
new ParameterSwapControllerActionSelector.ParameterSwapInfo("GetById", "id", typeof(int), typeof(Guid), typeof(Udi)),
|
||||
new ParameterSwapControllerActionSelector.ParameterSwapInfo("GetByIds", "ids", typeof(int[]), typeof(Guid[]), typeof(Udi[]))));
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns an Umbraco alias given a string
|
||||
/// </summary>
|
||||
@@ -144,9 +166,7 @@ namespace Umbraco.Web.Editors
|
||||
|
||||
return foundContent.Path.Split(new[] {','}, StringSplitOptions.RemoveEmptyEntries).Select(int.Parse);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Gets the url of an entity
|
||||
/// </summary>
|
||||
@@ -185,13 +205,9 @@ namespace Umbraco.Web.Editors
|
||||
Content = new StringContent(returnUrl)
|
||||
};
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets an entity by it's unique id if the entity supports that
|
||||
/// </summary>
|
||||
/// <param name="id"></param>
|
||||
/// <param name="type"></param>
|
||||
/// <returns></returns>
|
||||
|
||||
[Obsolete("Use GetyById instead")]
|
||||
[EditorBrowsable(EditorBrowsableState.Never)]
|
||||
public EntityBasic GetByKey(Guid id, UmbracoEntityTypes type)
|
||||
{
|
||||
return GetResultForKey(id, type);
|
||||
@@ -206,7 +222,7 @@ namespace Umbraco.Web.Editors
|
||||
/// <returns></returns>
|
||||
public EntityBasic GetByQuery(string query, int nodeContextId, UmbracoEntityTypes type)
|
||||
{
|
||||
//TODO: Rename this!!! It's a bit misleading, it should be GetByXPath
|
||||
//TODO: Rename this!!! It's misleading, it should be GetByXPath
|
||||
|
||||
|
||||
if (type != UmbracoEntityTypes.Document)
|
||||
@@ -235,13 +251,61 @@ namespace Umbraco.Web.Editors
|
||||
},
|
||||
publishedContentExists: i => Umbraco.TypedContent(i) != null);
|
||||
}
|
||||
|
||||
|
||||
#region GetById
|
||||
|
||||
/// <summary>
|
||||
/// Gets an entity by it's id
|
||||
/// </summary>
|
||||
/// <param name="id"></param>
|
||||
/// <param name="type"></param>
|
||||
/// <returns></returns>
|
||||
public EntityBasic GetById(int id, UmbracoEntityTypes type)
|
||||
{
|
||||
return GetResultForId(id, type);
|
||||
}
|
||||
|
||||
public IEnumerable<EntityBasic> GetByIds([FromUri]int[] ids, UmbracoEntityTypes type)
|
||||
/// <summary>
|
||||
/// Gets an entity by it's key
|
||||
/// </summary>
|
||||
/// <param name="id"></param>
|
||||
/// <param name="type"></param>
|
||||
/// <returns></returns>
|
||||
public EntityBasic GetById(Guid id, UmbracoEntityTypes type)
|
||||
{
|
||||
return GetResultForKey(id, type);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets an entity by it's UDI
|
||||
/// </summary>
|
||||
/// <param name="id"></param>
|
||||
/// <param name="type"></param>
|
||||
/// <returns></returns>
|
||||
public EntityBasic GetById(Udi id, UmbracoEntityTypes type)
|
||||
{
|
||||
var guidUdi = id as GuidUdi;
|
||||
if (guidUdi != null)
|
||||
{
|
||||
return GetResultForKey(guidUdi.Guid, type);
|
||||
}
|
||||
throw new HttpResponseException(HttpStatusCode.NotFound);
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region GetByIds
|
||||
/// <summary>
|
||||
/// Get entities by integer ids
|
||||
/// </summary>
|
||||
/// <param name="ids"></param>
|
||||
/// <param name="type"></param>
|
||||
/// <returns></returns>
|
||||
/// <remarks>
|
||||
/// We allow for POST because there could be quite a lot of Ids
|
||||
/// </remarks>
|
||||
[HttpGet]
|
||||
[HttpPost]
|
||||
public IEnumerable<EntityBasic> GetByIds([FromJsonPath]int[] ids, UmbracoEntityTypes type)
|
||||
{
|
||||
if (ids == null)
|
||||
{
|
||||
@@ -250,6 +314,66 @@ namespace Umbraco.Web.Editors
|
||||
return GetResultForIds(ids, type);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get entities by GUID ids
|
||||
/// </summary>
|
||||
/// <param name="ids"></param>
|
||||
/// <param name="type"></param>
|
||||
/// <returns></returns>
|
||||
/// <remarks>
|
||||
/// We allow for POST because there could be quite a lot of Ids
|
||||
/// </remarks>
|
||||
[HttpGet]
|
||||
[HttpPost]
|
||||
public IEnumerable<EntityBasic> GetByIds([FromJsonPath]Guid[] ids, UmbracoEntityTypes type)
|
||||
{
|
||||
if (ids == null)
|
||||
{
|
||||
throw new HttpResponseException(HttpStatusCode.NotFound);
|
||||
}
|
||||
return GetResultForKeys(ids, type);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get entities by UDIs
|
||||
/// </summary>
|
||||
/// <param name="ids">
|
||||
/// A list of UDIs to lookup items by, all UDIs must be of the same UDI type!
|
||||
/// </param>
|
||||
/// <param name="type"></param>
|
||||
/// <returns></returns>
|
||||
/// <remarks>
|
||||
/// We allow for POST because there could be quite a lot of Ids.
|
||||
/// </remarks>
|
||||
[HttpGet]
|
||||
[HttpPost]
|
||||
public IEnumerable<EntityBasic> GetByIds([FromJsonPath]Udi[] ids, [FromUri]UmbracoEntityTypes type)
|
||||
{
|
||||
if (ids == null)
|
||||
{
|
||||
throw new HttpResponseException(HttpStatusCode.NotFound);
|
||||
}
|
||||
|
||||
if (ids.Length == 0)
|
||||
{
|
||||
return Enumerable.Empty<EntityBasic>();
|
||||
}
|
||||
|
||||
//all udi types will need to be the same in this list so we'll determine by the first
|
||||
//currently we only support GuidIdi for this method
|
||||
|
||||
var guidUdi = ids[0] as GuidUdi;
|
||||
if (guidUdi != null)
|
||||
{
|
||||
return GetResultForKeys(ids.Select(x => ((GuidUdi)x).Guid).ToArray(), type);
|
||||
}
|
||||
|
||||
throw new HttpResponseException(HttpStatusCode.NotFound);
|
||||
}
|
||||
#endregion
|
||||
|
||||
[Obsolete("Use GetyByIds instead")]
|
||||
[EditorBrowsable(EditorBrowsableState.Never)]
|
||||
public IEnumerable<EntityBasic> GetByKeys([FromUri]Guid[] ids, UmbracoEntityTypes type)
|
||||
{
|
||||
if (ids == null)
|
||||
@@ -264,6 +388,176 @@ namespace Umbraco.Web.Editors
|
||||
return GetResultForChildren(id, type);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get paged child entities by id
|
||||
/// </summary>
|
||||
/// <param name="id"></param>
|
||||
/// <param name="type"></param>
|
||||
/// <param name="pageNumber"></param>
|
||||
/// <param name="pageSize"></param>
|
||||
/// <param name="orderBy"></param>
|
||||
/// <param name="orderDirection"></param>
|
||||
/// <param name="filter"></param>
|
||||
/// <returns></returns>
|
||||
public PagedResult<EntityBasic> GetPagedChildren(
|
||||
string id,
|
||||
UmbracoEntityTypes type,
|
||||
int pageNumber,
|
||||
int pageSize,
|
||||
string orderBy = "SortOrder",
|
||||
Direction orderDirection = Direction.Ascending,
|
||||
string filter = "")
|
||||
{
|
||||
int intId;
|
||||
|
||||
if (int.TryParse(id, out intId))
|
||||
{
|
||||
return GetPagedChildren(intId, type, pageNumber, pageSize, orderBy, orderDirection, filter);
|
||||
}
|
||||
|
||||
Guid guidId;
|
||||
if (Guid.TryParse(id, out guidId))
|
||||
{
|
||||
//Not supported currently
|
||||
throw new HttpResponseException(HttpStatusCode.NotFound);
|
||||
}
|
||||
|
||||
Udi udiId;
|
||||
if (Udi.TryParse(id, out udiId))
|
||||
{
|
||||
//Not supported currently
|
||||
throw new HttpResponseException(HttpStatusCode.NotFound);
|
||||
}
|
||||
|
||||
//so we don't have an INT, GUID or UDI, it's just a string, so now need to check if it's a special id or a member type
|
||||
if (id == Constants.Conventions.MemberTypes.AllMembersListId)
|
||||
{
|
||||
//the EntityService can search paged members from the root
|
||||
|
||||
intId = -1;
|
||||
return GetPagedChildren(intId, type, pageNumber, pageSize, orderBy, orderDirection, filter);
|
||||
}
|
||||
|
||||
//the EntityService cannot search members of a certain type, this is currently not supported and would require
|
||||
//quite a bit of plumbing to do in the Services/Repository, we'll revert to a paged search
|
||||
|
||||
int total;
|
||||
var searchResult = ExamineSearch(filter ?? "", type, pageSize, pageNumber - 1, out total, id);
|
||||
|
||||
return new PagedResult<EntityBasic>(total, pageNumber, pageSize)
|
||||
{
|
||||
Items = searchResult
|
||||
};
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get paged child entities by id
|
||||
/// </summary>
|
||||
/// <param name="id"></param>
|
||||
/// <param name="type"></param>
|
||||
/// <param name="pageNumber"></param>
|
||||
/// <param name="pageSize"></param>
|
||||
/// <param name="orderBy"></param>
|
||||
/// <param name="orderDirection"></param>
|
||||
/// <param name="filter"></param>
|
||||
/// <returns></returns>
|
||||
public PagedResult<EntityBasic> GetPagedChildren(
|
||||
int id,
|
||||
UmbracoEntityTypes type,
|
||||
int pageNumber,
|
||||
int pageSize,
|
||||
string orderBy = "SortOrder",
|
||||
Direction orderDirection = Direction.Ascending,
|
||||
string filter = "")
|
||||
{
|
||||
if (pageNumber <= 0)
|
||||
throw new HttpResponseException(HttpStatusCode.NotFound);
|
||||
if (pageSize <= 0)
|
||||
throw new HttpResponseException(HttpStatusCode.NotFound);
|
||||
|
||||
var objectType = ConvertToObjectType(type);
|
||||
if (objectType.HasValue)
|
||||
{
|
||||
long totalRecords;
|
||||
var entities = Services.EntityService.GetPagedChildren(id, objectType.Value, pageNumber - 1, pageSize, out totalRecords, orderBy, orderDirection, filter);
|
||||
|
||||
if (totalRecords == 0)
|
||||
{
|
||||
return new PagedResult<EntityBasic>(0, 0, 0);
|
||||
}
|
||||
|
||||
var pagedResult = new PagedResult<EntityBasic>(totalRecords, pageNumber, pageSize)
|
||||
{
|
||||
Items = entities.Select(Mapper.Map<EntityBasic>)
|
||||
};
|
||||
|
||||
return pagedResult;
|
||||
}
|
||||
|
||||
//now we need to convert the unknown ones
|
||||
switch (type)
|
||||
{
|
||||
case UmbracoEntityTypes.PropertyType:
|
||||
case UmbracoEntityTypes.PropertyGroup:
|
||||
case UmbracoEntityTypes.Domain:
|
||||
case UmbracoEntityTypes.Language:
|
||||
case UmbracoEntityTypes.User:
|
||||
case UmbracoEntityTypes.Macro:
|
||||
default:
|
||||
throw new NotSupportedException("The " + typeof(EntityController) + " does not currently support data for the type " + type);
|
||||
}
|
||||
}
|
||||
|
||||
public PagedResult<EntityBasic> GetPagedDescendants(
|
||||
int id,
|
||||
UmbracoEntityTypes type,
|
||||
int pageNumber,
|
||||
int pageSize,
|
||||
string orderBy = "SortOrder",
|
||||
Direction orderDirection = Direction.Ascending,
|
||||
string filter = "")
|
||||
{
|
||||
if (pageNumber <= 0)
|
||||
throw new HttpResponseException(HttpStatusCode.NotFound);
|
||||
if (pageSize <= 0)
|
||||
throw new HttpResponseException(HttpStatusCode.NotFound);
|
||||
|
||||
var objectType = ConvertToObjectType(type);
|
||||
if (objectType.HasValue)
|
||||
{
|
||||
long totalRecords;
|
||||
//if it's from root, don't return recycled
|
||||
var entities = id == Constants.System.Root
|
||||
? Services.EntityService.GetPagedDescendantsFromRoot(objectType.Value, pageNumber - 1, pageSize, out totalRecords, orderBy, orderDirection, filter, includeTrashed:false)
|
||||
: Services.EntityService.GetPagedDescendants(id, objectType.Value, pageNumber - 1, pageSize, out totalRecords, orderBy, orderDirection, filter);
|
||||
|
||||
if (totalRecords == 0)
|
||||
{
|
||||
return new PagedResult<EntityBasic>(0, 0, 0);
|
||||
}
|
||||
|
||||
var pagedResult = new PagedResult<EntityBasic>(totalRecords, pageNumber, pageSize)
|
||||
{
|
||||
Items = entities.Select(Mapper.Map<EntityBasic>)
|
||||
};
|
||||
|
||||
return pagedResult;
|
||||
}
|
||||
|
||||
//now we need to convert the unknown ones
|
||||
switch (type)
|
||||
{
|
||||
case UmbracoEntityTypes.PropertyType:
|
||||
case UmbracoEntityTypes.PropertyGroup:
|
||||
case UmbracoEntityTypes.Domain:
|
||||
case UmbracoEntityTypes.Language:
|
||||
case UmbracoEntityTypes.User:
|
||||
case UmbracoEntityTypes.Macro:
|
||||
default:
|
||||
throw new NotSupportedException("The " + typeof(EntityController) + " does not currently support data for the type " + type);
|
||||
}
|
||||
}
|
||||
|
||||
public IEnumerable<EntityBasic> GetAncestors(int id, UmbracoEntityTypes type)
|
||||
{
|
||||
return GetResultForAncestors(id, type);
|
||||
@@ -279,12 +573,30 @@ namespace Umbraco.Web.Editors
|
||||
/// </summary>
|
||||
/// <param name="query"></param>
|
||||
/// <param name="entityType"></param>
|
||||
/// <param name="searchFrom">
|
||||
/// A starting point for the search, generally a node id, but for members this is a member type alias
|
||||
/// </param>
|
||||
/// <param name="searchFrom"></param>
|
||||
/// <returns></returns>
|
||||
private IEnumerable<EntityBasic> ExamineSearch(string query, UmbracoEntityTypes entityType, string searchFrom = null)
|
||||
{
|
||||
int total;
|
||||
return ExamineSearch(query, entityType, 200, 0, out total, searchFrom);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Searches for results based on the entity type
|
||||
/// </summary>
|
||||
/// <param name="query"></param>
|
||||
/// <param name="entityType"></param>
|
||||
/// <param name="totalFound"></param>
|
||||
/// <param name="searchFrom">
|
||||
/// A starting point for the search, generally a node id, but for members this is a member type alias
|
||||
/// </param>
|
||||
/// <param name="pageSize"></param>
|
||||
/// <param name="pageIndex"></param>
|
||||
/// <returns></returns>
|
||||
private IEnumerable<EntityBasic> ExamineSearch(string query, UmbracoEntityTypes entityType, int pageSize, int pageIndex, out int totalFound, string searchFrom = null)
|
||||
{
|
||||
//TODO: We need to update this to support paging
|
||||
|
||||
var sb = new StringBuilder();
|
||||
|
||||
string type;
|
||||
@@ -360,91 +672,113 @@ namespace Umbraco.Web.Editors
|
||||
|
||||
query = Lucene.Net.QueryParsers.QueryParser.Escape(query);
|
||||
|
||||
if (query.IsNullOrWhiteSpace())
|
||||
//nothing to search
|
||||
if (searchFrom.IsNullOrWhiteSpace() && query.IsNullOrWhiteSpace())
|
||||
{
|
||||
totalFound = 0;
|
||||
return new List<EntityBasic>();
|
||||
}
|
||||
|
||||
//add back the surrounding quotes
|
||||
query = string.Format("{0}{1}{0}", "\"", query);
|
||||
|
||||
//node name exactly boost x 10
|
||||
sb.Append("+(__nodeName: (");
|
||||
sb.Append(query.ToLower());
|
||||
sb.Append(")^10.0 ");
|
||||
|
||||
foreach (var f in fields)
|
||||
//update the query with the query term
|
||||
if (query.IsNullOrWhiteSpace() == false)
|
||||
{
|
||||
//additional fields normally
|
||||
sb.Append(f);
|
||||
sb.Append(": (");
|
||||
sb.Append(query);
|
||||
//add back the surrounding quotes
|
||||
query = string.Format("{0}{1}{0}", "\"", query);
|
||||
|
||||
//node name exactly boost x 10
|
||||
sb.Append("+(__nodeName: (");
|
||||
sb.Append(query.ToLower());
|
||||
sb.Append(")^10.0 ");
|
||||
|
||||
foreach (var f in fields)
|
||||
{
|
||||
//additional fields normally
|
||||
sb.Append(f);
|
||||
sb.Append(": (");
|
||||
sb.Append(query);
|
||||
sb.Append(") ");
|
||||
}
|
||||
|
||||
sb.Append(") ");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (query.Trim(new[] { '\"', '\'' }).IsNullOrWhiteSpace())
|
||||
var trimmed = query.Trim(new[] {'\"', '\''});
|
||||
|
||||
//nothing to search
|
||||
if (searchFrom.IsNullOrWhiteSpace() && trimmed.IsNullOrWhiteSpace())
|
||||
{
|
||||
totalFound = 0;
|
||||
return new List<EntityBasic>();
|
||||
}
|
||||
|
||||
query = Lucene.Net.QueryParsers.QueryParser.Escape(query);
|
||||
|
||||
var querywords = query.Split(new[] { ' ' }, StringSplitOptions.RemoveEmptyEntries);
|
||||
|
||||
//node name exactly boost x 10
|
||||
sb.Append("+(__nodeName:");
|
||||
sb.Append("\"");
|
||||
sb.Append(query.ToLower());
|
||||
sb.Append("\"");
|
||||
sb.Append("^10.0 ");
|
||||
|
||||
//node name normally with wildcards
|
||||
sb.Append(" __nodeName:");
|
||||
sb.Append("(");
|
||||
foreach (var w in querywords)
|
||||
//update the query with the query term
|
||||
if (trimmed.IsNullOrWhiteSpace() == false)
|
||||
{
|
||||
sb.Append(w.ToLower());
|
||||
sb.Append("* ");
|
||||
}
|
||||
sb.Append(") ");
|
||||
query = Lucene.Net.QueryParsers.QueryParser.Escape(query);
|
||||
|
||||
var querywords = query.Split(new[] { ' ' }, StringSplitOptions.RemoveEmptyEntries);
|
||||
|
||||
foreach (var f in fields)
|
||||
{
|
||||
//additional fields normally
|
||||
sb.Append(f);
|
||||
sb.Append(":");
|
||||
//node name exactly boost x 10
|
||||
sb.Append("+(__nodeName:");
|
||||
sb.Append("\"");
|
||||
sb.Append(query.ToLower());
|
||||
sb.Append("\"");
|
||||
sb.Append("^10.0 ");
|
||||
|
||||
//node name normally with wildcards
|
||||
sb.Append(" __nodeName:");
|
||||
sb.Append("(");
|
||||
foreach (var w in querywords)
|
||||
{
|
||||
sb.Append(w.ToLower());
|
||||
sb.Append("* ");
|
||||
}
|
||||
sb.Append(")");
|
||||
sb.Append(" ");
|
||||
sb.Append(") ");
|
||||
|
||||
|
||||
foreach (var f in fields)
|
||||
{
|
||||
//additional fields normally
|
||||
sb.Append(f);
|
||||
sb.Append(":");
|
||||
sb.Append("(");
|
||||
foreach (var w in querywords)
|
||||
{
|
||||
sb.Append(w.ToLower());
|
||||
sb.Append("* ");
|
||||
}
|
||||
sb.Append(")");
|
||||
sb.Append(" ");
|
||||
}
|
||||
|
||||
sb.Append(") ");
|
||||
}
|
||||
}
|
||||
|
||||
//must match index type
|
||||
sb.Append(") +__IndexType:");
|
||||
sb.Append("+__IndexType:");
|
||||
sb.Append(type);
|
||||
|
||||
|
||||
var raw = internalSearcher.CreateSearchCriteria().RawQuery(sb.ToString());
|
||||
|
||||
//limit results to 200 to avoid huge over processing (CPU)
|
||||
var result = internalSearcher.Search(raw, 200);
|
||||
var result = internalSearcher
|
||||
//only return the number of items specified to read up to the amount of records to fill from 0 -> the number of items on the page requested
|
||||
.Search(raw, pageSize * (pageIndex + 1));
|
||||
|
||||
totalFound = result.TotalItemCount;
|
||||
|
||||
var pagedResult = result.Skip(pageIndex);
|
||||
|
||||
switch (entityType)
|
||||
{
|
||||
case UmbracoEntityTypes.Member:
|
||||
return MemberFromSearchResults(result);
|
||||
return MemberFromSearchResults(pagedResult.ToArray());
|
||||
case UmbracoEntityTypes.Media:
|
||||
return MediaFromSearchResults(result);
|
||||
return MediaFromSearchResults(pagedResult);
|
||||
case UmbracoEntityTypes.Document:
|
||||
return ContentFromSearchResults(result);
|
||||
return ContentFromSearchResults(pagedResult);
|
||||
default:
|
||||
throw new NotSupportedException("The " + typeof(EntityController) + " currently does not support searching against object type " + entityType);
|
||||
}
|
||||
@@ -455,7 +789,7 @@ namespace Umbraco.Web.Editors
|
||||
/// </summary>
|
||||
/// <param name="results"></param>
|
||||
/// <returns></returns>
|
||||
private IEnumerable<EntityBasic> MemberFromSearchResults(ISearchResults results)
|
||||
private IEnumerable<EntityBasic> MemberFromSearchResults(SearchResult[] results)
|
||||
{
|
||||
var mapped = Mapper.Map<IEnumerable<EntityBasic>>(results).ToArray();
|
||||
//add additional data
|
||||
@@ -489,7 +823,7 @@ namespace Umbraco.Web.Editors
|
||||
/// </summary>
|
||||
/// <param name="results"></param>
|
||||
/// <returns></returns>
|
||||
private IEnumerable<EntityBasic> MediaFromSearchResults(ISearchResults results)
|
||||
private IEnumerable<EntityBasic> MediaFromSearchResults(IEnumerable<SearchResult> results)
|
||||
{
|
||||
var mapped = Mapper.Map<IEnumerable<EntityBasic>>(results).ToArray();
|
||||
//add additional data
|
||||
@@ -509,9 +843,9 @@ namespace Umbraco.Web.Editors
|
||||
/// </summary>
|
||||
/// <param name="results"></param>
|
||||
/// <returns></returns>
|
||||
private IEnumerable<EntityBasic> ContentFromSearchResults(ISearchResults results)
|
||||
private IEnumerable<EntityBasic> ContentFromSearchResults(IEnumerable<SearchResult> results)
|
||||
{
|
||||
var mapped = Mapper.Map<ISearchResults, IEnumerable<EntityBasic>>(results).ToArray();
|
||||
var mapped = Mapper.Map<IEnumerable<EntityBasic>>(results).ToArray();
|
||||
//add additional data
|
||||
foreach (var m in mapped)
|
||||
{
|
||||
@@ -643,21 +977,21 @@ namespace Umbraco.Web.Editors
|
||||
}
|
||||
}
|
||||
|
||||
private IEnumerable<EntityBasic> GetResultForKeys(IEnumerable<Guid> keys, UmbracoEntityTypes entityType)
|
||||
private IEnumerable<EntityBasic> GetResultForKeys(Guid[] keys, UmbracoEntityTypes entityType)
|
||||
{
|
||||
var keysArray = keys.ToArray();
|
||||
if (keysArray.Any() == false) return Enumerable.Empty<EntityBasic>();
|
||||
if (keys.Length == 0)
|
||||
return Enumerable.Empty<EntityBasic>();
|
||||
|
||||
var objectType = ConvertToObjectType(entityType);
|
||||
if (objectType.HasValue)
|
||||
{
|
||||
var entities = Services.EntityService.GetAll(objectType.Value, keysArray)
|
||||
var entities = Services.EntityService.GetAll(objectType.Value, keys)
|
||||
.WhereNotNull()
|
||||
.Select(Mapper.Map<EntityBasic>);
|
||||
|
||||
// entities are in "some" order, put them back in order
|
||||
var xref = entities.ToDictionary(x => x.Key);
|
||||
var result = keysArray.Select(x => xref.ContainsKey(x) ? xref[x] : null).Where(x => x != null);
|
||||
var result = keys.Select(x => xref.ContainsKey(x) ? xref[x] : null).Where(x => x != null);
|
||||
|
||||
return result;
|
||||
}
|
||||
@@ -675,21 +1009,21 @@ namespace Umbraco.Web.Editors
|
||||
}
|
||||
}
|
||||
|
||||
private IEnumerable<EntityBasic> GetResultForIds(IEnumerable<int> ids, UmbracoEntityTypes entityType)
|
||||
private IEnumerable<EntityBasic> GetResultForIds(int[] ids, UmbracoEntityTypes entityType)
|
||||
{
|
||||
var idsArray = ids.ToArray();
|
||||
if (idsArray.Any() == false) return Enumerable.Empty<EntityBasic>();
|
||||
if (ids.Length == 0)
|
||||
return Enumerable.Empty<EntityBasic>();
|
||||
|
||||
var objectType = ConvertToObjectType(entityType);
|
||||
if (objectType.HasValue)
|
||||
{
|
||||
var entities = Services.EntityService.GetAll(objectType.Value, idsArray)
|
||||
var entities = Services.EntityService.GetAll(objectType.Value, ids)
|
||||
.WhereNotNull()
|
||||
.Select(Mapper.Map<EntityBasic>);
|
||||
|
||||
// entities are in "some" order, put them back in order
|
||||
var xref = entities.ToDictionary(x => x.Id);
|
||||
var result = idsArray.Select(x => xref.ContainsKey(x) ? xref[x] : null).Where(x => x != null);
|
||||
var result = ids.Select(x => xref.ContainsKey(x) ? xref[x] : null).Where(x => x != null);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -1,68 +0,0 @@
|
||||
using System;
|
||||
using System.Web;
|
||||
using System.Web.Http.Controllers;
|
||||
using Umbraco.Core;
|
||||
|
||||
namespace Umbraco.Web.Editors
|
||||
{
|
||||
/// <summary>
|
||||
/// This allows for calling GetById/GetByIds with a GUID... so it will automatically route to GetByKey/GetByKeys
|
||||
/// </summary>
|
||||
internal class EntityControllerActionSelector : ApiControllerActionSelector
|
||||
{
|
||||
|
||||
public override HttpActionDescriptor SelectAction(HttpControllerContext controllerContext)
|
||||
{
|
||||
if (controllerContext.Request.RequestUri.GetLeftPart(UriPartial.Path).InvariantEndsWith("GetById"))
|
||||
{
|
||||
var id = HttpUtility.ParseQueryString(controllerContext.Request.RequestUri.Query).Get("id");
|
||||
|
||||
if (id != null)
|
||||
{
|
||||
Guid parsed;
|
||||
if (Guid.TryParse(id, out parsed))
|
||||
{
|
||||
var controllerType = controllerContext.Controller.GetType();
|
||||
var method = controllerType.GetMethod("GetByKey");
|
||||
if (method != null)
|
||||
{
|
||||
return new ReflectedHttpActionDescriptor(controllerContext.ControllerDescriptor, method);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (controllerContext.Request.RequestUri.GetLeftPart(UriPartial.Path).InvariantEndsWith("GetByIds"))
|
||||
{
|
||||
var ids = HttpUtility.ParseQueryString(controllerContext.Request.RequestUri.Query).GetValues("ids");
|
||||
|
||||
if (ids != null)
|
||||
{
|
||||
var allmatched = true;
|
||||
foreach (var id in ids)
|
||||
{
|
||||
Guid parsed;
|
||||
if (Guid.TryParse(id, out parsed) == false)
|
||||
{
|
||||
allmatched = false;
|
||||
}
|
||||
}
|
||||
if (allmatched)
|
||||
{
|
||||
var controllerType = controllerContext.Controller.GetType();
|
||||
var method = controllerType.GetMethod("GetByKeys");
|
||||
if (method != null)
|
||||
{
|
||||
return new ReflectedHttpActionDescriptor(controllerContext.ControllerDescriptor, method);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
return base.SelectAction(controllerContext);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -4,18 +4,5 @@ using Umbraco.Web.WebApi;
|
||||
|
||||
namespace Umbraco.Web.Editors
|
||||
{
|
||||
/// <summary>
|
||||
/// This get's applied to the EntityController in order to have a custom IHttpActionSelector assigned to it
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// NOTE: It is SOOOO important to remember that you cannot just assign this in the 'initialize' method of a webapi
|
||||
/// controller as it will assign it GLOBALLY which is what you def do not want to do.
|
||||
/// </remarks>
|
||||
internal class EntityControllerConfigurationAttribute : Attribute, IControllerConfiguration
|
||||
{
|
||||
public void Initialize(HttpControllerSettings controllerSettings, HttpControllerDescriptor controllerDescriptor)
|
||||
{
|
||||
controllerSettings.Services.Replace(typeof(IHttpActionSelector), new EntityControllerActionSelector());
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,101 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Net.Http;
|
||||
using System.Web.Http;
|
||||
using System.Web.Http.Controllers;
|
||||
using System.Web.Http.ModelBinding;
|
||||
using System.Web.Http.ValueProviders;
|
||||
using Newtonsoft.Json;
|
||||
using Newtonsoft.Json.Linq;
|
||||
using Umbraco.Core;
|
||||
|
||||
namespace Umbraco.Web.Editors
|
||||
{
|
||||
/// <summary>
|
||||
/// Used to bind a value from an inner json property
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// An example would be if you had json like:
|
||||
/// { ids: [1,2,3,4] }
|
||||
///
|
||||
/// And you had an action like: GetByIds(int[] ids, UmbracoEntityTypes type)
|
||||
///
|
||||
/// The ids array will not bind because the object being sent up is an object and not an array so the
|
||||
/// normal json formatter will not figure this out.
|
||||
///
|
||||
/// This would also let you bind sub levels of the JSON being sent up too if you wanted with any jsonpath
|
||||
/// </remarks>
|
||||
internal class FromJsonPathAttribute : ModelBinderAttribute
|
||||
{
|
||||
private readonly string _jsonPath;
|
||||
private readonly FromUriAttribute _fromUriAttribute = new FromUriAttribute();
|
||||
|
||||
public FromJsonPathAttribute()
|
||||
{
|
||||
}
|
||||
|
||||
public FromJsonPathAttribute(string jsonPath) : base(typeof(JsonPathBinder))
|
||||
{
|
||||
_jsonPath = jsonPath;
|
||||
}
|
||||
|
||||
public override IEnumerable<ValueProviderFactory> GetValueProviderFactories(HttpConfiguration configuration)
|
||||
{
|
||||
return _fromUriAttribute.GetValueProviderFactories(configuration);
|
||||
}
|
||||
|
||||
public override HttpParameterBinding GetBinding(HttpParameterDescriptor parameter)
|
||||
{
|
||||
var config = parameter.Configuration;
|
||||
//get the default binder, we'll use that if it's a GET or if the body is empty
|
||||
var underlyingBinder = base.GetModelBinder(config, parameter.ParameterType);
|
||||
var binder = new JsonPathBinder(underlyingBinder, _jsonPath);
|
||||
var valueProviderFactories = GetValueProviderFactories(config);
|
||||
|
||||
return new ModelBinderParameterBinding(parameter, binder, valueProviderFactories);
|
||||
}
|
||||
|
||||
private class JsonPathBinder : IModelBinder
|
||||
{
|
||||
private readonly IModelBinder _underlyingBinder;
|
||||
private readonly string _jsonPath;
|
||||
|
||||
public JsonPathBinder(IModelBinder underlyingBinder, string jsonPath)
|
||||
{
|
||||
_underlyingBinder = underlyingBinder;
|
||||
_jsonPath = jsonPath;
|
||||
}
|
||||
|
||||
public bool BindModel(HttpActionContext actionContext, ModelBindingContext bindingContext)
|
||||
{
|
||||
if (actionContext.Request.Method == HttpMethod.Get)
|
||||
{
|
||||
return _underlyingBinder.BindModel(actionContext, bindingContext);
|
||||
}
|
||||
|
||||
var requestContent = new HttpMessageContent(actionContext.Request);
|
||||
var strJson = requestContent.HttpRequestMessage.Content.ReadAsStringAsync().Result;
|
||||
|
||||
if (strJson.IsNullOrWhiteSpace())
|
||||
{
|
||||
return _underlyingBinder.BindModel(actionContext, bindingContext);
|
||||
}
|
||||
|
||||
var json = JsonConvert.DeserializeObject<JObject>(strJson);
|
||||
|
||||
//if no explicit json path then use the model name
|
||||
var match = json.SelectToken(_jsonPath ?? bindingContext.ModelName);
|
||||
|
||||
if (match == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
bindingContext.Model = match.ToObject(bindingContext.ModelType);
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,7 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel;
|
||||
using System.Globalization;
|
||||
using System.IO;
|
||||
using System.Net;
|
||||
using System.Net.Http;
|
||||
@@ -28,7 +29,9 @@ using Umbraco.Web.Mvc;
|
||||
using Umbraco.Web.WebApi;
|
||||
using System.Linq;
|
||||
using System.Runtime.Serialization;
|
||||
using System.Text.RegularExpressions;
|
||||
using System.Web.Http.Controllers;
|
||||
using Examine;
|
||||
using Umbraco.Web.WebApi.Binders;
|
||||
using Umbraco.Web.WebApi.Filters;
|
||||
using umbraco;
|
||||
@@ -59,7 +62,7 @@ namespace Umbraco.Web.Editors
|
||||
public void Initialize(HttpControllerSettings controllerSettings, HttpControllerDescriptor controllerDescriptor)
|
||||
{
|
||||
controllerSettings.Services.Replace(typeof(IHttpActionSelector), new ParameterSwapControllerActionSelector(
|
||||
new ParameterSwapControllerActionSelector.ParameterSwapInfo("GetChildren", "id", typeof(int), typeof(Guid), typeof(string))));
|
||||
new ParameterSwapControllerActionSelector.ParameterSwapInfo("GetChildren", "id", typeof(int), typeof(Guid), typeof(Udi), typeof(string))));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -187,6 +190,7 @@ namespace Umbraco.Web.Editors
|
||||
.Select(Mapper.Map<IMedia, ContentItemBasic<ContentPropertyBasic, IMedia>>);
|
||||
}
|
||||
|
||||
#region GetChildren
|
||||
/// <summary>
|
||||
/// Returns the child media objects - using the entity INT id
|
||||
/// </summary>
|
||||
@@ -244,7 +248,7 @@ namespace Umbraco.Web.Editors
|
||||
Direction orderDirection = Direction.Ascending,
|
||||
bool orderBySystemField = true,
|
||||
string filter = "")
|
||||
{
|
||||
{
|
||||
var entity = Services.EntityService.GetByKey(id);
|
||||
if (entity != null)
|
||||
{
|
||||
@@ -253,6 +257,39 @@ namespace Umbraco.Web.Editors
|
||||
throw new HttpResponseException(HttpStatusCode.NotFound);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the child media objects - using the entity UDI id
|
||||
/// </summary>
|
||||
/// <param name="id"></param>
|
||||
/// <param name="pageNumber"></param>
|
||||
/// <param name="pageSize"></param>
|
||||
/// <param name="orderBy"></param>
|
||||
/// <param name="orderDirection"></param>
|
||||
/// <param name="orderBySystemField"></param>
|
||||
/// <param name="filter"></param>
|
||||
/// <returns></returns>
|
||||
[FilterAllowedOutgoingMedia(typeof(IEnumerable<ContentItemBasic<ContentPropertyBasic, IMedia>>), "Items")]
|
||||
public PagedResult<ContentItemBasic<ContentPropertyBasic, IMedia>> GetChildren(Udi id,
|
||||
int pageNumber = 0,
|
||||
int pageSize = 0,
|
||||
string orderBy = "SortOrder",
|
||||
Direction orderDirection = Direction.Ascending,
|
||||
bool orderBySystemField = true,
|
||||
string filter = "")
|
||||
{
|
||||
var guidUdi = id as GuidUdi;
|
||||
if (guidUdi != null)
|
||||
{
|
||||
var entity = Services.EntityService.GetByKey(guidUdi.Guid);
|
||||
if (entity != null)
|
||||
{
|
||||
return GetChildren(entity.Id, pageNumber, pageSize, orderBy, orderDirection, orderBySystemField, filter);
|
||||
}
|
||||
}
|
||||
|
||||
throw new HttpResponseException(HttpStatusCode.NotFound);
|
||||
}
|
||||
|
||||
[Obsolete("Do not use this method, use either the overload with INT or GUID instead, this will be removed in future versions")]
|
||||
[EditorBrowsable(EditorBrowsableState.Never)]
|
||||
[UmbracoTreeAuthorize(Constants.Trees.MediaTypes, Constants.Trees.Media)]
|
||||
@@ -275,7 +312,8 @@ namespace Umbraco.Web.Editors
|
||||
}
|
||||
|
||||
throw new HttpResponseException(HttpStatusCode.NotFound);
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
/// <summary>
|
||||
/// Moves an item to the recycle bin, if it is already there then it will permanently delete it
|
||||
|
||||
@@ -40,7 +40,7 @@ namespace Umbraco.Web.Editors
|
||||
public void Initialize(HttpControllerSettings controllerSettings, HttpControllerDescriptor controllerDescriptor)
|
||||
{
|
||||
controllerSettings.Services.Replace(typeof(IHttpActionSelector), new ParameterSwapControllerActionSelector(
|
||||
new ParameterSwapControllerActionSelector.ParameterSwapInfo("GetAllowedChildren", "contentId", typeof(int), typeof(Guid), typeof(string))));
|
||||
new ParameterSwapControllerActionSelector.ParameterSwapInfo("GetAllowedChildren", "contentId", typeof(int), typeof(Guid), typeof(Udi), typeof(string))));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -187,6 +187,7 @@ namespace Umbraco.Web.Editors
|
||||
}
|
||||
|
||||
|
||||
#region GetAllowedChildren
|
||||
/// <summary>
|
||||
/// Returns the allowed child content type objects for the content item id passed in - based on an INT id
|
||||
/// </summary>
|
||||
@@ -247,10 +248,30 @@ namespace Umbraco.Web.Editors
|
||||
|
||||
throw new HttpResponseException(HttpStatusCode.NotFound);
|
||||
}
|
||||
|
||||
[Obsolete("Do not use this method, use either the overload with INT or GUID instead, this will be removed in future versions")]
|
||||
|
||||
/// <summary>
|
||||
/// Returns the allowed child content type objects for the content item id passed in - based on a UDI id
|
||||
/// </summary>
|
||||
/// <param name="contentId"></param>
|
||||
[UmbracoTreeAuthorize(Constants.Trees.MediaTypes, Constants.Trees.Media)]
|
||||
public IEnumerable<ContentTypeBasic> GetAllowedChildren(Udi contentId)
|
||||
{
|
||||
var guidUdi = contentId as GuidUdi;
|
||||
if (guidUdi != null)
|
||||
{
|
||||
var entity = ApplicationContext.Services.EntityService.GetByKey(guidUdi.Guid);
|
||||
if (entity != null)
|
||||
{
|
||||
return GetAllowedChildren(entity.Id);
|
||||
}
|
||||
}
|
||||
|
||||
throw new HttpResponseException(HttpStatusCode.NotFound);
|
||||
}
|
||||
|
||||
[Obsolete("Do not use this method, use either the overload with INT, GUID or UDI instead, this will be removed in future versions")]
|
||||
[EditorBrowsable(EditorBrowsableState.Never)]
|
||||
[UmbracoTreeAuthorize(Constants.Trees.MediaTypes, Constants.Trees.Media)]
|
||||
[UmbracoTreeAuthorize(Constants.Trees.MediaTypes, Constants.Trees.Media)]
|
||||
public IEnumerable<ContentTypeBasic> GetAllowedChildren(string contentId)
|
||||
{
|
||||
foreach (var type in new[] { typeof(int), typeof(Guid) })
|
||||
@@ -260,11 +281,12 @@ namespace Umbraco.Web.Editors
|
||||
{
|
||||
//oooh magic! will auto select the right overload
|
||||
return GetAllowedChildren((dynamic)parsed.Result);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
throw new HttpResponseException(HttpStatusCode.NotFound);
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
/// <summary>
|
||||
/// Move the media type
|
||||
|
||||
@@ -1,7 +1,15 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Linq;
|
||||
using System.Net.Http;
|
||||
using System.Net.Http.Formatting;
|
||||
using System.Web;
|
||||
using System.Web.Http;
|
||||
using System.Web.Http.Controllers;
|
||||
using System.Web.Http.Validation;
|
||||
using System.Web.Http.ValueProviders;
|
||||
using Newtonsoft.Json;
|
||||
using Newtonsoft.Json.Linq;
|
||||
using Umbraco.Core;
|
||||
|
||||
namespace Umbraco.Web.Editors
|
||||
@@ -12,6 +20,8 @@ namespace Umbraco.Web.Editors
|
||||
/// <remarks>
|
||||
/// As an example, lets say we have 2 methods: GetChildren(int id) and GetChildren(Guid id), by default Web Api won't allow this since
|
||||
/// it won't know what to select, but if this Tuple is passed in new Tuple{string, string}("GetChildren", "id")
|
||||
///
|
||||
/// This supports POST values too however only for JSON values
|
||||
/// </remarks>
|
||||
internal class ParameterSwapControllerActionSelector : ApiControllerActionSelector
|
||||
{
|
||||
@@ -25,33 +35,102 @@ namespace Umbraco.Web.Editors
|
||||
{
|
||||
_actions = actions;
|
||||
}
|
||||
|
||||
public override HttpActionDescriptor SelectAction(HttpControllerContext controllerContext)
|
||||
{
|
||||
var found = _actions.FirstOrDefault(x => controllerContext.Request.RequestUri.GetLeftPart(UriPartial.Path).InvariantEndsWith(x.ActionName));
|
||||
|
||||
if (found != null)
|
||||
{
|
||||
var id = HttpUtility.ParseQueryString(controllerContext.Request.RequestUri.Query).Get(found.ParamName);
|
||||
|
||||
if (id != null)
|
||||
HttpActionDescriptor method;
|
||||
if (TryBindFromUri(controllerContext, found, out method))
|
||||
{
|
||||
var idTypes = found.SupportedTypes;
|
||||
return method;
|
||||
}
|
||||
|
||||
foreach (var idType in idTypes)
|
||||
//if it's a post we can try to read from the body and bind from the json value
|
||||
if (controllerContext.Request.Method == HttpMethod.Post)
|
||||
{
|
||||
var requestContent = new HttpMessageContent(controllerContext.Request);
|
||||
var strJson = requestContent.HttpRequestMessage.Content.ReadAsStringAsync().Result;
|
||||
var json = JsonConvert.DeserializeObject<JObject>(strJson);
|
||||
|
||||
if (json == null)
|
||||
{
|
||||
var converted = id.TryConvertTo(idType);
|
||||
if (converted)
|
||||
return base.SelectAction(controllerContext);
|
||||
}
|
||||
|
||||
var requestParam = json[found.ParamName];
|
||||
|
||||
if (requestParam != null)
|
||||
{
|
||||
var paramTypes = found.SupportedTypes;
|
||||
|
||||
foreach (var paramType in paramTypes)
|
||||
{
|
||||
var method = MatchByType(idType, controllerContext, found);
|
||||
if (method != null)
|
||||
return method;
|
||||
try
|
||||
{
|
||||
var converted = requestParam.ToObject(paramType);
|
||||
if (converted != null)
|
||||
{
|
||||
method = MatchByType(paramType, controllerContext, found);
|
||||
if (method != null)
|
||||
return method;
|
||||
}
|
||||
}
|
||||
catch (JsonReaderException)
|
||||
{
|
||||
//can't convert
|
||||
}
|
||||
catch (JsonSerializationException)
|
||||
{
|
||||
//can't convert
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return base.SelectAction(controllerContext);
|
||||
}
|
||||
|
||||
private bool TryBindFromUri(HttpControllerContext controllerContext, ParameterSwapInfo found, out HttpActionDescriptor method)
|
||||
{
|
||||
var requestParam = HttpUtility.ParseQueryString(controllerContext.Request.RequestUri.Query).Get(found.ParamName);
|
||||
|
||||
requestParam = (requestParam == null) ? null : requestParam.Trim();
|
||||
var paramTypes = found.SupportedTypes;
|
||||
|
||||
if (requestParam == string.Empty && paramTypes.Length > 0)
|
||||
{
|
||||
//if it's empty then in theory we can select any of the actions since they'll all need to deal with empty or null parameters
|
||||
//so we'll try to use the first one available
|
||||
method = MatchByType(paramTypes[0], controllerContext, found);
|
||||
if (method != null)
|
||||
return true;
|
||||
}
|
||||
|
||||
if (requestParam != null)
|
||||
{
|
||||
foreach (var paramType in paramTypes)
|
||||
{
|
||||
//check if this is IEnumerable and if so this will get it's type
|
||||
//we need to know this since the requestParam will always just be a string
|
||||
var enumType = paramType.GetEnumeratedType();
|
||||
|
||||
var converted = requestParam.TryConvertTo(enumType ?? paramType);
|
||||
if (converted)
|
||||
{
|
||||
method = MatchByType(paramType, controllerContext, found);
|
||||
if (method != null)
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
method = null;
|
||||
return false;
|
||||
}
|
||||
|
||||
private static ReflectedHttpActionDescriptor MatchByType(Type idType, HttpControllerContext controllerContext, ParameterSwapInfo found)
|
||||
{
|
||||
var controllerType = controllerContext.Controller.GetType();
|
||||
|
||||
@@ -1,5 +1,3 @@
|
||||
using System.Web;
|
||||
|
||||
namespace Umbraco.Web
|
||||
{
|
||||
/// <summary>
|
||||
@@ -8,8 +6,6 @@ namespace Umbraco.Web
|
||||
/// <remarks>
|
||||
/// NOTE: This has a singleton lifespan
|
||||
/// </remarks>
|
||||
public interface IHttpContextAccessor
|
||||
{
|
||||
HttpContextBase Value { get; }
|
||||
}
|
||||
public interface IHttpContextAccessor : Core.IHttpContextAccessor
|
||||
{ }
|
||||
}
|
||||
@@ -42,6 +42,10 @@ namespace Umbraco.Web.Models.ContentEditing
|
||||
[ReadOnly(true)]
|
||||
public string Snippet { get; set; }
|
||||
|
||||
[DataMember(Name = "id")]
|
||||
[ReadOnly(true)]
|
||||
public string Id { get; set; }
|
||||
|
||||
public List<Notification> Notifications { get; private set; }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -84,17 +84,21 @@ namespace Umbraco.Web.Models.ContentEditing
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The real persisted content object
|
||||
/// The real persisted content object - used during inbound model binding
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This is not used for outgoing model information.
|
||||
/// </remarks>
|
||||
[JsonIgnore]
|
||||
internal TPersisted PersistedContent { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The DTO object used to gather all required content data including data type information etc... for use with validation
|
||||
/// The DTO object used to gather all required content data including data type information etc... for use with validation - used during inbound model binding
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// We basically use this object to hydrate all required data from the database into one object so we can validate everything we need
|
||||
/// instead of having to look up all the data individually.
|
||||
/// This is not used for outgoing model information.
|
||||
/// </remarks>
|
||||
[JsonIgnore]
|
||||
internal ContentItemDto<TPersisted> ContentDto { get; set; }
|
||||
|
||||
@@ -6,7 +6,10 @@ using System.Linq;
|
||||
using System.Runtime.Serialization;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using Newtonsoft.Json;
|
||||
using Umbraco.Core;
|
||||
using Umbraco.Core.Models.Validation;
|
||||
using Umbraco.Core.Serialization;
|
||||
|
||||
namespace Umbraco.Web.Models.ContentEditing
|
||||
{
|
||||
@@ -25,7 +28,12 @@ namespace Umbraco.Web.Models.ContentEditing
|
||||
[DataMember(Name = "id", IsRequired = true)]
|
||||
[Required]
|
||||
public object Id { get; set; }
|
||||
|
||||
|
||||
[DataMember(Name = "udi")]
|
||||
[ReadOnly(true)]
|
||||
[JsonConverter(typeof(UdiJsonConverter))]
|
||||
public Udi Udi { get; set; }
|
||||
|
||||
[DataMember(Name = "icon")]
|
||||
public string Icon { get; set; }
|
||||
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using System.Runtime.Serialization;
|
||||
using System.Collections.Generic;
|
||||
using System.Runtime.Serialization;
|
||||
|
||||
namespace Umbraco.Web.Models.ContentEditing
|
||||
{
|
||||
@@ -33,5 +34,11 @@ namespace Umbraco.Web.Models.ContentEditing
|
||||
[DataMember(Name = "view", IsRequired = true)]
|
||||
public string View { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// This allows for custom configuration to be injected into the pre-value editor
|
||||
/// </summary>
|
||||
[DataMember(Name = "config")]
|
||||
public IDictionary<string, object> Config { get; set; }
|
||||
|
||||
}
|
||||
}
|
||||
@@ -2,6 +2,7 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using AutoMapper;
|
||||
using Umbraco.Core.Configuration.UmbracoSettings;
|
||||
using Umbraco.Core.Models;
|
||||
using Umbraco.Core.PropertyEditors;
|
||||
using Umbraco.Web.Models.ContentEditing;
|
||||
@@ -10,9 +11,22 @@ namespace Umbraco.Web.Models.Mapping
|
||||
{
|
||||
internal class AvailablePropertyEditorsResolver : ValueResolver<IDataTypeDefinition, IEnumerable<PropertyEditorBasic>>
|
||||
{
|
||||
private readonly IContentSection _contentSection;
|
||||
|
||||
public AvailablePropertyEditorsResolver(IContentSection contentSection)
|
||||
{
|
||||
_contentSection = contentSection;
|
||||
}
|
||||
|
||||
protected override IEnumerable<PropertyEditorBasic> ResolveCore(IDataTypeDefinition source)
|
||||
{
|
||||
return PropertyEditorResolver.Current.PropertyEditors
|
||||
.Where(x =>
|
||||
{
|
||||
if (_contentSection.ShowDeprecatedPropertyEditors)
|
||||
return true;
|
||||
return source.PropertyEditorAlias == x.Alias || x.IsDeprecated == false;
|
||||
})
|
||||
.OrderBy(x => x.Name)
|
||||
.Select(Mapper.Map<PropertyEditorBasic>);
|
||||
}
|
||||
|
||||
@@ -28,6 +28,7 @@ namespace Umbraco.Web.Models.Mapping
|
||||
|
||||
//FROM IContent TO ContentItemDisplay
|
||||
config.CreateMap<IContent, ContentItemDisplay>()
|
||||
.ForMember(display => display.Udi, expression => expression.MapFrom(content => Udi.Create(Constants.UdiEntityType.Document, content.Key)))
|
||||
.ForMember(display => display.Owner, expression => expression.ResolveUsing(new OwnerResolver<IContent>()))
|
||||
.ForMember(display => display.Updater, expression => expression.ResolveUsing(new CreatorResolver()))
|
||||
.ForMember(display => display.Icon, expression => expression.MapFrom(content => content.ContentType.Icon))
|
||||
@@ -58,6 +59,7 @@ namespace Umbraco.Web.Models.Mapping
|
||||
|
||||
//FROM IContent TO ContentItemBasic<ContentPropertyBasic, IContent>
|
||||
config.CreateMap<IContent, ContentItemBasic<ContentPropertyBasic, IContent>>()
|
||||
.ForMember(display => display.Udi, expression => expression.MapFrom(content => Udi.Create(Constants.UdiEntityType.Document, content.Key)))
|
||||
.ForMember(dto => dto.Owner, expression => expression.ResolveUsing(new OwnerResolver<IContent>()))
|
||||
.ForMember(dto => dto.Updater, expression => expression.ResolveUsing(new CreatorResolver()))
|
||||
.ForMember(dto => dto.Icon, expression => expression.MapFrom(content => content.ContentType.Icon))
|
||||
@@ -68,6 +70,7 @@ namespace Umbraco.Web.Models.Mapping
|
||||
|
||||
//FROM IContent TO ContentItemDto<IContent>
|
||||
config.CreateMap<IContent, ContentItemDto<IContent>>()
|
||||
.ForMember(display => display.Udi, expression => expression.MapFrom(content => Udi.Create(Constants.UdiEntityType.Document, content.Key)))
|
||||
.ForMember(dto => dto.Owner, expression => expression.ResolveUsing(new OwnerResolver<IContent>()))
|
||||
.ForMember(dto => dto.HasPublishedVersion, expression => expression.MapFrom(content => content.HasPublishedVersion))
|
||||
.ForMember(dto => dto.Updater, expression => expression.Ignore())
|
||||
|
||||
@@ -161,9 +161,12 @@ namespace Umbraco.Web.Models.Mapping
|
||||
|
||||
});
|
||||
|
||||
config.CreateMap<IMemberType, ContentTypeBasic>();
|
||||
config.CreateMap<IMediaType, ContentTypeBasic>();
|
||||
config.CreateMap<IContentType, ContentTypeBasic>();
|
||||
config.CreateMap<IMemberType, ContentTypeBasic>()
|
||||
.ForMember(x => x.Udi, expression => expression.MapFrom(content => Udi.Create(Constants.UdiEntityType.MemberType, content.Key)));
|
||||
config.CreateMap<IMediaType, ContentTypeBasic>()
|
||||
.ForMember(x => x.Udi, expression => expression.MapFrom(content => Udi.Create(Constants.UdiEntityType.MediaType, content.Key)));
|
||||
config.CreateMap<IContentType, ContentTypeBasic>()
|
||||
.ForMember(x => x.Udi, expression => expression.MapFrom(content => Udi.Create(Constants.UdiEntityType.DocumentType, content.Key)));
|
||||
|
||||
config.CreateMap<PropertyTypeBasic, PropertyType>()
|
||||
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user