Merge branch 'temp8' into temp8-oembed-collection

This commit is contained in:
Stephan
2019-02-01 17:44:53 +01:00
119 changed files with 1428 additions and 756 deletions
+1 -1
View File
@@ -8,7 +8,7 @@
<owners>Umbraco HQ</owners>
<licenseUrl>http://opensource.org/licenses/MIT</licenseUrl>
<projectUrl>http://umbraco.com/</projectUrl>
<iconUrl>http://umbraco.com/media/357769/100px_transparent.png</iconUrl>
<iconUrl>https://umbraco.com/dist/nuget/logo-small.png</iconUrl>
<requireLicenseAcceptance>false</requireLicenseAcceptance>
<description>Contains the core assemblies needed to run Umbraco Cms. This package only contains assemblies and can be used for package development. Use the UmbracoCms package to setup Umbraco in Visual Studio as an ASP.NET project.</description>
<summary>Contains the core assemblies needed to run Umbraco Cms</summary>
+2 -2
View File
@@ -8,13 +8,13 @@
<owners>Umbraco HQ</owners>
<licenseUrl>http://opensource.org/licenses/MIT</licenseUrl>
<projectUrl>http://umbraco.com/</projectUrl>
<iconUrl>http://umbraco.com/media/357769/100px_transparent.png</iconUrl>
<iconUrl>https://umbraco.com/dist/nuget/logo-small.png</iconUrl>
<requireLicenseAcceptance>false</requireLicenseAcceptance>
<description>Contains the web assemblies needed to run Umbraco Cms. This package only contains assemblies and can be used for package development. Use the UmbracoCms package to setup Umbraco in Visual Studio as an ASP.NET project.</description>
<summary>Contains the core assemblies needed to run Umbraco Cms</summary>
<language>en-US</language>
<tags>umbraco</tags>
<dependencies>
<dependencies>
<!--
note: dependencies are specified as [x.y.z,x.999999) eg [2.1.0,2.999999) and NOT [2.1.0,3.0.0) because
the latter would pick anything below 3.0.0 and that includes prereleases such as 3.0.0-alpha, and we do
+1 -1
View File
@@ -8,7 +8,7 @@
<owners>Umbraco HQ</owners>
<licenseUrl>http://opensource.org/licenses/MIT</licenseUrl>
<projectUrl>http://umbraco.com/</projectUrl>
<iconUrl>http://umbraco.com/media/357769/100px_transparent.png</iconUrl>
<iconUrl>https://umbraco.com/dist/nuget/logo-small.png</iconUrl>
<requireLicenseAcceptance>false</requireLicenseAcceptance>
<description>Installs Umbraco Cms in your Visual Studio ASP.NET project</description>
<summary>Installs Umbraco Cms in your Visual Studio ASP.NET project</summary>
+1 -1
View File
@@ -54,7 +54,7 @@ if ($project) {
[xml]$config = Get-Content $destinationWebConfig
$config.configuration.appSettings.ChildNodes | ForEach-Object {
if($_.key -eq "umbracoConfigurationStatus")
if($_.key -eq "Umbraco.Core.ConfigurationStatus")
{
# The web.config has an umbraco-specific appSetting in it
# don't overwrite it and let config transforms do their thing
@@ -37,6 +37,7 @@ namespace Umbraco.Core.Composing.Composers
composition.RegisterUnique<IMemberService, MemberService>();
composition.RegisterUnique<IMediaService, MediaService>();
composition.RegisterUnique<IContentTypeService, ContentTypeService>();
composition.RegisterUnique<IContentTypeBaseServiceProvider, ContentTypeBaseServiceProvider>();
composition.RegisterUnique<IMediaTypeService, MediaTypeService>();
composition.RegisterUnique<IDataTypeService, DataTypeService>();
composition.RegisterUnique<IFileService, FileService>();
@@ -18,14 +18,14 @@ namespace Umbraco.Core.Composing
/// Creates a new instance of the configured container.
/// </summary>
/// <remarks>
/// To override the default LightInjectContainer, add an appSetting named umbracoContainerType with
/// To override the default LightInjectContainer, add an appSetting named 'Umbraco.Core.RegisterType' with
/// a fully qualified type name to a class with a static method "Create" returning an IRegister.
/// </remarks>
public static IRegister Create()
{
Type type;
var configuredTypeName = ConfigurationManager.AppSettings["umbracoRegisterType"];
var configuredTypeName = ConfigurationManager.AppSettings[Constants.AppSettings.RegisterType];
if (configuredTypeName.IsNullOrWhiteSpace())
{
// try to get the web LightInject container type,
+1 -1
View File
@@ -32,7 +32,7 @@ namespace Umbraco.Core.Composing
if (_assembliesAcceptingLoadExceptions != null)
return _assembliesAcceptingLoadExceptions;
var s = ConfigurationManager.AppSettings["Umbraco.AssembliesAcceptingLoadExceptions"];
var s = ConfigurationManager.AppSettings[Constants.AppSettings.AssembliesAcceptingLoadExceptions];
return _assembliesAcceptingLoadExceptions = string.IsNullOrWhiteSpace(s)
? Array.Empty<string>()
: s.Split(',').Select(x => x.Trim()).ToArray();
+2 -2
View File
@@ -7,8 +7,8 @@ namespace Umbraco.Core.Configuration
public CoreDebug()
{
var appSettings = System.Configuration.ConfigurationManager.AppSettings;
LogUncompletedScopes = string.Equals("true", appSettings["Umbraco.CoreDebug.LogUncompletedScopes"], StringComparison.OrdinalIgnoreCase);
DumpOnTimeoutThreadAbort = string.Equals("true", appSettings["Umbraco.CoreDebug.DumpOnTimeoutThreadAbort"], StringComparison.OrdinalIgnoreCase);
LogUncompletedScopes = string.Equals("true", appSettings[Constants.AppSettings.Debug.LogUncompletedScopes], StringComparison.OrdinalIgnoreCase);
DumpOnTimeoutThreadAbort = string.Equals("true", appSettings[Constants.AppSettings.Debug.DumpOnTimeoutThreadAbort], StringComparison.OrdinalIgnoreCase);
}
// when true, Scope logs the stack trace for any scope that gets disposed without being completed.
@@ -85,8 +85,8 @@ namespace Umbraco.Core.Configuration
{
if (_reservedUrls != null) return _reservedUrls;
var urls = ConfigurationManager.AppSettings.ContainsKey("umbracoReservedUrls")
? ConfigurationManager.AppSettings["umbracoReservedUrls"]
var urls = ConfigurationManager.AppSettings.ContainsKey(Constants.AppSettings.ReservedUrls)
? ConfigurationManager.AppSettings[Constants.AppSettings.ReservedUrls]
: string.Empty;
//ensure the built on (non-changeable) reserved paths are there at all times
@@ -107,14 +107,14 @@ namespace Umbraco.Core.Configuration
if (_reservedPaths != null) return _reservedPaths;
var reservedPaths = StaticReservedPaths;
var umbPath = ConfigurationManager.AppSettings.ContainsKey("umbracoPath") && !ConfigurationManager.AppSettings["umbracoPath"].IsNullOrWhiteSpace()
? ConfigurationManager.AppSettings["umbracoPath"]
var umbPath = ConfigurationManager.AppSettings.ContainsKey(Constants.AppSettings.Path) && !ConfigurationManager.AppSettings[Constants.AppSettings.Path].IsNullOrWhiteSpace()
? ConfigurationManager.AppSettings[Constants.AppSettings.Path]
: "~/umbraco";
//always add the umbraco path to the list
reservedPaths += umbPath.EnsureEndsWith(',');
var allPaths = ConfigurationManager.AppSettings.ContainsKey("umbracoReservedPaths")
? ConfigurationManager.AppSettings["umbracoReservedPaths"]
var allPaths = ConfigurationManager.AppSettings.ContainsKey(Constants.AppSettings.ReservedPaths)
? ConfigurationManager.AppSettings[Constants.AppSettings.ReservedPaths]
: string.Empty;
_reservedPaths = reservedPaths + allPaths;
@@ -133,8 +133,8 @@ namespace Umbraco.Core.Configuration
{
get
{
return ConfigurationManager.AppSettings.ContainsKey("umbracoContentXML")
? ConfigurationManager.AppSettings["umbracoContentXML"]
return ConfigurationManager.AppSettings.ContainsKey(Constants.AppSettings.ContentXML)
? ConfigurationManager.AppSettings[Constants.AppSettings.ContentXML]
: "~/App_Data/umbraco.config";
}
}
@@ -147,8 +147,8 @@ namespace Umbraco.Core.Configuration
{
get
{
return ConfigurationManager.AppSettings.ContainsKey("umbracoPath")
? IOHelper.ResolveUrl(ConfigurationManager.AppSettings["umbracoPath"])
return ConfigurationManager.AppSettings.ContainsKey(Constants.AppSettings.Path)
? IOHelper.ResolveUrl(ConfigurationManager.AppSettings[Constants.AppSettings.Path])
: string.Empty;
}
}
@@ -161,13 +161,13 @@ namespace Umbraco.Core.Configuration
{
get
{
return ConfigurationManager.AppSettings.ContainsKey("umbracoConfigurationStatus")
? ConfigurationManager.AppSettings["umbracoConfigurationStatus"]
return ConfigurationManager.AppSettings.ContainsKey(Constants.AppSettings.ConfigurationStatus)
? ConfigurationManager.AppSettings[Constants.AppSettings.ConfigurationStatus]
: string.Empty;
}
set
{
SaveSetting("umbracoConfigurationStatus", value);
SaveSetting(Constants.AppSettings.ConfigurationStatus, value);
}
}
@@ -249,7 +249,7 @@ namespace Umbraco.Core.Configuration
{
try
{
return int.Parse(ConfigurationManager.AppSettings["umbracoTimeOutInMinutes"]);
return int.Parse(ConfigurationManager.AppSettings[Constants.AppSettings.TimeOutInMinutes]);
}
catch
{
@@ -268,7 +268,7 @@ namespace Umbraco.Core.Configuration
{
try
{
return int.Parse(ConfigurationManager.AppSettings["umbracoVersionCheckPeriod"]);
return int.Parse(ConfigurationManager.AppSettings[Constants.AppSettings.VersionCheckPeriod]);
}
catch
{
@@ -287,7 +287,7 @@ namespace Umbraco.Core.Configuration
{
get
{
var setting = ConfigurationManager.AppSettings["umbracoLocalTempStorage"];
var setting = ConfigurationManager.AppSettings[Constants.AppSettings.LocalTempStorage];
if (!string.IsNullOrWhiteSpace(setting))
return Enum<LocalTempStorage>.Parse(setting);
@@ -304,8 +304,8 @@ namespace Umbraco.Core.Configuration
{
get
{
return ConfigurationManager.AppSettings.ContainsKey("umbracoDefaultUILanguage")
? ConfigurationManager.AppSettings["umbracoDefaultUILanguage"]
return ConfigurationManager.AppSettings.ContainsKey(Constants.AppSettings.DefaultUILanguage)
? ConfigurationManager.AppSettings[Constants.AppSettings.DefaultUILanguage]
: string.Empty;
}
}
@@ -322,7 +322,7 @@ namespace Umbraco.Core.Configuration
{
try
{
return bool.Parse(ConfigurationManager.AppSettings["umbracoHideTopLevelNodeFromPath"]);
return bool.Parse(ConfigurationManager.AppSettings[Constants.AppSettings.HideTopLevelNodeFromPath]);
}
catch
{
@@ -340,7 +340,7 @@ namespace Umbraco.Core.Configuration
{
try
{
return bool.Parse(ConfigurationManager.AppSettings["umbracoUseHttps"]);
return bool.Parse(ConfigurationManager.AppSettings[Constants.AppSettings.UseHttps]);
}
catch
{
@@ -82,7 +82,7 @@ namespace Umbraco.Core.Configuration
try
{
// TODO: https://github.com/umbraco/Umbraco-CMS/issues/4238 - stop having version in web.config appSettings
var value = ConfigurationManager.AppSettings["umbracoConfigurationStatus"];
var value = ConfigurationManager.AppSettings[Constants.AppSettings.ConfigurationStatus];
return value.IsNullOrWhiteSpace() ? null : SemVersion.TryParse(value, out var semver) ? semver : null;
}
catch
+124
View File
@@ -0,0 +1,124 @@
using System;
namespace Umbraco.Core
{
public static partial class Constants
{
/// <summary>
/// Specific web.config AppSetting keys for Umbraco.Core application
/// </summary>
public static class AppSettings
{
// TODO: Kill me - still used in Umbraco.Core.IO.SystemFiles:27
[Obsolete("We need to kill this appsetting as we do not use XML content cache umbraco.config anymore due to NuCache")]
public const string ContentXML = "Umbraco.Core.ContentXML"; //umbracoContentXML
/// <summary>
/// TODO: FILL ME IN
/// </summary>
public const string RegisterType = "Umbraco.Core.RegisterType";
/// <summary>
/// This is used for a unit test in PublishedMediaCache
/// </summary>
public const string PublishedMediaCacheSeconds = "Umbraco.Core.PublishedMediaCacheSeconds";
/// <summary>
/// TODO: FILL ME IN
/// </summary>
public const string AssembliesAcceptingLoadExceptions = "Umbraco.Core.AssembliesAcceptingLoadExceptions";
/// <summary>
/// This will return the version number of the currently installed umbraco instance
/// </summary>
/// <remarks>
/// Umbraco will automatically set & modify this value when installing & upgrading
/// </remarks>
public const string ConfigurationStatus = "Umbraco.Core.ConfigurationStatus";
/// <summary>
/// Gets the path to umbraco's root directory (/umbraco by default).
/// </summary>
public const string Path = "Umbraco.Core.Path";
/// <summary>
/// The reserved urls from web.config.
/// </summary>
public const string ReservedUrls = "Umbraco.Core.ReservedUrls";
/// <summary>
/// The reserved paths from web.config
/// </summary>
public const string ReservedPaths = "Umbraco.Core.ReservedPaths";
/// <summary>
/// Set the timeout for the Umbraco backoffice in minutes
/// </summary>
public const string TimeOutInMinutes = "Umbraco.Core.TimeOutInMinutes";
/// <summary>
/// The number of days to check for a new version of Umbraco
/// </summary>
/// <remarks>
/// Default is set to 7. Setting this to 0 will never check
/// This is used to help track statistics
/// </remarks>
public const string VersionCheckPeriod = "Umbraco.Core.VersionCheckPeriod";
/// <summary>
/// This is the location type to store temporary files such as cache files or other localized files for a given machine
/// </summary>
/// <remarks>
/// Currently used for the xml cache file and the plugin cache files
/// </remarks>
public const string LocalTempStorage = "Umbraco.Core.LocalTempStorage";
/// <summary>
/// The default UI language of the backoffice such as 'en-US'
/// </summary>
public const string DefaultUILanguage = "Umbraco.Core.DefaultUILanguage";
/// <summary>
/// A true/false value indicating whether umbraco should hide top level nodes from generated urls.
/// </summary>
public const string HideTopLevelNodeFromPath = "Umbraco.Core.HideTopLevelNodeFromPath";
/// <summary>
/// A true or false indicating whether umbraco should force a secure (https) connection to the backoffice.
/// </summary>
public const string UseHttps = "Umbraco.Core.UseHttps";
/// <summary>
/// TODO: FILL ME IN
/// </summary>
public const string DisableElectionForSingleServer = "Umbraco.Core.DisableElectionForSingleServer";
/// <summary>
/// Debug specific web.config AppSetting keys for Umbraco
/// </summary>
/// <remarks>
/// Do not use these keys in a production environment
/// </remarks>
public static class Debug
{
/// <summary>
/// When set to true, Scope logs the stack trace for any scope that gets disposed without being completed.
/// this helps troubleshooting rogue scopes that we forget to complete
/// </summary>
public const string LogUncompletedScopes = "Umbraco.Core.Debug.LogUncompletedScopes";
/// <summary>
/// When set to true, the Logger creates a mini dump of w3wp in ~/App_Data/MiniDump whenever it logs
/// an error due to a ThreadAbortException that is due to a timeout.
/// </summary>
public const string DumpOnTimeoutThreadAbort = "Umbraco.Core.Debug.DumpOnTimeoutThreadAbort";
/// <summary>
/// TODO: FILL ME IN
/// </summary>
public const string DatabaseFactoryServerVersion = "Umbraco.Core.Debug.DatabaseFactoryServerVersion";
}
}
}
}
+14 -20
View File
@@ -129,7 +129,7 @@ namespace Umbraco.Core
}
return false;
}
/// <summary>
/// Returns properties that do not belong to a group
/// </summary>
@@ -158,16 +158,6 @@ namespace Umbraco.Core
.Contains(property.PropertyTypeId));
}
public static IContentTypeComposition GetContentType(this IContentBase contentBase)
{
if (contentBase == null) throw new ArgumentNullException(nameof(contentBase));
if (contentBase is IContent content) return content.ContentType;
if (contentBase is IMedia media) return media.ContentType;
if (contentBase is IMember member) return member.ContentType;
throw new NotSupportedException("Unsupported IContentBase implementation: " + contentBase.GetType().FullName + ".");
}
#region SetValue for setting file contents
/// <summary>
@@ -176,7 +166,7 @@ namespace Umbraco.Core
/// <remarks>This really is for FileUpload fields only, and should be obsoleted. For anything else,
/// you need to store the file by yourself using Store and then figure out
/// how to deal with auto-fill properties (if any) and thumbnails (if any) by yourself.</remarks>
public static void SetValue(this IContentBase content, string propertyTypeAlias, string filename, Stream filestream, string culture = null, string segment = null)
public static void SetValue(this IContentBase content, IContentTypeBaseServiceProvider contentTypeBaseServiceProvider, string propertyTypeAlias, string filename, Stream filestream, string culture = null, string segment = null)
{
if (filename == null || filestream == null) return;
@@ -185,12 +175,12 @@ namespace Umbraco.Core
if (string.IsNullOrWhiteSpace(filename)) return;
filename = filename.ToLower();
SetUploadFile(content, propertyTypeAlias, filename, filestream, culture, segment);
SetUploadFile(content,contentTypeBaseServiceProvider, propertyTypeAlias, filename, filestream, culture, segment);
}
private static void SetUploadFile(this IContentBase content, string propertyTypeAlias, string filename, Stream filestream, string culture = null, string segment = null)
private static void SetUploadFile(this IContentBase content, IContentTypeBaseServiceProvider contentTypeBaseServiceProvider, string propertyTypeAlias, string filename, Stream filestream, string culture = null, string segment = null)
{
var property = GetProperty(content, propertyTypeAlias);
var property = GetProperty(content, contentTypeBaseServiceProvider, propertyTypeAlias);
// Fixes https://github.com/umbraco/Umbraco-CMS/issues/3937 - Assigning a new file to an
// existing IMedia with extension SetValue causes exception 'Illegal characters in path'
@@ -211,12 +201,14 @@ namespace Umbraco.Core
}
// gets or creates a property for a content item.
private static Property GetProperty(IContentBase content, string propertyTypeAlias)
private static Property GetProperty(IContentBase content, IContentTypeBaseServiceProvider contentTypeBaseServiceProvider, string propertyTypeAlias)
{
var property = content.Properties.FirstOrDefault(x => x.Alias.InvariantEquals(propertyTypeAlias));
if (property != null) return property;
var propertyType = content.GetContentType().CompositionPropertyTypes
var contentTypeService = contentTypeBaseServiceProvider.For(content);
var contentType = contentTypeService.Get(content.ContentTypeId);
var propertyType = contentType.CompositionPropertyTypes
.FirstOrDefault(x => x.Alias.InvariantEquals(propertyTypeAlias));
if (propertyType == null)
throw new Exception("No property type exists with alias " + propertyTypeAlias + ".");
@@ -242,9 +234,11 @@ namespace Umbraco.Core
/// the "folder number" that was assigned to the previous file referenced by the property,
/// if any.</para>
/// </remarks>
public static string StoreFile(this IContentBase content, string propertyTypeAlias, string filename, Stream filestream, string filepath)
public static string StoreFile(this IContentBase content, IContentTypeBaseServiceProvider contentTypeBaseServiceProvider, string propertyTypeAlias, string filename, Stream filestream, string filepath)
{
var propertyType = content.GetContentType()
var contentTypeService = contentTypeBaseServiceProvider.For(content);
var contentType = contentTypeService.Get(content.ContentTypeId);
var propertyType = contentType
.CompositionPropertyTypes.FirstOrDefault(x => x.Alias.InvariantEquals(propertyTypeAlias));
if (propertyType == null) throw new ArgumentException("Invalid property type alias " + propertyTypeAlias + ".");
return MediaFileSystem.StoreFile(content, propertyType, filename, filestream, filepath);
@@ -325,7 +319,7 @@ namespace Umbraco.Core
{
return serializer.Serialize(content, false, false);
}
/// <summary>
/// Creates the xml representation for the <see cref="IMedia"/> object
@@ -9,6 +9,16 @@ namespace Umbraco.Core
/// </summary>
public static class ContentVariationExtensions
{
/// <summary>
/// Determines whether the content type is invariant.
/// </summary>
public static bool VariesByNothing(this ISimpleContentType contentType) => contentType.Variations.VariesByNothing();
/// <summary>
/// Determines whether the content type varies by culture.
/// </summary>
public static bool VariesByCulture(this ISimpleContentType contentType) => contentType.Variations.VariesByCulture();
/// <summary>
/// Determines whether the content type is invariant.
/// </summary>
+3 -2
View File
@@ -8,7 +8,8 @@ namespace Umbraco.Core.IO
public class SystemFiles
{
public static string TinyMceConfig => SystemDirectories.Config + "/tinyMceConfig.config";
// TODO: Kill this off we don't have umbraco.config XML cache we now have NuCache
public static string GetContentCacheXml(IGlobalSettings globalSettings)
{
switch (globalSettings.LocalTempStorageLocation)
@@ -24,7 +25,7 @@ namespace Umbraco.Core.IO
appDomainHash);
return Path.Combine(cachePath, "umbraco.config");
case LocalTempStorage.Default:
return IOHelper.ReturnPath("umbracoContentXML", "~/App_Data/umbraco.config");
return IOHelper.ReturnPath(Constants.AppSettings.ContentXML, "~/App_Data/umbraco.config");
default:
throw new ArgumentOutOfRangeException();
}
@@ -211,13 +211,13 @@ namespace Umbraco.Core.Migrations.Install
private void CreatePropertyTypeData()
{
_database.Insert(Constants.DatabaseSchema.Tables.PropertyType, "id", false, new PropertyTypeDto { Id = 6, UniqueId = 6.ToGuid(), DataTypeId = 1043, ContentTypeId = 1032, PropertyTypeGroupId = 3, Alias = Constants.Conventions.Media.File, Name = "Upload image", SortOrder = 0, Mandatory = false, ValidationRegExp = null, Description = null, Variations = (byte) ContentVariation.Nothing });
_database.Insert(Constants.DatabaseSchema.Tables.PropertyType, "id", false, new PropertyTypeDto { Id = 7, UniqueId = 7.ToGuid(), DataTypeId = Constants.DataTypes.LabelInt, ContentTypeId = 1032, PropertyTypeGroupId = 3, Alias = Constants.Conventions.Media.Width, Name = "Width", SortOrder = 0, Mandatory = false, ValidationRegExp = null, Description = null, Variations = (byte) ContentVariation.Nothing });
_database.Insert(Constants.DatabaseSchema.Tables.PropertyType, "id", false, new PropertyTypeDto { Id = 8, UniqueId = 8.ToGuid(), DataTypeId = Constants.DataTypes.LabelInt, ContentTypeId = 1032, PropertyTypeGroupId = 3, Alias = Constants.Conventions.Media.Height, Name = "Height", SortOrder = 0, Mandatory = false, ValidationRegExp = null, Description = null, Variations = (byte) ContentVariation.Nothing });
_database.Insert(Constants.DatabaseSchema.Tables.PropertyType, "id", false, new PropertyTypeDto { Id = 9, UniqueId = 9.ToGuid(), DataTypeId = Constants.DataTypes.LabelBigint, ContentTypeId = 1032, PropertyTypeGroupId = 3, Alias = Constants.Conventions.Media.Bytes, Name = "Size", SortOrder = 0, Mandatory = false, ValidationRegExp = null, Description = null, Variations = (byte) ContentVariation.Nothing });
_database.Insert(Constants.DatabaseSchema.Tables.PropertyType, "id", false, new PropertyTypeDto { Id = 7, UniqueId = 7.ToGuid(), DataTypeId = Constants.DataTypes.LabelInt, ContentTypeId = 1032, PropertyTypeGroupId = 3, Alias = Constants.Conventions.Media.Width, Name = "Width", SortOrder = 0, Mandatory = false, ValidationRegExp = null, Description = "in pixels", Variations = (byte) ContentVariation.Nothing });
_database.Insert(Constants.DatabaseSchema.Tables.PropertyType, "id", false, new PropertyTypeDto { Id = 8, UniqueId = 8.ToGuid(), DataTypeId = Constants.DataTypes.LabelInt, ContentTypeId = 1032, PropertyTypeGroupId = 3, Alias = Constants.Conventions.Media.Height, Name = "Height", SortOrder = 0, Mandatory = false, ValidationRegExp = null, Description = "in pixels", Variations = (byte) ContentVariation.Nothing });
_database.Insert(Constants.DatabaseSchema.Tables.PropertyType, "id", false, new PropertyTypeDto { Id = 9, UniqueId = 9.ToGuid(), DataTypeId = Constants.DataTypes.LabelBigint, ContentTypeId = 1032, PropertyTypeGroupId = 3, Alias = Constants.Conventions.Media.Bytes, Name = "Size", SortOrder = 0, Mandatory = false, ValidationRegExp = null, Description = "in bytes", Variations = (byte) ContentVariation.Nothing });
_database.Insert(Constants.DatabaseSchema.Tables.PropertyType, "id", false, new PropertyTypeDto { Id = 10, UniqueId = 10.ToGuid(), DataTypeId = -92, ContentTypeId = 1032, PropertyTypeGroupId = 3, Alias = Constants.Conventions.Media.Extension, Name = "Type", SortOrder = 0, Mandatory = false, ValidationRegExp = null, Description = null, Variations = (byte) ContentVariation.Nothing });
_database.Insert(Constants.DatabaseSchema.Tables.PropertyType, "id", false, new PropertyTypeDto { Id = 24, UniqueId = 24.ToGuid(), DataTypeId = -90, ContentTypeId = 1033, PropertyTypeGroupId = 4, Alias = Constants.Conventions.Media.File, Name = "Upload file", SortOrder = 0, Mandatory = false, ValidationRegExp = null, Description = null, Variations = (byte) ContentVariation.Nothing });
_database.Insert(Constants.DatabaseSchema.Tables.PropertyType, "id", false, new PropertyTypeDto { Id = 25, UniqueId = 25.ToGuid(), DataTypeId = -92, ContentTypeId = 1033, PropertyTypeGroupId = 4, Alias = Constants.Conventions.Media.Extension, Name = "Type", SortOrder = 0, Mandatory = false, ValidationRegExp = null, Description = null, Variations = (byte) ContentVariation.Nothing });
_database.Insert(Constants.DatabaseSchema.Tables.PropertyType, "id", false, new PropertyTypeDto { Id = 26, UniqueId = 26.ToGuid(), DataTypeId = Constants.DataTypes.LabelBigint, ContentTypeId = 1033, PropertyTypeGroupId = 4, Alias = Constants.Conventions.Media.Bytes, Name = "Size", SortOrder = 0, Mandatory = false, ValidationRegExp = null, Description = null, Variations = (byte) ContentVariation.Nothing });
_database.Insert(Constants.DatabaseSchema.Tables.PropertyType, "id", false, new PropertyTypeDto { Id = 26, UniqueId = 26.ToGuid(), DataTypeId = Constants.DataTypes.LabelBigint, ContentTypeId = 1033, PropertyTypeGroupId = 4, Alias = Constants.Conventions.Media.Bytes, Name = "Size", SortOrder = 0, Mandatory = false, ValidationRegExp = null, Description = "in bytes", Variations = (byte) ContentVariation.Nothing });
//membership property types
_database.Insert(Constants.DatabaseSchema.Tables.PropertyType, "id", false, new PropertyTypeDto { Id = 28, UniqueId = 28.ToGuid(), DataTypeId = -89, ContentTypeId = 1044, PropertyTypeGroupId = 11, Alias = Constants.Conventions.Member.Comments, Name = Constants.Conventions.Member.CommentsLabel, SortOrder = 0, Mandatory = false, ValidationRegExp = null, Description = null, Variations = (byte) ContentVariation.Nothing });
_database.Insert(Constants.DatabaseSchema.Tables.PropertyType, "id", false, new PropertyTypeDto { Id = 29, UniqueId = 29.ToGuid(), DataTypeId = Constants.DataTypes.LabelInt, ContentTypeId = 1044, PropertyTypeGroupId = 11, Alias = Constants.Conventions.Member.FailedPasswordAttempts, Name = Constants.Conventions.Member.FailedPasswordAttemptsLabel, SortOrder = 1, Mandatory = false, ValidationRegExp = null, Description = null, Variations = (byte) ContentVariation.Nothing });
@@ -36,8 +36,8 @@ namespace Umbraco.Core.Migrations.Upgrade
get
{
// no state in database yet - assume we have something in web.config that makes some sense
if (!SemVersion.TryParse(ConfigurationManager.AppSettings["umbracoConfigurationStatus"], out var currentVersion))
throw new InvalidOperationException("Could not get current version from web.config umbracoConfigurationStatus appSetting.");
if (!SemVersion.TryParse(ConfigurationManager.AppSettings[Constants.AppSettings.ConfigurationStatus], out var currentVersion))
throw new InvalidOperationException($"Could not get current version from web.config {Constants.AppSettings.ConfigurationStatus} appSetting.");
// we currently support upgrading from 7.10.0 and later
if (currentVersion < new SemVersion(7, 10))
@@ -35,8 +35,8 @@ namespace Umbraco.Core.Migrations.Upgrade
public override void AfterMigrations(IScope scope, ILogger logger)
{
// assume we have something in web.config that makes some sense = the origin version
if (!SemVersion.TryParse(ConfigurationManager.AppSettings["umbracoConfigurationStatus"], out var originVersion))
throw new InvalidOperationException("Could not get current version from web.config umbracoConfigurationStatus appSetting.");
if (!SemVersion.TryParse(ConfigurationManager.AppSettings[Constants.AppSettings.ConfigurationStatus], out var originVersion))
throw new InvalidOperationException($"Could not get current version from web.config {Constants.AppSettings.ConfigurationStatus} appSetting.");
// target version is the code version
var targetVersion = UmbracoVersion.SemanticVersion;
+8 -11
View File
@@ -15,7 +15,6 @@ namespace Umbraco.Core.Models
[DataContract(IsReference = true)]
public class Content : ContentBase, IContent
{
private IContentType _contentType;
private int? _templateId;
private ContentScheduleCollection _schedule;
private bool _published;
@@ -48,7 +47,8 @@ namespace Umbraco.Core.Models
public Content(string name, IContent parent, IContentType contentType, PropertyCollection properties, string culture = null)
: base(name, parent, contentType, properties, culture)
{
_contentType = contentType ?? throw new ArgumentNullException(nameof(contentType));
if (contentType == null) throw new ArgumentNullException(nameof(contentType));
ContentType = new SimpleContentType(contentType);
_publishedState = PublishedState.Unpublished;
PublishedVersionId = 0;
}
@@ -75,7 +75,8 @@ namespace Umbraco.Core.Models
public Content(string name, int parentId, IContentType contentType, PropertyCollection properties, string culture = null)
: base(name, parentId, contentType, properties, culture)
{
_contentType = contentType ?? throw new ArgumentNullException(nameof(contentType));
if (contentType == null) throw new ArgumentNullException(nameof(contentType));
ContentType = new SimpleContentType(contentType);
_publishedState = PublishedState.Unpublished;
PublishedVersionId = 0;
}
@@ -137,7 +138,6 @@ namespace Umbraco.Core.Models
set => SetPropertyValueAndDetectChanges(value, ref _templateId, Ps.Value.TemplateSelector);
}
/// <summary>
/// Gets or sets a value indicating whether this content item is published or not.
/// </summary>
@@ -181,7 +181,7 @@ namespace Umbraco.Core.Models
/// Gets the ContentType used by this content object
/// </summary>
[IgnoreDataMember]
public IContentType ContentType => _contentType;
public ISimpleContentType ContentType { get; private set; }
/// <inheritdoc />
[IgnoreDataMember]
@@ -423,7 +423,7 @@ namespace Umbraco.Core.Models
public void ChangeContentType(IContentType contentType)
{
ContentTypeId = contentType.Id;
_contentType = contentType;
ContentType = new SimpleContentType(contentType);
ContentTypeBase = contentType;
Properties.EnsurePropertyTypes(PropertyTypes);
@@ -442,7 +442,7 @@ namespace Umbraco.Core.Models
if(clearProperties)
{
ContentTypeId = contentType.Id;
_contentType = contentType;
ContentType = new SimpleContentType(contentType);
ContentTypeBase = contentType;
Properties.EnsureCleanPropertyTypes(PropertyTypes);
@@ -457,9 +457,6 @@ namespace Umbraco.Core.Models
public override void ResetDirtyProperties(bool rememberDirty)
{
base.ResetDirtyProperties(rememberDirty);
if (ContentType != null)
ContentType.ResetDirtyProperties(rememberDirty);
// take care of the published state
_publishedState = _published ? PublishedState.Published : PublishedState.Unpublished;
@@ -500,7 +497,7 @@ namespace Umbraco.Core.Models
var clonedContent = (Content)clone;
//need to manually clone this since it's not settable
clonedContent._contentType = (IContentType) ContentType.DeepClone();
clonedContent.ContentType = ContentType;
//if culture infos exist then deal with event bindings
if (clonedContent._publishInfos != null)
+3
View File
@@ -160,5 +160,8 @@ namespace Umbraco.Core.Models
return result;
}
/// <inheritdoc />
IContentType IContentType.DeepCloneWithResetIdentities(string newAlias) => (IContentType)DeepCloneWithResetIdentities(newAlias);
}
}
+2 -2
View File
@@ -504,9 +504,9 @@ namespace Umbraco.Core.Models
}
}
public IContentType DeepCloneWithResetIdentities(string alias)
public ContentTypeBase DeepCloneWithResetIdentities(string alias)
{
var clone = (ContentType)DeepClone();
var clone = (ContentTypeBase)DeepClone();
clone.Alias = alias;
clone.Key = Guid.Empty;
foreach (var propertyGroup in clone.PropertyGroups)
+1 -1
View File
@@ -69,7 +69,7 @@ namespace Umbraco.Core.Models
/// <summary>
/// Gets the content type of this content.
/// </summary>
IContentType ContentType { get; }
ISimpleContentType ContentType { get; }
/// <summary>
/// Gets a value indicating whether a culture is published.
@@ -0,0 +1,67 @@
namespace Umbraco.Core.Models
{
/// <summary>
/// Represents a simplified view of a content type.
/// </summary>
public interface ISimpleContentType
{
/// <summary>
/// Gets the alias of the content type.
/// </summary>
string Alias { get; }
/// <summary>
/// Gets the identifier of the content type.
/// </summary>
int Id { get; }
/// <summary>
/// Gets the default template of the content type.
/// </summary>
ITemplate DefaultTemplate { get; }
/// <summary>
/// Gets the content variation of the content type.
/// </summary>
ContentVariation Variations { get; }
/// <summary>
/// Gets the icon of the content type.
/// </summary>
string Icon { get; }
/// <summary>
/// Gets a value indicating whether the content type is a container.
/// </summary>
bool IsContainer { get; }
/// <summary>
/// Gets the name of the content type.
/// </summary>
string Name { get; }
/// <summary>
/// Gets a value indicating whether content of that type can be created at the root of the tree.
/// </summary>
bool AllowedAsRoot { get; }
/// <summary>
/// Gets a value indicating whether the content type is an element content type.
/// </summary>
bool IsElement { get; }
/// <summary>
/// Validates that a combination of culture and segment is valid for the content type properties.
/// </summary>
/// <param name="culture">The culture.</param>
/// <param name="segment">The segment.</param>
/// <param name="wildcards">A value indicating whether wildcard are supported.</param>
/// <returns>True if the combination is valid; otherwise false.</returns>
/// <remarks>
/// <para>The combination must be valid for properties of the content type. For instance, if the content type varies by culture,
/// then an invariant culture is valid, because some properties may be invariant. On the other hand, if the content type is invariant,
/// then a variant culture is invalid, because no property could possibly vary by culture.</para>
/// </remarks>
bool SupportsPropertyVariation(string culture, string segment, bool wildcards = false);
}
}
+1 -1
View File
@@ -67,7 +67,7 @@ namespace Umbraco.Core.Models
// culture
//
// I assume that, on a site, all language names should be in the SAME language, in DB,
// and that would be the umbracoDefaultUILanguage (app setting) - BUT if by accident
// and that would be the Umbraco.Core.DefaultUILanguage (app setting) - BUT if by accident
// ANY culture has been retrieved with another current thread culture - it's now corrupt
//
// so, the logic below ensures that the name always end up being the correct name
+2 -24
View File
@@ -44,29 +44,7 @@ namespace Umbraco.Core.Models
/// <inheritdoc />
public override bool IsPublishing => IsPublishingConst;
/// <summary>
/// Creates a deep clone of the current entity with its identity/alias and it's property identities reset
/// </summary>
/// <returns></returns>
public new IMediaType DeepCloneWithResetIdentities(string alias)
{
var clone = (MediaType)DeepClone();
clone.Alias = alias;
clone.Key = Guid.Empty;
foreach (var propertyGroup in clone.PropertyGroups)
{
propertyGroup.ResetIdentity();
propertyGroup.ResetDirtyProperties(false);
}
foreach (var propertyType in clone.PropertyTypes)
{
propertyType.ResetIdentity();
propertyType.ResetDirtyProperties(false);
}
clone.ResetIdentity();
clone.ResetDirtyProperties(false);
return clone;
}
/// <inheritdoc />
IMediaType IMediaType.DeepCloneWithResetIdentities(string newAlias) => (IMediaType)DeepCloneWithResetIdentities(newAlias);
}
}
@@ -0,0 +1,84 @@
namespace Umbraco.Core.Models
{
/// <summary>
/// Implements <see cref="ISimpleContentType"/>.
/// </summary>
public class SimpleContentType : ISimpleContentType
{
/// <summary>
/// Initializes a new instance of the <see cref="SimpleContentType"/> class.
/// </summary>
public SimpleContentType(IContentType contentType)
{
Id = contentType.Id;
Alias = contentType.Alias;
DefaultTemplate = contentType.DefaultTemplate;
Variations = contentType.Variations;
Icon = contentType.Icon;
IsContainer = contentType.IsContainer;
Icon = contentType.Icon;
Name = contentType.Name;
AllowedAsRoot = contentType.AllowedAsRoot;
IsElement = contentType.IsElement;
}
/// <inheritdoc />
public string Alias { get; }
/// <inheritdoc />
public int Id { get; }
/// <inheritdoc />
public ITemplate DefaultTemplate { get; }
/// <inheritdoc />
public ContentVariation Variations { get; }
/// <inheritdoc />
public string Icon { get; }
/// <inheritdoc />
public bool IsContainer { get; }
/// <inheritdoc />
public string Name { get; }
/// <inheritdoc />
public bool AllowedAsRoot { get; }
/// <inheritdoc />
public bool IsElement { get; }
/// <inheritdoc />
public bool SupportsPropertyVariation(string culture, string segment, bool wildcards = false)
{
// non-exact validation: can accept a 'null' culture if the property type varies
// by culture, and likewise for segment
// wildcard validation: can accept a '*' culture or segment
return Variations.ValidateVariation(culture, segment, false, wildcards, false);
}
protected bool Equals(SimpleContentType other)
{
return string.Equals(Alias, other.Alias) && Id == other.Id;
}
/// <inheritdoc />
public override bool Equals(object obj)
{
if (ReferenceEquals(null, obj)) return false;
if (ReferenceEquals(this, obj)) return true;
if (obj.GetType() != GetType()) return false;
return Equals((SimpleContentType) obj);
}
/// <inheritdoc />
public override int GetHashCode()
{
unchecked
{
return ((Alias != null ? Alias.GetHashCode() : 0) * 397) ^ Id;
}
}
}
}
@@ -139,7 +139,7 @@ namespace Umbraco.Core.Persistence
{
// replace NPoco database type by a more efficient one
var setting = ConfigurationManager.AppSettings["Umbraco.DatabaseFactory.ServerVersion"];
var setting = ConfigurationManager.AppSettings[Constants.AppSettings.Debug.DatabaseFactoryServerVersion];
var fromSettings = false;
if (setting.IsNullOrWhiteSpace() || !setting.StartsWith("SqlServer.")
@@ -76,7 +76,7 @@ namespace Umbraco.Core.Runtime
// TODO: this is a hack, use proper configuration!
// also: we still register the full IServerMessenger because
// even on 1 single server we can have 2 concurrent app domains
var singleServer = "true".InvariantEquals(ConfigurationManager.AppSettings["umbracoDisableElectionForSingleServer"]);
var singleServer = "true".InvariantEquals(ConfigurationManager.AppSettings[Constants.AppSettings.DisableElectionForSingleServer]);
return singleServer
? (IServerRegistrar) new SingleServerRegistrar(f.GetInstance<IRuntimeState>())
: new DatabaseServerRegistrar(
+4 -4
View File
@@ -6,15 +6,15 @@ namespace Umbraco.Core
{
public static class ServiceContextExtensions
{
public static IContentTypeServiceBase<T> GetContentTypeService<T>(this ServiceContext services)
public static IContentTypeBaseService<T> GetContentTypeService<T>(this ServiceContext services)
where T : IContentTypeComposition
{
if (typeof(T).Implements<IContentType>())
return services.ContentTypeService as IContentTypeServiceBase<T>;
return services.ContentTypeService as IContentTypeBaseService<T>;
if (typeof(T).Implements<IMediaType>())
return services.MediaTypeService as IContentTypeServiceBase<T>;
return services.MediaTypeService as IContentTypeBaseService<T>;
if (typeof(T).Implements<IMemberType>())
return services.MemberTypeService as IContentTypeServiceBase<T>;
return services.MemberTypeService as IContentTypeBaseService<T>;
throw new ArgumentException("Type " + typeof(T).FullName + " does not have a service.");
}
}
@@ -0,0 +1,22 @@
using Umbraco.Core.Models;
namespace Umbraco.Core.Services
{
/// <summary>
/// Provides the <see cref="IContentTypeBaseService"/> corresponding to an <see cref="IContentBase"/> object.
/// </summary>
public interface IContentTypeBaseServiceProvider
{
/// <summary>
/// Gets the content type service base managing types for the specified content base.
/// </summary>
/// <remarks>
/// <para>If <paramref name="contentBase"/> is an <see cref="IContent"/>, this returns the
/// <see cref="IContentTypeService"/>, and if it's an <see cref="IMedia"/>, this returns
/// the <see cref="IMediaTypeService"/>, etc.</para>
/// <para>Services are returned as <see cref="IContentTypeBaseService"/> and can be used
/// to retrieve the content / media / whatever type as <see cref="IContentTypeComposition"/>.</para>
/// </remarks>
IContentTypeBaseService For(IContentBase contentBase);
}
}
@@ -7,7 +7,7 @@ namespace Umbraco.Core.Services
/// <summary>
/// Manages <see cref="IContentType"/> objects.
/// </summary>
public interface IContentTypeService : IContentTypeServiceBase<IContentType>
public interface IContentTypeService : IContentTypeBaseService<IContentType>
{
/// <summary>
/// Gets all property type aliases.
@@ -4,15 +4,37 @@ using Umbraco.Core.Models;
namespace Umbraco.Core.Services
{
/// <summary>
/// Provides a common base interface for <see cref="IContentTypeBase"/>.
/// </summary>
public interface IContentTypeBaseService
{
/// <summary>
/// Gets a content type.
/// </summary>
IContentTypeComposition Get(int id);
}
/// <summary>
/// Provides a common base interface for <see cref="IContentTypeService"/>, <see cref="IMediaTypeService"/> and <see cref="IMemberTypeService"/>.
/// </summary>
/// <typeparam name="TItem">The type of the item.</typeparam>
public interface IContentTypeServiceBase<TItem> : IService
public interface IContentTypeBaseService<TItem> : IContentTypeBaseService, IService
where TItem : IContentTypeComposition
{
/// <summary>
/// Gets a content type.
/// </summary>
TItem Get(int id);
/// <summary>
/// Gets a content type.
/// </summary>
TItem Get(Guid key);
/// <summary>
/// Gets a content type.
/// </summary>
TItem Get(string alias);
int Count();
@@ -5,6 +5,6 @@ namespace Umbraco.Core.Services
/// <summary>
/// Manages <see cref="IMediaType"/> objects.
/// </summary>
public interface IMediaTypeService : IContentTypeServiceBase<IMediaType>
public interface IMediaTypeService : IContentTypeBaseService<IMediaType>
{ }
}
@@ -5,7 +5,7 @@ namespace Umbraco.Core.Services
/// <summary>
/// Manages <see cref="IMemberType"/> objects.
/// </summary>
public interface IMemberTypeService : IContentTypeServiceBase<IMemberType>
public interface IMemberTypeService : IContentTypeBaseService<IMemberType>
{
string GetDefault();
}
@@ -2727,7 +2727,7 @@ namespace Umbraco.Core.Services.Implement
{
if (blueprint == null) throw new ArgumentNullException(nameof(blueprint));
var contentType = blueprint.ContentType;
var contentType = _contentTypeRepository.Get(blueprint.ContentType.Id);
var content = new Content(name, -1, contentType);
content.Path = string.Concat(content.ParentId.ToString(), ",", content.Id);
@@ -0,0 +1,34 @@
using System;
using Umbraco.Core.Models;
namespace Umbraco.Core.Services.Implement
{
public class ContentTypeBaseServiceProvider : IContentTypeBaseServiceProvider
{
private readonly IContentTypeService _contentTypeService;
private readonly IMediaTypeService _mediaTypeService;
private readonly IMemberTypeService _memberTypeService;
public ContentTypeBaseServiceProvider(IContentTypeService contentTypeService, IMediaTypeService mediaTypeService, IMemberTypeService memberTypeService)
{
_contentTypeService = contentTypeService;
_mediaTypeService = mediaTypeService;
_memberTypeService = memberTypeService;
}
public IContentTypeBaseService For(IContentBase contentBase)
{
switch (contentBase)
{
case IContent _:
return _contentTypeService;
case IMedia _:
return _mediaTypeService;
case IMember _:
return _memberTypeService;
default:
throw new ArgumentException($"Invalid contentBase type: {contentBase.GetType().FullName}" , nameof(contentBase));
}
}
}
}
@@ -8,7 +8,7 @@ namespace Umbraco.Core.Services.Implement
{
public abstract class ContentTypeServiceBase<TItem, TService> : ContentTypeServiceBase
where TItem : class, IContentTypeComposition
where TService : class, IContentTypeServiceBase<TItem>
where TService : class, IContentTypeBaseService<TItem>
{
protected ContentTypeServiceBase(IScopeProvider provider, ILogger logger, IEventMessagesFactory eventMessagesFactory)
: base(provider, logger, eventMessagesFactory)
@@ -13,10 +13,10 @@ using Umbraco.Core.Services.Changes;
namespace Umbraco.Core.Services.Implement
{
public abstract class ContentTypeServiceBase<TRepository, TItem, TService> : ContentTypeServiceBase<TItem, TService>, IContentTypeServiceBase<TItem>
public abstract class ContentTypeServiceBase<TRepository, TItem, TService> : ContentTypeServiceBase<TItem, TService>, IContentTypeBaseService<TItem>
where TRepository : IContentTypeRepositoryBase<TItem>
where TItem : class, IContentTypeComposition
where TService : class, IContentTypeServiceBase<TItem>
where TService : class, IContentTypeBaseService<TItem>
{
private readonly IAuditRepository _auditRepository;
private readonly IEntityContainerRepository _containerRepository;
@@ -211,6 +211,11 @@ namespace Umbraco.Core.Services.Implement
#region Get, Has, Is, Count
IContentTypeComposition IContentTypeBaseService.Get(int id)
{
return Get(id);
}
public TItem Get(int id)
{
using (var scope = ScopeProvider.CreateScope(autoComplete: true))
@@ -594,7 +599,7 @@ namespace Umbraco.Core.Services.Implement
//var originalb = (ContentTypeCompositionBase)original;
// but we *know* it has to be a ContentTypeCompositionBase anyways
var originalb = (ContentTypeCompositionBase) (object) original;
var clone = (TItem) originalb.DeepCloneWithResetIdentities(alias);
var clone = (TItem) (object) originalb.DeepCloneWithResetIdentities(alias);
clone.Name = name;
@@ -645,7 +650,7 @@ namespace Umbraco.Core.Services.Implement
//var copyingb = (ContentTypeCompositionBase) copying;
// but we *know* it has to be a ContentTypeCompositionBase anyways
var copyingb = (ContentTypeCompositionBase) (object)copying;
copy = (TItem) copyingb.DeepCloneWithResetIdentities(alias);
copy = (TItem) (object) copyingb.DeepCloneWithResetIdentities(alias);
copy.Name = copy.Name + " (copy)"; // might not be unique
@@ -951,5 +956,7 @@ namespace Umbraco.Core.Services.Implement
}
#endregion
}
}
+13 -3
View File
@@ -32,11 +32,12 @@ namespace Umbraco.Core.Services
private readonly Lazy<IExternalLoginService> _externalLoginService;
private readonly Lazy<IRedirectUrlService> _redirectUrlService;
private readonly Lazy<IConsentService> _consentService;
private readonly Lazy<IContentTypeBaseServiceProvider> _contentTypeBaseServiceProvider;
/// <summary>
/// Initializes a new instance of the <see cref="ServiceContext"/> class with lazy services.
/// </summary>
public ServiceContext(Lazy<IPublicAccessService> publicAccessService, Lazy<IDomainService> domainService, Lazy<IAuditService> auditService, Lazy<ILocalizedTextService> localizedTextService, Lazy<ITagService> tagService, Lazy<IContentService> contentService, Lazy<IUserService> userService, Lazy<IMemberService> memberService, Lazy<IMediaService> mediaService, Lazy<IContentTypeService> contentTypeService, Lazy<IMediaTypeService> mediaTypeService, Lazy<IDataTypeService> dataTypeService, Lazy<IFileService> fileService, Lazy<ILocalizationService> localizationService, Lazy<IPackagingService> packagingService, Lazy<IServerRegistrationService> serverRegistrationService, Lazy<IEntityService> entityService, Lazy<IRelationService> relationService, Lazy<IMacroService> macroService, Lazy<IMemberTypeService> memberTypeService, Lazy<IMemberGroupService> memberGroupService, Lazy<INotificationService> notificationService, Lazy<IExternalLoginService> externalLoginService, Lazy<IRedirectUrlService> redirectUrlService, Lazy<IConsentService> consentService)
public ServiceContext(Lazy<IPublicAccessService> publicAccessService, Lazy<IDomainService> domainService, Lazy<IAuditService> auditService, Lazy<ILocalizedTextService> localizedTextService, Lazy<ITagService> tagService, Lazy<IContentService> contentService, Lazy<IUserService> userService, Lazy<IMemberService> memberService, Lazy<IMediaService> mediaService, Lazy<IContentTypeService> contentTypeService, Lazy<IMediaTypeService> mediaTypeService, Lazy<IDataTypeService> dataTypeService, Lazy<IFileService> fileService, Lazy<ILocalizationService> localizationService, Lazy<IPackagingService> packagingService, Lazy<IServerRegistrationService> serverRegistrationService, Lazy<IEntityService> entityService, Lazy<IRelationService> relationService, Lazy<IMacroService> macroService, Lazy<IMemberTypeService> memberTypeService, Lazy<IMemberGroupService> memberGroupService, Lazy<INotificationService> notificationService, Lazy<IExternalLoginService> externalLoginService, Lazy<IRedirectUrlService> redirectUrlService, Lazy<IConsentService> consentService, Lazy<IContentTypeBaseServiceProvider> contentTypeBaseServiceProvider)
{
_publicAccessService = publicAccessService;
_domainService = domainService;
@@ -63,6 +64,7 @@ namespace Umbraco.Core.Services
_externalLoginService = externalLoginService;
_redirectUrlService = redirectUrlService;
_consentService = consentService;
_contentTypeBaseServiceProvider = contentTypeBaseServiceProvider;
}
/// <summary>
@@ -96,7 +98,8 @@ namespace Umbraco.Core.Services
IExternalLoginService externalLoginService = null,
IServerRegistrationService serverRegistrationService = null,
IRedirectUrlService redirectUrlService = null,
IConsentService consentService = null)
IConsentService consentService = null,
IContentTypeBaseServiceProvider contentTypeBaseServiceProvider = null)
{
Lazy<T> Lazy<T>(T service) => service == null ? null : new Lazy<T>(() => service);
@@ -125,7 +128,9 @@ namespace Umbraco.Core.Services
Lazy(notificationService),
Lazy(externalLoginService),
Lazy(redirectUrlService),
Lazy(consentService));
Lazy(consentService),
Lazy(contentTypeBaseServiceProvider)
);
}
/// <summary>
@@ -252,5 +257,10 @@ namespace Umbraco.Core.Services
/// Gets the ConsentService.
/// </summary>
public IConsentService ConsentService => _consentService.Value;
/// <summary>
/// Gets the ContentTypeServiceBaseFactory.
/// </summary>
public IContentTypeBaseServiceProvider ContentTypeBaseServices => _contentTypeBaseServiceProvider.Value;
}
}
+5
View File
@@ -285,6 +285,7 @@
<Compile Include="Constants-Security.cs" />
<Compile Include="Constants-System.cs" />
<Compile Include="Constants-Indexes.cs" />
<Compile Include="Constants-AppSettings.cs" />
<Compile Include="Constants-Web.cs" />
<Compile Include="Constants.cs" />
<Compile Include="Composing\RegisterExtensions.cs" />
@@ -410,6 +411,7 @@
<Compile Include="Models\IAuditEntry.cs" />
<Compile Include="Models\IAuditItem.cs" />
<Compile Include="Models\IConsent.cs" />
<Compile Include="Models\ISimpleContentType.cs" />
<Compile Include="Models\Identity\IdentityMapperProfile.cs" />
<Compile Include="Models\Membership\MemberExportModel.cs" />
<Compile Include="Models\Membership\MemberExportProperty.cs" />
@@ -432,6 +434,7 @@
<Compile Include="Models\PublishedContent\VariationContext.cs" />
<Compile Include="Models\PublishedContent\ThreadCultureVariationContextAccessor.cs" />
<Compile Include="Models\PublishedContent\VariationContextAccessorExtensions.cs" />
<Compile Include="Models\SimpleContentType.cs" />
<Compile Include="Models\Trees\IBackOfficeSection.cs" />
<Compile Include="PackageActions\AllowDoctype.cs" />
<Compile Include="PackageActions\PublishRootDocument.cs" />
@@ -1343,6 +1346,7 @@
<Compile Include="Serialization\UdiRangeJsonConverter.cs" />
<Compile Include="ServiceContextExtensions.cs" />
<Compile Include="Services\IConsentService.cs" />
<Compile Include="Services\IContentTypeBaseServiceProvider.cs" />
<Compile Include="Services\IEntityXmlSerializer.cs" />
<Compile Include="Services\Implement\AuditService.cs" />
<Compile Include="Services\Changes\ContentTypeChange.cs" />
@@ -1360,6 +1364,7 @@
<Compile Include="Services\Implement\ContentTypeServiceBaseOfTItemTService.cs" />
<Compile Include="Services\Implement\ContentTypeServiceBaseOfTRepositoryTItemTService.cs" />
<Compile Include="Services\ContentTypeServiceExtensions.cs" />
<Compile Include="Services\Implement\ContentTypeBaseServiceProvider.cs" />
<Compile Include="Services\Implement\DataTypeService.cs" />
<Compile Include="Services\Implement\DomainService.cs" />
<Compile Include="Services\Implement\EntityService.cs" />
@@ -23,10 +23,10 @@ namespace Umbraco.Examine
/// <summary>
/// By default these are the member fields we index
/// </summary>
public static readonly string[] DefaultMemberIndexFields = { "id", "nodeName", "updateDate", "loginName", "email" };
public static readonly string[] DefaultMemberIndexFields = { "id", "nodeName", "updateDate", "loginName", "email", UmbracoExamineIndex.NodeKeyFieldName };
private static readonly IEnumerable<string> ValidCategories = new[] { IndexTypes.Member };
protected override IEnumerable<string> ValidIndexCategories => ValidCategories;
}
}
+8 -9
View File
@@ -4,15 +4,14 @@
</configSections>
<appSettings>
<add key="umbracoConfigurationStatus" value="6.0.0"/>
<add key="umbracoReservedUrls" value="~/config/splashes/booting.aspx,~/install/default.aspx,~/config/splashes/noNodes.aspx,~/VSEnterpriseHelper.axd,~/.well-known" />
<add key="umbracoReservedPaths" value="~/install/"/>
<add key="umbracoPath" value="~/umbraco"/>
<add key="umbracoHideTopLevelNodeFromPath" value="true"/>
<add key="umbracoUseDirectoryUrls" value="false"/>
<add key="umbracoTimeOutInMinutes" value="20"/>
<add key="umbracoDefaultUILanguage" value="en"/>
<add key="umbracoUseHttps" value="false"/>
<add key="Umbraco.Core.ConfigurationStatus" value="6.0.0"/>
<add key="Umbraco.Core.ReservedUrls" value="~/config/splashes/booting.aspx,~/install/default.aspx,~/config/splashes/noNodes.aspx,~/VSEnterpriseHelper.axd,~/.well-known" />
<add key="Umbraco.Core.ReservedPaths" value="~/install/"/>
<add key="Umbraco.Core.Path" value="~/umbraco"/>
<add key="Umbraco.Core.HideTopLevelNodeFromPath" value="true"/>
<add key="Umbraco.Core.TimeOutInMinutes" value="20"/>
<add key="Umbraco.Core.DefaultUILanguage" value="en"/>
<add key="Umbraco.Core.UseHttps" value="false"/>
<add key="dataAnnotations:dataTypeAttribute:disableRegEx" value="false"/>
</appSettings>
@@ -645,7 +645,7 @@ namespace Umbraco.Tests.LegacyXmlPublishedCache
private static void InitializeCacheConfig()
{
var value = ConfigurationManager.AppSettings["Umbraco.PublishedMediaCache.Seconds"];
var value = ConfigurationManager.AppSettings[Constants.AppSettings.PublishedMediaCacheSeconds];
int seconds;
if (int.TryParse(value, out seconds) == false)
seconds = PublishedMediaCacheTimespanSeconds;
@@ -18,7 +18,7 @@ namespace Umbraco.Tests.Manifest
var contentType = Mock.Of<IContentType>();
Mock.Get(contentType).Setup(x => x.Alias).Returns("type1");
var content = Mock.Of<IContent>();
Mock.Get(content).Setup(x => x.ContentType).Returns(contentType);
Mock.Get(content).Setup(x => x.ContentType).Returns(new SimpleContentType(contentType));
var group1 = Mock.Of<IReadOnlyUserGroup>();
Mock.Get(group1).Setup(x => x.Alias).Returns("group1");
+2 -17
View File
@@ -75,6 +75,8 @@ namespace Umbraco.Tests.Models
contentType.Variations = ContentVariation.Culture;
content.ChangeContentType(contentType);
Assert.IsFalse(content.IsPropertyDirty("PublishCultureInfos")); //hasn't been changed
Thread.Sleep(500); //The "Date" wont be dirty if the test runs too fast since it will be the same date
@@ -301,20 +303,7 @@ namespace Umbraco.Tests.Models
Assert.AreEqual(clone, content);
Assert.AreEqual(clone.Id, content.Id);
Assert.AreEqual(clone.VersionId, content.VersionId);
Assert.AreNotSame(clone.ContentType, content.ContentType);
Assert.AreEqual(clone.ContentType, content.ContentType);
Assert.AreEqual(clone.ContentType.PropertyGroups.Count, content.ContentType.PropertyGroups.Count);
for (var index = 0; index < content.ContentType.PropertyGroups.Count; index++)
{
Assert.AreNotSame(clone.ContentType.PropertyGroups[index], content.ContentType.PropertyGroups[index]);
Assert.AreEqual(clone.ContentType.PropertyGroups[index], content.ContentType.PropertyGroups[index]);
}
Assert.AreEqual(clone.ContentType.PropertyTypes.Count(), content.ContentType.PropertyTypes.Count());
for (var index = 0; index < content.ContentType.PropertyTypes.Count(); index++)
{
Assert.AreNotSame(clone.ContentType.PropertyTypes.ElementAt(index), content.ContentType.PropertyTypes.ElementAt(index));
Assert.AreEqual(clone.ContentType.PropertyTypes.ElementAt(index), content.ContentType.PropertyTypes.ElementAt(index));
}
Assert.AreEqual(clone.ContentTypeId, content.ContentTypeId);
Assert.AreEqual(clone.CreateDate, content.CreateDate);
Assert.AreEqual(clone.CreatorId, content.CreatorId);
@@ -407,8 +396,6 @@ namespace Umbraco.Tests.Models
content.Trashed = true;
content.UpdateDate = DateTime.Now;
content.WriterId = 23;
content.ContentType.UpdateDate = DateTime.Now; //update a child object
// Act
content.ResetDirtyProperties();
@@ -446,8 +433,6 @@ namespace Umbraco.Tests.Models
Assert.IsTrue(culture.Value.WasPropertyDirty("Name"));
Assert.IsTrue(culture.Value.WasPropertyDirty("Date"));
}
//verify child objects were reset too
Assert.IsTrue(content.ContentType.WasPropertyDirty("UpdateDate"));
}
[Test]
@@ -26,6 +26,7 @@ namespace Umbraco.Tests.Models.Mapping
base.Compose();
Composition.RegisterUnique(f => Mock.Of<ICultureDictionaryFactory>());
Composition.RegisterUnique(f => Mock.Of<IContentTypeService>());
}
[DataEditor("Test.Test", "Test", "~/Test.html")]
@@ -116,7 +117,12 @@ namespace Umbraco.Tests.Models.Mapping
public void To_Display_Model()
{
var contentType = MockedContentTypes.CreateSimpleContentType();
var contentTypeServiceMock = Mock.Get(Current.Services.ContentTypeService);
contentTypeServiceMock.Setup(x => x.Get(contentType.Id)).Returns(() => contentType);
var content = MockedContent.CreateSimpleContent(contentType);
FixUsers(content);
// need ids for tabs
@@ -145,6 +151,10 @@ namespace Umbraco.Tests.Models.Mapping
{
var contentType = MockedContentTypes.CreateSimpleContentType();
contentType.PropertyGroups.Clear();
var contentTypeServiceMock = Mock.Get(Current.Services.ContentTypeService);
contentTypeServiceMock.Setup(x => x.Get(contentType.Id)).Returns(() => contentType);
var content = new Content("Home", -1, contentType) { Level = 1, SortOrder = 1, CreatorId = 0, WriterId = 0 };
var result = Mapper.Map<IContent, ContentItemDisplay>(content);
@@ -176,6 +186,10 @@ namespace Umbraco.Tests.Models.Mapping
p.Id = idSeed;
idSeed++;
}
var contentTypeServiceMock = Mock.Get(Current.Services.ContentTypeService);
contentTypeServiceMock.Setup(x => x.Get(contentType.Id)).Returns(() => contentType);
var content = MockedContent.CreateSimpleContent(contentType);
FixUsers(content);
@@ -290,6 +290,7 @@ namespace Umbraco.Tests.Models
// change - now we vary by culture
contentType.Variations |= ContentVariation.Culture;
propertyType.Variations |= ContentVariation.Culture;
content.ChangeContentType(contentType);
// can set value
// and get values
@@ -409,6 +410,8 @@ namespace Umbraco.Tests.Models
contentType.Variations |= ContentVariation.Culture;
propertyType.Variations |= ContentVariation.Culture;
content.ChangeContentType(contentType);
Assert.Throws<NotSupportedException>(() => content.SetValue("prop", "a")); // invariant = no
content.SetValue("prop", "a-fr", langFr);
content.SetValue("prop", "a-uk", langUk);
@@ -301,13 +301,15 @@ namespace Umbraco.Tests.Persistence.Repositories
var emptyContentType = MockedContentTypes.CreateBasicContentType();
var hasPropertiesContentType = MockedContentTypes.CreateSimpleContentType("umbTextpage1", "Textpage");
contentTypeRepository.Save(emptyContentType);
contentTypeRepository.Save(hasPropertiesContentType);
ServiceContext.FileService.SaveTemplate(hasPropertiesContentType.DefaultTemplate); // else, FK violation on contentType!
var content1 = MockedContent.CreateSimpleContent(hasPropertiesContentType);
var content2 = MockedContent.CreateBasicContent(emptyContentType);
var content3 = MockedContent.CreateSimpleContent(hasPropertiesContentType);
contentTypeRepository.Save(emptyContentType);
contentTypeRepository.Save(hasPropertiesContentType);
repository.Save(content1);
repository.Save(content2);
repository.Save(content3);
@@ -423,9 +425,9 @@ namespace Umbraco.Tests.Persistence.Repositories
var contentType = MockedContentTypes.CreateSimpleContentType("umbTextpage2", "Textpage");
contentType.AllowedTemplates = Enumerable.Empty<ITemplate>(); // because CreateSimpleContentType assigns one already
contentType.SetDefaultTemplate(template);
var textpage = MockedContent.CreateSimpleContent(contentType);
contentTypeRepository.Save(contentType);
var textpage = MockedContent.CreateSimpleContent(contentType);
repository.Save(textpage);
@@ -124,6 +124,9 @@ namespace Umbraco.Tests.PublishedContent
Mock.Get(contentTypeService).Setup(x => x.GetAll()).Returns(contentTypes);
Mock.Get(contentTypeService).Setup(x => x.GetAll(It.IsAny<int[]>())).Returns(contentTypes);
var contentTypeServiceBaseFactory = Mock.Of<IContentTypeBaseServiceProvider>();
Mock.Get(contentTypeServiceBaseFactory).Setup(x => x.For(It.IsAny<IContentBase>())).Returns(contentTypeService);
var dataTypeService = Mock.Of<IDataTypeService>();
Mock.Get(dataTypeService).Setup(x => x.GetAll()).Returns(dataTypes);
@@ -177,6 +180,7 @@ namespace Umbraco.Tests.PublishedContent
dataSource,
globalSettings,
new SiteDomainHelper(),
contentTypeServiceBaseFactory,
Mock.Of<IEntityXmlSerializer>());
// invariant is the current default
@@ -52,7 +52,7 @@ namespace Umbraco.Tests.Runtimes
// settings
// reset the current version to 0.0.0, clear connection strings
ConfigurationManager.AppSettings["umbracoConfigurationStatus"] = "";
ConfigurationManager.AppSettings[Constants.AppSettings.ConfigurationStatus] = "";
// FIXME: we need a better management of settings here (and, true config files?)
// create the very basic and essential things we need
@@ -80,6 +80,7 @@ namespace Umbraco.Tests.Scoping
var documentRepository = Mock.Of<IDocumentRepository>();
var mediaRepository = Mock.Of<IMediaRepository>();
var memberRepository = Mock.Of<IMemberRepository>();
var contentTypeServiceBaseFactory = Current.Services.ContentTypeBaseServices;
return new PublishedSnapshotService(
options,
@@ -96,7 +97,7 @@ namespace Umbraco.Tests.Scoping
documentRepository, mediaRepository, memberRepository,
DefaultCultureAccessor,
new DatabaseDataSource(),
Factory.GetInstance<IGlobalSettings>(), new SiteDomainHelper(),
Factory.GetInstance<IGlobalSettings>(), new SiteDomainHelper(), contentTypeServiceBaseFactory,
Factory.GetInstance<IEntityXmlSerializer>());
}
@@ -26,7 +26,7 @@ namespace Umbraco.Tests.Security
public void ShouldAuthenticateRequest_When_Not_Configured()
{
//should force app ctx to show not-configured
ConfigurationManager.AppSettings.Set("umbracoConfigurationStatus", "");
ConfigurationManager.AppSettings.Set(Constants.AppSettings.ConfigurationStatus, "");
var globalSettings = TestObjects.GetGlobalSettings();
var umbracoContext = new UmbracoContext(
@@ -139,29 +139,33 @@ namespace Umbraco.Tests.Services
[Test]
public void Create_Content_From_Blueprint()
{
var contentService = ServiceContext.ContentService;
var contentTypeService = ServiceContext.ContentTypeService;
using (var scope = ScopeProvider.CreateScope(autoComplete: true))
{
var contentService = ServiceContext.ContentService;
var contentTypeService = ServiceContext.ContentTypeService;
var contentType = MockedContentTypes.CreateTextPageContentType();
ServiceContext.FileService.SaveTemplate(contentType.DefaultTemplate);
contentTypeService.Save(contentType);
var contentType = MockedContentTypes.CreateTextPageContentType();
ServiceContext.FileService.SaveTemplate(contentType.DefaultTemplate);
contentTypeService.Save(contentType);
var blueprint = MockedContent.CreateTextpageContent(contentType, "hello", -1);
blueprint.SetValue("title", "blueprint 1");
blueprint.SetValue("bodyText", "blueprint 2");
blueprint.SetValue("keywords", "blueprint 3");
blueprint.SetValue("description", "blueprint 4");
var blueprint = MockedContent.CreateTextpageContent(contentType, "hello", -1);
blueprint.SetValue("title", "blueprint 1");
blueprint.SetValue("bodyText", "blueprint 2");
blueprint.SetValue("keywords", "blueprint 3");
blueprint.SetValue("description", "blueprint 4");
contentService.SaveBlueprint(blueprint);
contentService.SaveBlueprint(blueprint);
var fromBlueprint = contentService.CreateContentFromBlueprint(blueprint, "hello world");
contentService.Save(fromBlueprint);
var fromBlueprint = contentService.CreateContentFromBlueprint(blueprint, "hello world");
contentService.Save(fromBlueprint);
Assert.IsTrue(fromBlueprint.HasIdentity);
Assert.AreEqual("blueprint 1", fromBlueprint.Properties["title"].GetValue());
Assert.AreEqual("blueprint 2", fromBlueprint.Properties["bodyText"].GetValue());
Assert.AreEqual("blueprint 3", fromBlueprint.Properties["keywords"].GetValue());
Assert.AreEqual("blueprint 4", fromBlueprint.Properties["description"].GetValue());
}
Assert.IsTrue(fromBlueprint.HasIdentity);
Assert.AreEqual("blueprint 1", fromBlueprint.Properties["title"].GetValue());
Assert.AreEqual("blueprint 2", fromBlueprint.Properties["bodyText"].GetValue());
Assert.AreEqual("blueprint 3", fromBlueprint.Properties["keywords"].GetValue());
Assert.AreEqual("blueprint 4", fromBlueprint.Properties["description"].GetValue());
}
[Test]
@@ -407,46 +407,6 @@ namespace Umbraco.Tests.Services
Assert.IsNull(doc2.GetValue("title", "en-US"));
}
[Test]
public void Deleting_Media_Type_With_Hierarchy_Of_Media_Items_Moves_Orphaned_Media_To_Recycle_Bin()
{
IMediaType contentType1 = MockedContentTypes.CreateSimpleMediaType("test1", "Test1");
ServiceContext.MediaTypeService.Save(contentType1);
IMediaType contentType2 = MockedContentTypes.CreateSimpleMediaType("test2", "Test2");
ServiceContext.MediaTypeService.Save(contentType2);
IMediaType contentType3 = MockedContentTypes.CreateSimpleMediaType("test3", "Test3");
ServiceContext.MediaTypeService.Save(contentType3);
var contentTypes = new[] { contentType1, contentType2, contentType3 };
var parentId = -1;
var ids = new List<int>();
for (int i = 0; i < 2; i++)
{
for (var index = 0; index < contentTypes.Length; index++)
{
var contentType = contentTypes[index];
var contentItem = MockedMedia.CreateSimpleMedia(contentType, "MyName_" + index + "_" + i, parentId);
ServiceContext.MediaService.Save(contentItem);
parentId = contentItem.Id;
ids.Add(contentItem.Id);
}
}
//delete the first content type, all other content of different content types should be in the recycle bin
ServiceContext.MediaTypeService.Delete(contentTypes[0]);
var found = ServiceContext.MediaService.GetByIds(ids);
Assert.AreEqual(4, found.Count());
foreach (var content in found)
{
Assert.IsTrue(content.Trashed);
}
}
[Test]
public void Deleting_Content_Type_With_Hierarchy_Of_Content_Items_Moves_Orphaned_Content_To_Recycle_Bin()
{
@@ -491,60 +451,6 @@ namespace Umbraco.Tests.Services
}
}
[Test]
public void Deleting_Media_Types_With_Hierarchy_Of_Media_Items_Doesnt_Raise_Trashed_Event_For_Deleted_Items()
{
MediaService.Trashed += MediaServiceOnTrashed;
try
{
IMediaType contentType1 = MockedContentTypes.CreateSimpleMediaType("test1", "Test1");
ServiceContext.MediaTypeService.Save(contentType1);
IMediaType contentType2 = MockedContentTypes.CreateSimpleMediaType("test2", "Test2");
ServiceContext.MediaTypeService.Save(contentType2);
IMediaType contentType3 = MockedContentTypes.CreateSimpleMediaType("test3", "Test3");
ServiceContext.MediaTypeService.Save(contentType3);
var contentTypes = new[] { contentType1, contentType2, contentType3 };
var parentId = -1;
var ids = new List<int>();
for (int i = 0; i < 2; i++)
{
for (var index = 0; index < contentTypes.Length; index++)
{
var contentType = contentTypes[index];
var contentItem = MockedMedia.CreateSimpleMedia(contentType, "MyName_" + index + "_" + i, parentId);
ServiceContext.MediaService.Save(contentItem);
parentId = contentItem.Id;
ids.Add(contentItem.Id);
}
}
foreach (var contentType in contentTypes.Reverse())
{
ServiceContext.MediaTypeService.Delete(contentType);
}
}
finally
{
MediaService.Trashed -= MediaServiceOnTrashed;
}
}
private void MediaServiceOnTrashed(IMediaService sender, MoveEventArgs<IMedia> e)
{
foreach (var item in e.MoveInfoCollection)
{
//if this item doesn't exist then Fail!
var exists = ServiceContext.MediaService.GetById(item.Entity.Id);
if (exists == null)
Assert.Fail("The item doesn't exist");
}
}
[Test]
public void Deleting_Content_Types_With_Hierarchy_Of_Content_Items_Doesnt_Raise_Trashed_Event_For_Deleted_Items_1()
{
@@ -1109,12 +1015,13 @@ namespace Umbraco.Tests.Services
var metaContentType = MockedContentTypes.CreateMetaContentType();
service.Save(metaContentType);
var simpleContentType = MockedContentTypes.CreateSimpleContentType("category", "Category", metaContentType);
var simpleContentType = MockedContentTypes.CreateSimpleContentType("category", "Category", metaContentType) as IContentType;
service.Save(simpleContentType);
var categoryId = simpleContentType.Id;
// Act
var sut = simpleContentType.DeepCloneWithResetIdentities("newcategory");
Assert.IsNotNull(sut);
service.Save(sut);
// Assert
@@ -1146,11 +1053,12 @@ namespace Umbraco.Tests.Services
var parentContentType2 = MockedContentTypes.CreateSimpleContentType("parent2", "Parent2", null, true);
service.Save(parentContentType2);
var simpleContentType = MockedContentTypes.CreateSimpleContentType("category", "Category", parentContentType1, true);
var simpleContentType = MockedContentTypes.CreateSimpleContentType("category", "Category", parentContentType1, true) as IContentType;
service.Save(simpleContentType);
// Act
var clone = simpleContentType.DeepCloneWithResetIdentities("newcategory");
Assert.IsNotNull(clone);
clone.RemoveContentType("parent1");
clone.AddContentType(parentContentType2);
clone.ParentId = parentContentType2.Id;
@@ -2114,22 +2022,6 @@ namespace Umbraco.Tests.Services
Assert.IsNull(contentType2.Description);
}
[Test]
public void Empty_Description_Is_Always_Null_After_Saving_Media_Type()
{
var service = ServiceContext.MediaTypeService;
var mediaType = MockedContentTypes.CreateSimpleMediaType("mediaType", "Media Type");
mediaType.Description = null;
service.Save(mediaType);
var mediaType2 = MockedContentTypes.CreateSimpleMediaType("mediaType2", "Media Type 2");
mediaType2.Description = string.Empty;
service.Save(mediaType2);
Assert.IsNull(mediaType.Description);
Assert.IsNull(mediaType2.Description);
}
[Test]
public void Variations_In_Compositions()
{
@@ -53,6 +53,7 @@ namespace Umbraco.Tests.Services
var documentRepository = Factory.GetInstance<IDocumentRepository>();
var mediaRepository = Mock.Of<IMediaRepository>();
var memberRepository = Mock.Of<IMemberRepository>();
var contentTypeServiceBaseFactory = Current.Services.ContentTypeBaseServices;
return new PublishedSnapshotService(
options,
@@ -69,7 +70,7 @@ namespace Umbraco.Tests.Services
documentRepository, mediaRepository, memberRepository,
DefaultCultureAccessor,
new DatabaseDataSource(),
Factory.GetInstance<IGlobalSettings>(), new SiteDomainHelper(),
Factory.GetInstance<IGlobalSettings>(), new SiteDomainHelper(), contentTypeServiceBaseFactory,
Factory.GetInstance<IEntityXmlSerializer>());
}
@@ -175,8 +176,6 @@ namespace Umbraco.Tests.Services
Assert.AreEqual("v1en", document.GetValue("value1"));
Assert.AreEqual("v2", document.GetValue("value2"));
Assert.IsFalse(document.ContentType.PropertyTypes.First(x => x.Alias == "value1").VariesByCulture());
Console.WriteLine(GetJson(document.Id));
AssertJsonStartsWith(document.Id,
"{'properties':{'value1':[{'culture':'','seg':'','val':'v1en'}],'value2':[{'culture':'','seg':'','val':'v2'}]},'cultureData':");
@@ -194,8 +193,6 @@ namespace Umbraco.Tests.Services
Assert.AreEqual("v1en", document.GetValue("value1"));
Assert.AreEqual("v2", document.GetValue("value2"));
Assert.IsFalse(document.ContentType.PropertyTypes.First(x => x.Alias == "value1").VariesByCulture());
Console.WriteLine(GetJson(document.Id));
AssertJsonStartsWith(document.Id,
"{'properties':{'value1':[{'culture':'','seg':'','val':'v1en'}],'value2':[{'culture':'','seg':'','val':'v2'}]},'cultureData':");
@@ -212,8 +209,6 @@ namespace Umbraco.Tests.Services
Assert.AreEqual("v1fr", document.GetValue("value1", "fr"));
Assert.AreEqual("v2", document.GetValue("value2"));
Assert.IsTrue(document.ContentType.PropertyTypes.First(x => x.Alias == "value1").VariesByCulture());
Console.WriteLine(GetJson(document.Id));
AssertJsonStartsWith(document.Id,
"{'properties':{'value1':[{'culture':'en','seg':'','val':'v1en'},{'culture':'fr','seg':'','val':'v1fr'}],'value2':[{'culture':'','seg':'','val':'v2'}]},'cultureData':");
@@ -288,8 +283,6 @@ namespace Umbraco.Tests.Services
Assert.AreEqual("v1", document.GetValue("value1"));
Assert.AreEqual("v2", document.GetValue("value2"));
Assert.IsFalse(document.ContentType.PropertyTypes.First(x => x.Alias == "value1").VariesByCulture());
Console.WriteLine(GetJson(document.Id));
AssertJsonStartsWith(document.Id,
"{'properties':{'value1':[{'culture':'','seg':'','val':'v1'}],'value2':[{'culture':'','seg':'','val':'v2'}]},'cultureData':");
@@ -305,8 +298,6 @@ namespace Umbraco.Tests.Services
Assert.IsNull(document.GetValue("value1", "fr"));
Assert.AreEqual("v2", document.GetValue("value2"));
Assert.IsTrue(document.ContentType.PropertyTypes.First(x => x.Alias == "value1").VariesByCulture());
Console.WriteLine(GetJson(document.Id));
AssertJsonStartsWith(document.Id,
"{'properties':{'value1':[{'culture':'en','seg':'','val':'v1'}],'value2':[{'culture':'','seg':'','val':'v2'}]},'cultureData':");
@@ -324,8 +315,6 @@ namespace Umbraco.Tests.Services
Assert.AreEqual("v1", document.GetValue("value1"));
Assert.AreEqual("v2", document.GetValue("value2"));
Assert.IsFalse(document.ContentType.PropertyTypes.First(x => x.Alias == "value1").VariesByCulture());
Console.WriteLine(GetJson(document.Id));
AssertJsonStartsWith(document.Id,
"{'properties':{'value1':[{'culture':'','seg':'','val':'v1'}],'value2':[{'culture':'','seg':'','val':'v2'}]},'cultureData':");
@@ -401,8 +390,6 @@ namespace Umbraco.Tests.Services
Assert.AreEqual("v1en", document.GetValue("value1"));
Assert.AreEqual("v2", document.GetValue("value2"));
Assert.IsFalse(document.ContentType.PropertyTypes.First(x => x.Alias == "value1").VariesByCulture());
Console.WriteLine(GetJson(document.Id));
AssertJsonStartsWith(document.Id,
"{'properties':{'value1':[{'culture':'','seg':'','val':'v1en'}],'value2':[{'culture':'','seg':'','val':'v2'}]},'cultureData':");
@@ -419,8 +406,6 @@ namespace Umbraco.Tests.Services
Assert.AreEqual("v1fr", document.GetValue("value1", "fr"));
Assert.AreEqual("v2", document.GetValue("value2"));
Assert.IsTrue(document.ContentType.PropertyTypes.First(x => x.Alias == "value1").VariesByCulture());
Console.WriteLine(GetJson(document.Id));
AssertJsonStartsWith(document.Id,
"{'properties':{'value1':[{'culture':'en','seg':'','val':'v1en'},{'culture':'fr','seg':'','val':'v1fr'}],'value2':[{'culture':'','seg':'','val':'v2'}]},'cultureData':");
@@ -439,8 +424,6 @@ namespace Umbraco.Tests.Services
Assert.IsNull(document.GetValue("value2", "fr"));
Assert.IsNull(document.GetValue("value2"));
Assert.IsTrue(document.ContentType.PropertyTypes.First(x => x.Alias == "value2").VariesByCulture());
Console.WriteLine(GetJson(document.Id));
AssertJsonStartsWith(document.Id,
"{'properties':{'value1':[{'culture':'en','seg':'','val':'v1en'},{'culture':'fr','seg':'','val':'v1fr'}],'value2':[{'culture':'en','seg':'','val':'v2'}]},'cultureData':");
@@ -0,0 +1,195 @@
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using NUnit.Framework;
using Umbraco.Core.Events;
using Umbraco.Core.Models;
using Umbraco.Core.Services;
using Umbraco.Core.Services.Implement;
using Umbraco.Tests.TestHelpers.Entities;
using Umbraco.Tests.Testing;
namespace Umbraco.Tests.Services
{
[TestFixture]
[Apartment(ApartmentState.STA)]
[UmbracoTest(Database = UmbracoTestOptions.Database.NewSchemaPerTest, PublishedRepositoryEvents = true)]
public class MediaTypeServiceTests : TestWithSomeContentBase
{
[Test]
public void Empty_Description_Is_Always_Null_After_Saving_Media_Type()
{
var mediaType = MockedContentTypes.CreateSimpleMediaType("mediaType", "Media Type");
mediaType.Description = null;
ServiceContext.MediaTypeService.Save(mediaType);
var mediaType2 = MockedContentTypes.CreateSimpleMediaType("mediaType2", "Media Type 2");
mediaType2.Description = string.Empty;
ServiceContext.MediaTypeService.Save(mediaType2);
Assert.IsNull(mediaType.Description);
Assert.IsNull(mediaType2.Description);
}
[Test]
public void Deleting_Media_Type_With_Hierarchy_Of_Media_Items_Moves_Orphaned_Media_To_Recycle_Bin()
{
IMediaType contentType1 = MockedContentTypes.CreateSimpleMediaType("test1", "Test1");
ServiceContext.MediaTypeService.Save(contentType1);
IMediaType contentType2 = MockedContentTypes.CreateSimpleMediaType("test2", "Test2");
ServiceContext.MediaTypeService.Save(contentType2);
IMediaType contentType3 = MockedContentTypes.CreateSimpleMediaType("test3", "Test3");
ServiceContext.MediaTypeService.Save(contentType3);
var contentTypes = new[] { contentType1, contentType2, contentType3 };
var parentId = -1;
var ids = new List<int>();
for (int i = 0; i < 2; i++)
{
for (var index = 0; index < contentTypes.Length; index++)
{
var contentType = contentTypes[index];
var contentItem = MockedMedia.CreateSimpleMedia(contentType, "MyName_" + index + "_" + i, parentId);
ServiceContext.MediaService.Save(contentItem);
parentId = contentItem.Id;
ids.Add(contentItem.Id);
}
}
//delete the first content type, all other content of different content types should be in the recycle bin
ServiceContext.MediaTypeService.Delete(contentTypes[0]);
var found = ServiceContext.MediaService.GetByIds(ids);
Assert.AreEqual(4, found.Count());
foreach (var content in found)
{
Assert.IsTrue(content.Trashed);
}
}
[Test]
public void Deleting_Media_Types_With_Hierarchy_Of_Media_Items_Doesnt_Raise_Trashed_Event_For_Deleted_Items()
{
MediaService.Trashed += MediaServiceOnTrashed;
try
{
IMediaType contentType1 = MockedContentTypes.CreateSimpleMediaType("test1", "Test1");
ServiceContext.MediaTypeService.Save(contentType1);
IMediaType contentType2 = MockedContentTypes.CreateSimpleMediaType("test2", "Test2");
ServiceContext.MediaTypeService.Save(contentType2);
IMediaType contentType3 = MockedContentTypes.CreateSimpleMediaType("test3", "Test3");
ServiceContext.MediaTypeService.Save(contentType3);
var contentTypes = new[] { contentType1, contentType2, contentType3 };
var parentId = -1;
var ids = new List<int>();
for (int i = 0; i < 2; i++)
{
for (var index = 0; index < contentTypes.Length; index++)
{
var contentType = contentTypes[index];
var contentItem = MockedMedia.CreateSimpleMedia(contentType, "MyName_" + index + "_" + i, parentId);
ServiceContext.MediaService.Save(contentItem);
parentId = contentItem.Id;
ids.Add(contentItem.Id);
}
}
foreach (var contentType in contentTypes.Reverse())
{
ServiceContext.MediaTypeService.Delete(contentType);
}
}
finally
{
MediaService.Trashed -= MediaServiceOnTrashed;
}
}
private void MediaServiceOnTrashed(IMediaService sender, MoveEventArgs<IMedia> e)
{
foreach (var item in e.MoveInfoCollection)
{
//if this item doesn't exist then Fail!
var exists = ServiceContext.MediaService.GetById(item.Entity.Id);
if (exists == null)
Assert.Fail("The item doesn't exist");
}
}
[Test]
public void Can_Copy_MediaType_By_Performing_Clone()
{
// Arrange
var mediaType = MockedContentTypes.CreateImageMediaType("Image2") as IMediaType;
ServiceContext.MediaTypeService.Save(mediaType);
// Act
var sut = mediaType.DeepCloneWithResetIdentities("Image2_2");
Assert.IsNotNull(sut);
ServiceContext.MediaTypeService.Save(sut);
// Assert
Assert.That(sut.HasIdentity, Is.True);
Assert.AreEqual(mediaType.ParentId, sut.ParentId);
Assert.AreEqual(mediaType.Level, sut.Level);
Assert.AreEqual(mediaType.PropertyTypes.Count(), sut.PropertyTypes.Count());
Assert.AreNotEqual(mediaType.Id, sut.Id);
Assert.AreNotEqual(mediaType.Key, sut.Key);
Assert.AreNotEqual(mediaType.Path, sut.Path);
Assert.AreNotEqual(mediaType.SortOrder, sut.SortOrder);
Assert.AreNotEqual(mediaType.PropertyTypes.First(x => x.Alias.Equals("umbracoFile")).Id, sut.PropertyTypes.First(x => x.Alias.Equals("umbracoFile")).Id);
Assert.AreNotEqual(mediaType.PropertyGroups.First(x => x.Name.Equals("Media")).Id, sut.PropertyGroups.First(x => x.Name.Equals("Media")).Id);
}
[Test]
public void Can_Copy_MediaType_To_New_Parent_By_Performing_Clone()
{
// Arrange
var parentMediaType1 = MockedContentTypes.CreateSimpleMediaType("parent1", "Parent1");
ServiceContext.MediaTypeService.Save(parentMediaType1);
var parentMediaType2 = MockedContentTypes.CreateSimpleMediaType("parent2", "Parent2", null, true);
ServiceContext.MediaTypeService.Save(parentMediaType2);
var mediaType = MockedContentTypes.CreateImageMediaType("Image2") as IMediaType;
ServiceContext.MediaTypeService.Save(mediaType);
// Act
var clone = mediaType.DeepCloneWithResetIdentities("newcategory");
Assert.IsNotNull(clone);
clone.RemoveContentType("parent1");
clone.AddContentType(parentMediaType2);
clone.ParentId = parentMediaType2.Id;
ServiceContext.MediaTypeService.Save(clone);
// Assert
Assert.That(clone.HasIdentity, Is.True);
var clonedMediaType = ServiceContext.MediaTypeService.Get(clone.Id);
var originalMediaType = ServiceContext.MediaTypeService.Get(mediaType.Id);
Assert.That(clonedMediaType.CompositionAliases().Any(x => x.Equals("parent2")), Is.True);
Assert.That(clonedMediaType.CompositionAliases().Any(x => x.Equals("parent1")), Is.False);
Assert.AreEqual(clonedMediaType.Path, "-1," + parentMediaType2.Id + "," + clonedMediaType.Id);
Assert.AreEqual(clonedMediaType.PropertyTypes.Count(), originalMediaType.PropertyTypes.Count());
Assert.AreNotEqual(clonedMediaType.ParentId, originalMediaType.ParentId);
Assert.AreEqual(clonedMediaType.ParentId, parentMediaType2.Id);
Assert.AreNotEqual(clonedMediaType.Id, originalMediaType.Id);
Assert.AreNotEqual(clonedMediaType.Key, originalMediaType.Key);
Assert.AreNotEqual(clonedMediaType.Path, originalMediaType.Path);
Assert.AreNotEqual(clonedMediaType.PropertyTypes.First(x => x.Alias.StartsWith("umbracoFile")).Id, originalMediaType.PropertyTypes.First(x => x.Alias.StartsWith("umbracoFile")).Id);
Assert.AreNotEqual(clonedMediaType.PropertyGroups.First(x => x.Name.StartsWith("Media")).Id, originalMediaType.PropertyGroups.First(x => x.Name.StartsWith("Media")).Id);
}
}
}
@@ -150,7 +150,7 @@ namespace Umbraco.Tests.TestHelpers.ControllerTesting
urlHelper.Setup(provider => provider.GetUrl(It.IsAny<UmbracoContext>(), It.IsAny<IPublishedContent>(), It.IsAny<UrlProviderMode>(), It.IsAny<string>(), It.IsAny<Uri>()))
.Returns(UrlInfo.Url("/hello/world/1234"));
var membershipHelper = new MembershipHelper(new TestUmbracoContextAccessor(umbCtx), Mock.Of<MembershipProvider>(), Mock.Of<RoleProvider>(), Mock.Of<IMemberService>(), Mock.Of<IMemberTypeService>(), Mock.Of<IUserService>(), Mock.Of<IPublicAccessService>(), null, Mock.Of<AppCaches>(), Mock.Of<ILogger>());
var membershipHelper = new MembershipHelper(new TestUmbracoContextAccessor(umbCtx), Mock.Of<MembershipProvider>(), Mock.Of<RoleProvider>(), Mock.Of<IMemberService>(), Mock.Of<IMemberTypeService>(), Mock.Of<IUserService>(), Mock.Of<IPublicAccessService>(), Mock.Of<AppCaches>(), Mock.Of<ILogger>());
var umbHelper = new UmbracoHelper(umbCtx,
Mock.Of<IPublishedContent>(),
+5 -3
View File
@@ -176,7 +176,7 @@ namespace Umbraco.Tests.TestHelpers
var propertyEditorCollection = new PropertyEditorCollection(new DataEditorCollection(Enumerable.Empty<DataEditor>()));
var compiledPackageXmlParser = new CompiledPackageXmlParser(new ConflictingPackageData(macroService.Value, fileService.Value));
return new PackagingService(
auditService.Value,
auditService.Value,
new PackagesRepository(contentService.Value, contentTypeService.Value, dataTypeService.Value, fileService.Value, macroService.Value, localizationService.Value,
new EntityXmlSerializer(contentService.Value, mediaService.Value, dataTypeService.Value, userService.Value, localizationService.Value, contentTypeService.Value, urlSegmentProviders), logger, "createdPackages.config"),
new PackagesRepository(contentService.Value, contentTypeService.Value, dataTypeService.Value, fileService.Value, macroService.Value, localizationService.Value,
@@ -188,9 +188,10 @@ namespace Umbraco.Tests.TestHelpers
new DirectoryInfo(IOHelper.GetRootDirectorySafe())));
});
var relationService = GetLazyService<IRelationService>(factory, c => new RelationService(scopeProvider, logger, eventMessagesFactory, entityService.Value, GetRepo<IRelationRepository>(c), GetRepo<IRelationTypeRepository>(c)));
var tagService = GetLazyService<ITagService>(factory, c => new TagService(scopeProvider, logger, eventMessagesFactory, GetRepo<ITagRepository>(c)));
var tagService = GetLazyService<ITagService>(factory, c => new TagService(scopeProvider, logger, eventMessagesFactory, GetRepo<ITagRepository>(c)));
var redirectUrlService = GetLazyService<IRedirectUrlService>(factory, c => new RedirectUrlService(scopeProvider, logger, eventMessagesFactory, GetRepo<IRedirectUrlRepository>(c)));
var consentService = GetLazyService<IConsentService>(factory, c => new ConsentService(scopeProvider, logger, eventMessagesFactory, GetRepo<IConsentRepository>(c)));
var contentTypeServiceBaseFactory = GetLazyService<IContentTypeBaseServiceProvider>(factory, c => new ContentTypeBaseServiceProvider(factory.GetInstance<IContentTypeService>(),factory.GetInstance<IMediaTypeService>(),factory.GetInstance<IMemberTypeService>()));
return new ServiceContext(
publicAccessService,
@@ -217,7 +218,8 @@ namespace Umbraco.Tests.TestHelpers
notificationService,
externalLoginService,
redirectUrlService,
consentService);
consentService,
contentTypeServiceBaseFactory);
}
private Lazy<T> GetLazyService<T>(IFactory container, Func<IFactory, T> ctor)
@@ -65,7 +65,7 @@ namespace Umbraco.Tests.Testing.TestingTests
Mock.Of<ITagQuery>(),
Mock.Of<ICultureDictionary>(),
Mock.Of<IUmbracoComponentRenderer>(),
new MembershipHelper(new TestUmbracoContextAccessor(umbracoContext), Mock.Of<MembershipProvider>(), Mock.Of<RoleProvider>(), Mock.Of<IMemberService>(), Mock.Of<IMemberTypeService>(), Mock.Of<IUserService>(), Mock.Of<IPublicAccessService>(), null, Mock.Of<AppCaches>(), Mock.Of<ILogger>()),
new MembershipHelper(new TestUmbracoContextAccessor(umbracoContext), Mock.Of<MembershipProvider>(), Mock.Of<RoleProvider>(), Mock.Of<IMemberService>(), Mock.Of<IMemberTypeService>(), Mock.Of<IUserService>(), Mock.Of<IPublicAccessService>(), Mock.Of<AppCaches>(), Mock.Of<ILogger>()),
ServiceContext.CreatePartial());
Assert.Pass();
}
+1 -1
View File
@@ -213,7 +213,7 @@ namespace Umbraco.Tests.Testing
// web
Composition.RegisterUnique(_ => Umbraco.Web.Composing.Current.UmbracoContextAccessor);
Composition.RegisterUnique<PublishedRouter>();
Composition.RegisterUnique<IPublishedRouter, PublishedRouter>();
Composition.WithCollectionBuilder<ContentFinderCollectionBuilder>();
Composition.RegisterUnique<IContentLastChanceFinder, TestLastChanceFinder>();
Composition.RegisterUnique<IVariationContextAccessor, TestVariationContextAccessor>();
+1
View File
@@ -147,6 +147,7 @@
<Compile Include="Services\EntityXmlSerializerTests.cs" />
<Compile Include="Packaging\CreatedPackagesRepositoryTests.cs" />
<Compile Include="Services\MemberGroupServiceTests.cs" />
<Compile Include="Services\MediaTypeServiceTests.cs" />
<Compile Include="Testing\Objects\TestDataSource.cs" />
<Compile Include="Published\PublishedSnapshotTestObjects.cs" />
<Compile Include="Published\ModelTypeTests.cs" />
@@ -70,7 +70,7 @@ namespace Umbraco.Tests.UmbracoExamine
m.GetCultureName(It.IsAny<string>()) == (string)x.Attribute("nodeName") &&
m.Path == (string)x.Attribute("path") &&
m.Properties == new PropertyCollection() &&
m.ContentType == Mock.Of<IContentType>(mt =>
m.ContentType == Mock.Of<ISimpleContentType>(mt =>
mt.Icon == "test" &&
mt.Alias == x.Name.LocalName &&
mt.Id == (int)x.Attribute("nodeType"))))
@@ -42,7 +42,7 @@ namespace Umbraco.Tests.UmbracoExamine
m.Path == (string)x.Attribute("path") &&
m.Properties == new PropertyCollection() &&
m.Published == true &&
m.ContentType == Mock.Of<IContentType>(mt =>
m.ContentType == Mock.Of<ISimpleContentType>(mt =>
mt.Icon == "test" &&
mt.Alias == x.Name.LocalName &&
mt.Id == (int)x.Attribute("nodeType"))))
@@ -82,6 +82,7 @@ namespace Umbraco.Tests.Web.Controllers
textService.Setup(x => x.Localize(It.IsAny<string>(), It.IsAny<CultureInfo>(), It.IsAny<IDictionary<string, string>>())).Returns("text");
Composition.RegisterUnique(f => Mock.Of<IContentService>());
Composition.RegisterUnique(f => Mock.Of<IContentTypeService>());
Composition.RegisterUnique(f => userServiceMock.Object);
Composition.RegisterUnique(f => entityService.Object);
Composition.RegisterUnique(f => dataTypeService.Object);
@@ -305,6 +306,9 @@ namespace Umbraco.Tests.Web.Controllers
contentServiceMock.Setup(x => x.Save(It.IsAny<IContent>(), It.IsAny<int>(), It.IsAny<bool>()))
.Returns(new OperationResult(OperationResultType.Success, new Core.Events.EventMessages())); //success
var contentTypeServiceMock = Mock.Get(Current.Services.ContentTypeService);
contentTypeServiceMock.Setup(x => x.Get(content.ContentTypeId)).Returns(() => MockedContentTypes.CreateSimpleContentType());
var propertyEditorCollection = new PropertyEditorCollection(new DataEditorCollection(Enumerable.Empty<DataEditor>()));
var usersController = new ContentController(propertyEditorCollection);
return usersController;
@@ -336,6 +340,9 @@ namespace Umbraco.Tests.Web.Controllers
contentServiceMock.Setup(x => x.Save(It.IsAny<IContent>(), It.IsAny<int>(), It.IsAny<bool>()))
.Returns(new OperationResult(OperationResultType.Success, new Core.Events.EventMessages())); //success
var contentTypeServiceMock = Mock.Get(Current.Services.ContentTypeService);
contentTypeServiceMock.Setup(x => x.Get(content.ContentTypeId)).Returns(() => MockedContentTypes.CreateSimpleContentType());
var propertyEditorCollection = new PropertyEditorCollection(new DataEditorCollection(Enumerable.Empty<DataEditor>()));
var usersController = new ContentController(propertyEditorCollection);
return usersController;
@@ -371,6 +378,9 @@ namespace Umbraco.Tests.Web.Controllers
contentServiceMock.Setup(x => x.Save(It.IsAny<IContent>(), It.IsAny<int>(), It.IsAny<bool>()))
.Returns(new OperationResult(OperationResultType.Success, new Core.Events.EventMessages())); //success
var contentTypeServiceMock = Mock.Get(Current.Services.ContentTypeService);
contentTypeServiceMock.Setup(x => x.Get(content.ContentTypeId)).Returns(() => MockedContentTypes.CreateSimpleContentType());
var propertyEditorCollection = new PropertyEditorCollection(new DataEditorCollection(Enumerable.Empty<DataEditor>()));
var usersController = new ContentController(propertyEditorCollection);
return usersController;
@@ -132,7 +132,7 @@ namespace Umbraco.Tests.Web.Mvc
Mock.Of<ITagQuery>(),
Mock.Of<ICultureDictionary>(),
Mock.Of<IUmbracoComponentRenderer>(),
new MembershipHelper(new TestUmbracoContextAccessor(umbracoContext), Mock.Of<MembershipProvider>(), Mock.Of<RoleProvider>(), Mock.Of<IMemberService>(), Mock.Of<IMemberTypeService>(), Mock.Of<IUserService>(), Mock.Of<IPublicAccessService>(), null, Mock.Of<AppCaches>(), Mock.Of<ILogger>()),
new MembershipHelper(new TestUmbracoContextAccessor(umbracoContext), Mock.Of<MembershipProvider>(), Mock.Of<RoleProvider>(), Mock.Of<IMemberService>(), Mock.Of<IMemberTypeService>(), Mock.Of<IUserService>(), Mock.Of<IPublicAccessService>(), Mock.Of<AppCaches>(), Mock.Of<ILogger>()),
ServiceContext.CreatePartial());
var ctrl = new TestSurfaceController(umbracoContext, helper);
+48 -48
View File
@@ -937,7 +937,7 @@
},
"ansi-colors": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-1.1.0.tgz",
"resolved": "http://registry.npmjs.org/ansi-colors/-/ansi-colors-1.1.0.tgz",
"integrity": "sha512-SFKX67auSNoVR38N3L+nvsPjOE0bybKTYbkf5tRvushrAPQ9V75huw0ZxBkKVeRU9kqH3d6HA4xTckbwZ4ixmA==",
"dev": true,
"requires": {
@@ -955,7 +955,7 @@
},
"ansi-escapes": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-3.1.0.tgz",
"resolved": "http://registry.npmjs.org/ansi-escapes/-/ansi-escapes-3.1.0.tgz",
"integrity": "sha512-UgAb8H9D41AQnu/PbWlCofQVcnV4Gs2bBJi9eZPxfU/hgglFh3SMDMENRIqdr7H6XFnXdoknctFByVsCOotTVw==",
"dev": true
},
@@ -1170,7 +1170,7 @@
"array-slice": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/array-slice/-/array-slice-1.1.0.tgz",
"integrity": "sha512-B1qMD3RBP7O8o0H2KbrXDyB0IccejMF15+87Lvlor12ONPRHP6gTjXMNkt/d3ZuOGbAe66hFmaCfECI24Ufp6w==",
"integrity": "sha1-42jqFfibxwaff/uJrsOmx9SsItQ=",
"dev": true
},
"array-sort": {
@@ -1216,7 +1216,7 @@
"arraybuffer.slice": {
"version": "0.0.7",
"resolved": "https://registry.npmjs.org/arraybuffer.slice/-/arraybuffer.slice-0.0.7.tgz",
"integrity": "sha512-wGUIVQXuehL5TCqQun8OW81jGzAWycqzFF8lFp+GOM5BXLYj3bKNsYC4daB7n6XjCqxQA/qgTJ+8ANR3acjrog==",
"integrity": "sha1-O7xCdd1YTMGxCAm4nU6LY6aednU=",
"dev": true
},
"asap": {
@@ -1269,7 +1269,7 @@
"async-limiter": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/async-limiter/-/async-limiter-1.0.0.tgz",
"integrity": "sha512-jp/uFnooOiO+L211eZOoSyzpOITMXx1rBITauYykG3BRYPu8h0UcxsPNB04RR5vo4Tyz3+ay17tR6JVf9qzYWg==",
"integrity": "sha1-ePrtjD0HSrgfIrTphdeehzj3IPg=",
"dev": true
},
"asynckit": {
@@ -2379,7 +2379,7 @@
},
"string_decoder": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz",
"resolved": "http://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz",
"integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==",
"dev": true,
"requires": {
@@ -2459,7 +2459,7 @@
"content-type": {
"version": "1.0.4",
"resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.4.tgz",
"integrity": "sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA==",
"integrity": "sha1-4TjMdeBAxyexlm/l5fjJruJW/js=",
"dev": true
},
"continuable-cache": {
@@ -2502,7 +2502,7 @@
"core-js": {
"version": "2.5.7",
"resolved": "https://registry.npmjs.org/core-js/-/core-js-2.5.7.tgz",
"integrity": "sha512-RszJCAxg/PP6uzXVXL6BsxSXx/B05oJAQ2vkJRjyjrEcNVycaqOmNb5OTxZPE3xa5gwZduqza6L9JOCenh/Ecw==",
"integrity": "sha1-+XJgj/DOrWi4QaFqky0LGDeRgU4=",
"dev": true
},
"core-util-is": {
@@ -3425,7 +3425,7 @@
"doctrine": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz",
"integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==",
"integrity": "sha1-XNAfwQFiG0LEzX9dGmYkNxbT850=",
"dev": true,
"requires": {
"esutils": "^2.0.2"
@@ -3953,7 +3953,7 @@
"debug": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz",
"integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==",
"integrity": "sha1-W7WgZyYotkFJVmuhaBnmFRjGcmE=",
"dev": true,
"requires": {
"ms": "2.0.0"
@@ -3989,7 +3989,7 @@
"debug": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz",
"integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==",
"integrity": "sha1-W7WgZyYotkFJVmuhaBnmFRjGcmE=",
"dev": true,
"requires": {
"ms": "2.0.0"
@@ -4153,7 +4153,7 @@
"source-map": {
"version": "0.6.1",
"resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
"integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
"integrity": "sha1-dHIq8y6WFOnCh6jQu95IteLxomM=",
"dev": true,
"optional": true
}
@@ -4248,7 +4248,7 @@
"eslint-scope": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-4.0.0.tgz",
"integrity": "sha512-1G6UTDi7Jc1ELFwnR58HV4fK9OQK4S6N985f166xqXxpjU6plxFISJa2Ba9KCQuFa8RCnj/lSFJbHo7UFDBnUA==",
"integrity": "sha1-UL8wcekzi83EMzF5Sgy1M/ATYXI=",
"dev": true,
"requires": {
"esrecurse": "^4.1.0",
@@ -4258,13 +4258,13 @@
"eslint-utils": {
"version": "1.3.1",
"resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-1.3.1.tgz",
"integrity": "sha512-Z7YjnIldX+2XMcjr7ZkgEsOj/bREONV60qYeB/bjMAqqqZ4zxKyWX+BOUkdmRmA9riiIPVvo5x86m5elviOk0Q==",
"integrity": "sha1-moUbqJ7nxGA0b5fPiTnHKYgn5RI=",
"dev": true
},
"eslint-visitor-keys": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.0.0.tgz",
"integrity": "sha512-qzm/XxIbxm/FHyH341ZrbnMUpe+5Bocte9xkmFMzPMjRaZMcXww+MpBptFvtU+79L362nqiLhekCxCxDPaUMBQ==",
"integrity": "sha1-PzGA+y4pEBdxastMnW1bXDSmqB0=",
"dev": true
},
"espree": {
@@ -4287,7 +4287,7 @@
"esquery": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/esquery/-/esquery-1.0.1.tgz",
"integrity": "sha512-SmiyZ5zIWH9VM+SRUReLS5Q8a7GxtRdxEBVZpm98rJM7Sb+A9DVCndXfkeFUd3byderg+EbDkfnevfCwynWaNA==",
"integrity": "sha1-QGxRZYsfWZGl+bYrHcJbAOPlxwg=",
"dev": true,
"requires": {
"estraverse": "^4.0.0"
@@ -4296,7 +4296,7 @@
"esrecurse": {
"version": "4.2.1",
"resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.2.1.tgz",
"integrity": "sha512-64RBB++fIOAXPw3P9cy89qfMlvZEXZkqqJkjqqXIvzP5ezRZjW+lPWjw35UX/3EhUPFYbg5ER4JYgDw4007/DQ==",
"integrity": "sha1-AHo7n9vCs7uH5IeeoZyS/b05Qs8=",
"dev": true,
"requires": {
"estraverse": "^4.1.0"
@@ -4356,7 +4356,7 @@
"eventemitter3": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-3.1.0.tgz",
"integrity": "sha512-ivIvhpq/Y0uSjcHDcOIccjmYjGLcP09MFGE7ysAwkAvkXfpZlC985pH2/ui64DKazbTW/4kN3yqozUxlXzI6cA==",
"integrity": "sha1-CQtNbNvWRe0Qv3UNS1QHlC17oWM=",
"dev": true
},
"exec-buffer": {
@@ -4571,7 +4571,7 @@
"fill-range": {
"version": "2.2.4",
"resolved": "https://registry.npmjs.org/fill-range/-/fill-range-2.2.4.tgz",
"integrity": "sha1-6x53OrsFbc2N8r/favWbizqTZWU=",
"integrity": "sha512-cnrcCbj01+j2gTG921VZPnHbjmdAf8oQV/iGeV2kZxGSyfYjjTyY79ErsK1WJWMpw6DaApEX72binqJE+/d+5Q==",
"dev": true,
"requires": {
"is-number": "^2.1.0",
@@ -5891,7 +5891,7 @@
"global-modules": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/global-modules/-/global-modules-1.0.0.tgz",
"integrity": "sha512-sKzpEkf11GpOFuw0Zzjzmt4B4UZwjOcG757PPvrfhxcLFbq0wpsgpOqxpxtxFiCG4DtG93M6XRVbF2oGdev7bg==",
"integrity": "sha1-bXcPDrUjrHgWTXK15xqIdyZcw+o=",
"dev": true,
"requires": {
"global-prefix": "^1.0.1",
@@ -6461,7 +6461,7 @@
"gulp-eslint": {
"version": "5.0.0",
"resolved": "https://registry.npmjs.org/gulp-eslint/-/gulp-eslint-5.0.0.tgz",
"integrity": "sha512-9GUqCqh85C7rP9120cpxXuZz2ayq3BZc85pCTuPJS03VQYxne0aWPIXWx6LSvsGPa3uRqtSO537vaugOh+5cXg==",
"integrity": "sha1-KiaECV93Syz3kxAmIHjFbMehK1I=",
"dev": true,
"requires": {
"eslint": "^5.0.1",
@@ -7415,7 +7415,7 @@
"has-binary2": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/has-binary2/-/has-binary2-1.0.3.tgz",
"integrity": "sha512-G1LWKhDSvhGeAQ8mPVQlqNcOB2sJdwATtZKl2pDKKHfpf/rYj24lkinxf69blJbnsvtqqNU+L3SL50vzZhXOnw==",
"integrity": "sha1-d3asYn8+p3JQz8My2rfd9eT10R0=",
"dev": true,
"requires": {
"isarray": "2.0.1"
@@ -7566,7 +7566,7 @@
"http-proxy": {
"version": "1.17.0",
"resolved": "https://registry.npmjs.org/http-proxy/-/http-proxy-1.17.0.tgz",
"integrity": "sha512-Taqn+3nNvYRfJ3bGvKfBSRwy1v6eePlm3oc/aWVxZp57DQr5Eq3xhKJi7Z4hZpS8PC3H4qI+Yly5EmFacGuA/g==",
"integrity": "sha1-etOElGWPhGBeL220Q230EPTlvpo=",
"dev": true,
"requires": {
"eventemitter3": "^3.0.0",
@@ -7860,7 +7860,7 @@
"is-absolute": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/is-absolute/-/is-absolute-1.0.0.tgz",
"integrity": "sha512-dOWoqflvcydARa360Gvv18DZ/gRuHKi2NU/wU5X1ZFzdYfH29nkiNZsF3mp4OJ3H4yo9Mx8A/uAGNzpzPN3yBA==",
"integrity": "sha1-OV4a6EsR8mrReV5zwXN45IowFXY=",
"dev": true,
"requires": {
"is-relative": "^1.0.0",
@@ -8155,7 +8155,7 @@
"is-relative": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/is-relative/-/is-relative-1.0.0.tgz",
"integrity": "sha512-Kw/ReK0iqwKeu0MITLFuj0jbPAmEiOsIwyIXvvbfa6QfmN9pkD1M+8pdk7Rl/dTKbH34/XBFMbgD4iMJhLQbGA==",
"integrity": "sha1-obtpNc6MXboei5dUubLcwCDiJg0=",
"dev": true,
"requires": {
"is-unc-path": "^1.0.0"
@@ -8164,7 +8164,7 @@
"is-resolvable": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/is-resolvable/-/is-resolvable-1.1.0.tgz",
"integrity": "sha512-qgDYXFSR5WvEfuS5dMj6oTMEbrrSaM0CrFk2Yiq/gXnBvD9pMa2jGXxyhGLfvhZpuMZe18CJpFxAt3CRs42NMg==",
"integrity": "sha1-+xj4fOH+uSUWnJpAfBkxijIG7Yg=",
"dev": true
},
"is-retry-allowed": {
@@ -8212,7 +8212,7 @@
"is-unc-path": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/is-unc-path/-/is-unc-path-1.0.0.tgz",
"integrity": "sha512-mrGpVd0fs7WWLfVsStvgF6iEJnbjDFZh9/emhRDcGWTduTfNHd9CHeUwH3gYIjdbwo4On6hunkztwOaAw0yllQ==",
"integrity": "sha1-1zHoiY7QkKEsNSrS6u1Qla0yLJ0=",
"dev": true,
"requires": {
"unc-path-regex": "^0.1.2"
@@ -8369,7 +8369,7 @@
"json-schema-traverse": {
"version": "0.4.1",
"resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz",
"integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==",
"integrity": "sha1-afaofZUTq4u4/mO9sJecRI5oRmA=",
"dev": true
},
"json-stable-stringify-without-jsonify": {
@@ -8496,7 +8496,7 @@
"source-map": {
"version": "0.6.1",
"resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
"integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
"integrity": "sha1-dHIq8y6WFOnCh6jQu95IteLxomM=",
"dev": true
}
}
@@ -9146,7 +9146,7 @@
"make-iterator": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/make-iterator/-/make-iterator-1.0.1.tgz",
"integrity": "sha512-pxiuXh0iVEq7VM7KMIhs5gxsfxCux2URptUQaXo4iZZJxBAzTPOLE2BumO5dbfVYq/hBJFBR/a1mFDmOx5AGmw==",
"integrity": "sha1-KbM/MSqo9UfEpeSQ9Wr87JkTOtY=",
"dev": true,
"requires": {
"kind-of": "^6.0.2"
@@ -9327,7 +9327,7 @@
"mimic-fn": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-1.2.0.tgz",
"integrity": "sha512-jf84uxzwiuiIVKiOLpfYk7N46TSy8ubTonmneY9vrpHNAnp0QBt2BxWV9dO3/j+BoVAb+a5G6YDPW3M5HOdMWQ==",
"integrity": "sha1-ggyGo5M0ZA6ZUWkovQP8qIBX0CI=",
"dev": true
},
"minimatch": {
@@ -12855,7 +12855,7 @@
"pluralize": {
"version": "7.0.0",
"resolved": "https://registry.npmjs.org/pluralize/-/pluralize-7.0.0.tgz",
"integrity": "sha512-ARhBOdzS3e41FbkW/XWrTEtukqqLoK5+Z/4UeDaLuSW+39JPeFgs4gCGqsrJHVZX0fUrx//4OF0K1CUGwlIFow==",
"integrity": "sha1-KYuJ34uTsCIdv0Ia0rGx6iP8Z3c=",
"dev": true
},
"posix-character-classes": {
@@ -13345,7 +13345,7 @@
"qjobs": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/qjobs/-/qjobs-1.2.0.tgz",
"integrity": "sha512-8YOJEHtxpySA3fFDyCRxA+UUV+fA+rTWnuWvylOK/NCjhY+b4ocCtmu8TtsWb+mYeU+GCHf/S66KZF/AsteKHg==",
"integrity": "sha1-xF6cYYAL0IfviNfiVkI73Unl0HE=",
"dev": true
},
"qs": {
@@ -13541,7 +13541,7 @@
},
"string_decoder": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz",
"resolved": "http://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz",
"integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==",
"dev": true,
"requires": {
@@ -14039,7 +14039,7 @@
"safer-buffer": {
"version": "2.1.2",
"resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz",
"integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==",
"integrity": "sha1-RPoWGwGHuVSd2Eu5GAL5vYOFzWo=",
"dev": true
},
"sax": {
@@ -14226,7 +14226,7 @@
"setprototypeof": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.0.tgz",
"integrity": "sha512-BvE/TwpZX4FXExxOxZyRGQQv651MSwmWKZGqvmPcRIjDqWub67kTKuIMx43cZZrS/cBBzwBcNDWoFxt2XEFIpQ==",
"integrity": "sha1-0L2FU2iHtv58DYGMuWLZ2RxU5lY=",
"dev": true
},
"shebang-command": {
@@ -14516,7 +14516,7 @@
"debug": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz",
"integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==",
"integrity": "sha1-W7WgZyYotkFJVmuhaBnmFRjGcmE=",
"dev": true,
"requires": {
"ms": "2.0.0"
@@ -14796,7 +14796,7 @@
"stream-consume": {
"version": "0.1.1",
"resolved": "https://registry.npmjs.org/stream-consume/-/stream-consume-0.1.1.tgz",
"integrity": "sha512-tNa3hzgkjEP7XbCkbRXe1jpg+ievoa0O4SCFlMOYEscGSS4JJsckGL8swUyAa/ApGU3Ae4t6Honor4HhL+tRyg==",
"integrity": "sha1-0721mMK9CugrjKx6xQsRB6eZbEg=",
"dev": true
},
"stream-shift": {
@@ -14808,7 +14808,7 @@
"streamroller": {
"version": "0.7.0",
"resolved": "https://registry.npmjs.org/streamroller/-/streamroller-0.7.0.tgz",
"integrity": "sha512-WREzfy0r0zUqp3lGO096wRuUp7ho1X6uo/7DJfTlEi0Iv/4gT7YHqXDjKC2ioVGBZtE8QzsQD9nx1nIuoZ57jQ==",
"integrity": "sha1-odG3z4PTmvsNYwSaWsv5NJO99ks=",
"dev": true,
"requires": {
"date-format": "^1.2.0",
@@ -14835,7 +14835,7 @@
"readable-stream": {
"version": "2.3.6",
"resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz",
"integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==",
"integrity": "sha1-sRwn2IuP8fvgcGQ8+UsMea4bCq8=",
"dev": true,
"requires": {
"core-util-is": "~1.0.0",
@@ -14850,7 +14850,7 @@
"string_decoder": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz",
"integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==",
"integrity": "sha1-nPFhG6YmhdcDCunkujQUnDrwP8g=",
"dev": true,
"requires": {
"safe-buffer": "~5.1.0"
@@ -14867,7 +14867,7 @@
"string-width": {
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz",
"integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==",
"integrity": "sha1-q5Pyeo3BPSjKyBXEYhQ6bZASrp4=",
"dev": true,
"requires": {
"is-fullwidth-code-point": "^2.0.0",
@@ -15409,7 +15409,7 @@
"tmp": {
"version": "0.0.33",
"resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz",
"integrity": "sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==",
"integrity": "sha1-bTQzWIl2jSGyvNoKonfO07G/rfk=",
"dev": true,
"requires": {
"os-tmpdir": "~1.0.2"
@@ -15573,7 +15573,7 @@
"type-is": {
"version": "1.6.16",
"resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.16.tgz",
"integrity": "sha512-HRkVv/5qY2G6I8iab9cI7v1bOIdhm94dVjQCPFElW9W+3GeDOSHmy2EBYe4VTApuzolPcmgFTN3ftVJRKR2J9Q==",
"integrity": "sha1-+JzjQVQcZysl7nrjxz3uOyvlAZQ=",
"dev": true,
"requires": {
"media-typer": "0.3.0",
@@ -15615,7 +15615,7 @@
"ultron": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/ultron/-/ultron-1.1.1.tgz",
"integrity": "sha512-UIEXBNeYmKptWH6z8ZnqTeS8fV74zG0/eRU9VGkpzz+LIJNs8W/zM/L+7ctCkRrgbNnnR0xxw4bKOr0cW0N0Og==",
"integrity": "sha1-n+FTahCmZKZSZqHjzPhf02MCvJw=",
"dev": true
},
"unc-path-regex": {
@@ -15777,13 +15777,13 @@
"upath": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/upath/-/upath-1.1.0.tgz",
"integrity": "sha512-bzpH/oBhoS/QI/YtbkqCg6VEiPYjSZtrHQM6/QnJS6OL9pKUFLqb3aFh4Scvwm45+7iAgiMkLhSbaZxUqmrprw==",
"integrity": "sha1-NSVll+RqWB20eT0M5H+prr/J+r0=",
"dev": true
},
"uri-js": {
"version": "4.2.2",
"resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.2.2.tgz",
"integrity": "sha512-KY9Frmirql91X2Qgjry0Wd4Y+YTdrdZheS8TFwvkbLWf/G5KNJDCh6pKL5OZctEW4+0Baa5idK2ZQuELRwPznQ==",
"integrity": "sha1-lMVA4f93KVbiKZUHwBCupsiDjrA=",
"dev": true,
"requires": {
"punycode": "^2.1.0"
@@ -16218,7 +16218,7 @@
"ws": {
"version": "3.3.3",
"resolved": "https://registry.npmjs.org/ws/-/ws-3.3.3.tgz",
"integrity": "sha512-nnWLa/NwZSt4KQJu51MYlCcSQ5g7INpOrOMt4XV8j4dqTXdmlUmSHQ8/oLC069ckre0fRsgfvsKwbTdtKLCDkA==",
"integrity": "sha1-8c+E/i1ekB686U767OeF8YeiKPI=",
"dev": true,
"requires": {
"async-limiter": "~1.0.0",
@@ -617,7 +617,7 @@
// TODO: Add "..." to save button label if there are more than one variant to publish - currently it just adds the elipses if there's more than 1 variant
if (isContentCultureVariant()) {
//before we launch the dialog we want to execute all client side validations first
if (formHelper.submitForm({ scope: $scope, action: "save" })) {
if (formHelper.submitForm({ scope: $scope, action: "openSaveDialog" })) {
var dialog = {
parentScope: $scope,
@@ -808,7 +808,7 @@
// Build the correct path so both /#/ and #/ work.
var query = 'id=' + content.id;
if ($scope.culture) {
query += "&culture=" + $scope.culture;
query += "#?culture=" + $scope.culture;
}
var redirect = Umbraco.Sys.ServerVariables.umbracoSettings.umbracoPath + '/preview/?' + query;
@@ -13,145 +13,145 @@
function addEditor(editor) {
if (!editor.style)
editor.style = {};
editor.animating = true;
showOverlayOnPrevEditor();
// start collapsing editors to make room for new ones
$timeout(function() {
var editorsElement = el[0];
// only select the editors which are allowed to be
// shown so we don't animate a lot of editors which aren't necessary
var moveEditors = editorsElement.querySelectorAll('.umb-editor:nth-last-child(-n+'+ allowedNumberOfVisibleEditors +')');
// collapse open editors before opening the new one
var collapseEditorAnimation = anime({
targets: moveEditors,
width: function(el, index, length) {
// we have to resize all small editors when they move to the
// left side so they don't leave a gap
if(el.classList.contains("umb-editor--small")) {
return "100%";
}
},
left: function(el, index, length){
if(length >= allowedNumberOfVisibleEditors) {
return index * editorIndent;
}
return (index + 1) * editorIndent;
},
var i = allowedNumberOfVisibleEditors;
var len = scope.editors.length;
while(i<len) {
var animeConfig = {
target: scope.editors[i].style,
easing: 'easeInOutQuint',
duration: 300
});
// push the new editor to the dom
scope.editors.push(editor);
});
// slide the new editor in
$timeout(function() {
var editorsElement = el[0];
// select the last editor we just pushed
var lastEditor = editorsElement.querySelector('.umb-editor:last-of-type');
var indentValue = scope.editors.length * editorIndent;
/* don't allow indent larger than what
fits the max number of visible editors */
if(scope.editors.length >= allowedNumberOfVisibleEditors) {
indentValue = allowedNumberOfVisibleEditors * editorIndent;
}
// indent all large editors
if(editor.size !== "small") {
lastEditor.style.left = indentValue + "px";
if(scope.editors[i].size !== "small") {
animeConfig.width = "100%";
}
if(len >= allowedNumberOfVisibleEditors) {
animeConfig.left = i * editorIndent;
} else {
animeConfig.left = (i + 1) * editorIndent;
}
anime(animeConfig);
i++;
}
// push the new editor to the dom
scope.editors.push(editor);
var indentValue = scope.editors.length * editorIndent;
// animation config
var addEditorAnimation = anime({
targets: lastEditor,
translateX: [100 + '%', 0],
opacity: [0, 1],
easing: 'easeInOutQuint',
duration: 300,
complete: function() {
$timeout(function(){
editor.animating = false;
});
}
});
// don't allow indent larger than what
// fits the max number of visible editors
if(scope.editors.length >= allowedNumberOfVisibleEditors) {
indentValue = allowedNumberOfVisibleEditors * editorIndent;
}
// indent all large editors
if(editor.size !== "small") {
editor.style.left = indentValue + "px";
}
editor.style._tx = 100;
//editor.style.opacity = 0;
editor.style.transform = "translateX("+editor.style._tx+"%)";
// animation config
anime({
targets: editor.style,
_tx: [100, 0],
//opacity: [0, 1],
easing: 'easeOutExpo',
duration: 480,
update: () => {
editor.style.transform = "translateX("+editor.style._tx+"%)";
scope.$digest();
},
complete: function() {
//$timeout(function(){
editor.animating = false;
scope.$digest();
//});
}
});
}
function removeEditor(editor) {
editor.animating = true;
$timeout(function(){
var editorsElement = el[0];
var lastEditor = editorsElement.querySelector('.umb-editor:last-of-type');
var removeEditorAnimation = anime({
targets: lastEditor,
translateX: [0, 100 + '%'],
opacity: [1, 0],
easing: 'easeInOutQuint',
duration: 300,
complete: function(a) {
$timeout(function(){
scope.editors.splice(-1,1);
removeOverlayFromPrevEditor();
});
}
});
expandEditors();
editor.style._tx = 0;
editor.style.transform = "translateX("+editor.style._tx+"%)";
// animation config
anime({
targets: editor.style,
_tx: [0, 100],
//opacity: [1, 0],
easing: 'easeInExpo',
duration: 360,
update: () => {
editor.style.transform = "translateX("+editor.style._tx+"%)";
scope.$digest();
},
complete: function() {
//$timeout(function(){
scope.editors.splice(-1,1);
removeOverlayFromPrevEditor();
scope.$digest();
//})
}
});
expandEditors();
}
function expandEditors() {
// expand hidden editors
$timeout(function() {
var editorsElement = el[0];
// only select the editors which are allowed to be
// shown so we don't animate a lot of editors which aren't necessary
// as the last element hasn't been removed from the dom yet we have to select the last four and then skip the last child (as it is the one closing).
var moveEditors = editorsElement.querySelectorAll('.umb-editor:nth-last-child(-n+'+ allowedNumberOfVisibleEditors + 1 +'):not(:last-child)');
var editorWidth = editorsElement.offsetWidth;
var expandEditorAnimation = anime({
targets: moveEditors,
left: function(el, index, length){
// move the editor all the way to the right if the top one is a small
if(el.classList.contains("umb-editor--small")) {
// only change the size if it is the editor on top
if(index + 1 === length) {
return editorWidth - 500;
}
} else {
return (index + 1) * editorIndent;
}
},
width: function(el, index, length) {
// set the correct size if the top editor is of type "small"
if(el.classList.contains("umb-editor--small") && index + 1 === length) {
return "500px";
}
},
var i = allowedNumberOfVisibleEditors + 1;
var len = scope.editors.length-1;
while(i<len) {
var animeConfig = {
target: scope.editors[i].style,
easing: 'easeInOutQuint',
duration: 300
});
});
}
if(scope.editors[i].size !== "small" && i === len) {
animeConfig.width = "500px";
}
if(scope.editors[i].size !== "small" && i === len) {
animeConfig.left = editorWidth - 500;
} else {
animeConfig.left = (index + 1) * editorIndent;
}
anime(animeConfig);
i++;
}
}
// show backdrop on previous editor
@@ -24,10 +24,10 @@
function umbTagsEditorController($rootScope, assetsService, umbRequestHelper, angularHelper, $timeout, $element) {
var vm = this;
let vm = this;
var typeahead;
var tagsHound;
let typeahead;
let tagsHound;
vm.$onInit = onInit;
vm.$onChanges = onChanges;
@@ -52,50 +52,52 @@
vm.isLoading = false;
//ensure that the models are formatted correctly
configureViewModel();
// Set the visible prompt to -1 to ensure it will not be visible
vm.promptIsVisible = "-1";
tagsHound = new Bloodhound({
datumTokenizer: Bloodhound.tokenizers.obj.whitespace('value'),
initialize: false,
identify: function (obj) { return obj.id; },
datumTokenizer: Bloodhound.tokenizers.obj.whitespace('text'),
queryTokenizer: Bloodhound.tokenizers.whitespace,
//pre-fetch the tags for this category
prefetch: {
url: umbRequestHelper.getApiUrl("tagsDataBaseUrl", "GetTags", { tagGroup: vm.config.group, culture: vm.culture }),
//TTL = 5 minutes
ttl: 300000,
transform: dataTransform
ttl: 300000
},
//dynamically get the tags for this category (they may have changed on the server)
remote: {
url: umbRequestHelper.getApiUrl("tagsDataBaseUrl", "GetTags", { tagGroup: vm.config.group, culture: vm.culture }),
transform: dataTransform
url: umbRequestHelper.getApiUrl("tagsDataBaseUrl", "GetTags", { tagGroup: vm.config.group, culture: vm.culture, query: "%QUERY" }),
wildcard: "%QUERY"
}
});
tagsHound.initialize(true);
//configure the type ahead
$timeout(function () {
tagsHound.initialize().then(function() {
//configure the type ahead
var sources = {
//see: https://github.com/twitter/typeahead.js/blob/master/doc/jquery_typeahead.md#options
// name = the data set name, we'll make this the tag group name
name: vm.config.group,
display: "value",
// name = the data set name, we'll make this the tag group name + culture
name: vm.config.group + (vm.culture ? vm.culture : ""),
display: "text",
//source: tagsHound
source: function (query, cb) {
source: function (query, syncCallback, asyncCallback) {
tagsHound.search(query,
function(suggestions) {
cb(removeCurrentTagsFromSuggestions(suggestions));
syncCallback(removeCurrentTagsFromSuggestions(suggestions));
}, function(suggestions) {
asyncCallback(removeCurrentTagsFromSuggestions(suggestions));
});
}
};
var opts = {
//This causes some strangeness as it duplicates the textbox, best leave off for now.
hint: false,
hint: true,
highlight: true,
cacheKey: new Date(), // Force a cache refresh each time the control is initialized
minLength: 1
@@ -104,28 +106,35 @@
typeahead = $element.find('.tags-' + vm.htmlId).typeahead(opts, sources)
.bind("typeahead:selected", function (obj, datum, name) {
angularHelper.safeApply($rootScope, function () {
addTagInternal(datum["value"]);
addTagInternal(datum["text"]);
vm.tagToAdd = "";
// clear the typed text
typeahead.typeahead('val', '');
});
}).bind("typeahead:autocompleted", function (obj, datum, name) {
angularHelper.safeApply($rootScope, function () {
addTagInternal(datum["value"]);
addTagInternal(datum["text"]);
vm.tagToAdd = "";
// clear the typed text
typeahead.typeahead('val', '');
});
}).bind("typeahead:opened", function (obj) {
});
});
});
});
}
/**
* Watch for value changes
* @param {any} changes
*/
function onChanges(changes) {
// watch for value changes externally
//when the model 'value' changes, sync the viewModel object
if (changes.value) {
if (!changes.value.isFirstChange() && changes.value.currentValue !== changes.value.previousValue) {
@@ -166,6 +175,7 @@
});
updateModelValue(vm.viewModel);
}
}
else if (angular.isArray(vm.value)) {
@@ -175,12 +185,10 @@
}
function updateModelValue(val) {
if (val) {
vm.onValueChanged({ value: val });
}
else {
vm.onValueChanged({ value: [] });
}
val = val ? val : [];
vm.onValueChanged({ value: val });
reValidate();
}
@@ -252,29 +260,19 @@
function hidePrompt() {
vm.promptIsVisible = "-1";
}
//helper method to format the data for bloodhound
function dataTransform(list) {
//transform the result to what bloodhound wants
var tagList = _.map(list, function (i) {
return { value: i.text };
});
// remove current tags from the list
return $.grep(tagList, function (tag) {
return ($.inArray(tag.value, vm.viewModel) === -1);
});
}
// helper method to remove current tags
function removeCurrentTagsFromSuggestions(suggestions) {
return $.grep(suggestions, function (suggestion) {
return ($.inArray(suggestion.value, vm.viewModel) === -1);
return ($.inArray(suggestion.text, vm.viewModel) === -1);
});
}
function reValidate() {
//this is required to re-validate
vm.tagEditorForm.tagCount.$setViewValue(vm.viewModel.length);
//this is required to re-validate for the mandatory validation
if (vm.tagEditorForm && vm.tagEditorForm.tagCount) {
vm.tagEditorForm.tagCount.$setViewValue(vm.viewModel.length);
}
}
}
@@ -6,4 +6,5 @@ angular.module('umbraco.interceptors', [])
$httpProvider.interceptors.push('securityInterceptor');
$httpProvider.interceptors.push('debugRequestInterceptor');
$httpProvider.interceptors.push('doNotPostDollarVariablesOnPostRequestInterceptor');
}]);
@@ -0,0 +1,38 @@
(function() {
'use strict';
function removeProperty(obj, propertyPrefix) {
for (var property in obj) {
if (obj.hasOwnProperty(property)) {
if (property.startsWith(propertyPrefix) && obj[property]) {
obj[property] = undefined;
}
if (typeof obj[property] == "object") {
removeProperty(obj[property], propertyPrefix);
}
}
}
}
function transform(data){
removeProperty(data, "$");
}
function doNotPostDollarVariablesRequestInterceptor($q, urlHelper) {
return {
//dealing with requests:
'request': function(config) {
if(config.method === "POST"){
transform(config.data);
}
return config;
}
};
}
angular.module('umbraco.interceptors').factory('doNotPostDollarVariablesOnPostRequestInterceptor', doNotPostDollarVariablesRequestInterceptor);
})();
@@ -28,7 +28,7 @@ function navigationService($routeParams, $location, $q, $timeout, $injector, eve
//A list of query strings defined that when changed will not cause a reload of the route
var nonRoutingQueryStrings = ["mculture", "cculture", "lq"];
var retainedQueryStrings = ["mculture"];
var retainedQueryStrings = ["mculture", "cculture"];
function setMode(mode) {
@@ -201,7 +201,8 @@ input[type="button"] {
}
// Made for Umbraco, 2019
.btn-selection {
.buttonBackground(@pinkLight, ligthen(@pinkLight, 20%), @blueExtraDark, @blueDark);
@btnSelectionBackgroundHover: darken(@pinkLight, 10%);
.buttonBackground(@pinkLight, @btnSelectionBackgroundHover, @blueExtraDark, @blueDark);
}
// Made for Umbraco, 2019, used for buttons that has to stand back.
.btn-white {
@@ -275,7 +275,7 @@ a, a:hover{
font-family: "Lato", Helvetica, Arial, sans-serif;
font-size: 13px;
line-height: 16px;
background: #413659;
background: #1b264f;
-webkit-transition: all 0.2s ease-in-out;
-moz-transition: all 0.2s ease-in-out;
transition: all 0.2s ease-in-out;
@@ -306,7 +306,7 @@ a, a:hover{
ul.sections {
display: block;
background: #413659;
background: #1b264f;
height: 100%;
position:absolute;
top: 90px;
@@ -322,7 +322,7 @@ ul.sections {
ul.sections li {
display: block;
border-left: 4px #413659 solid;
border-left: 4px #1b264f solid;
-webkit-transition: all .3s linear;
-moz-transition: all .3s linear;
transition: all .3s linear;
@@ -330,7 +330,8 @@ ul.sections li {
.fix-left-menu ul.sections li a span,
.fix-left-menu ul.sections li a i {
color: #8d869b;
color: #fff;
opacity: .7;
-webkit-transition: all .3s linear;
-moz-transition: all .3s linear;
transition: all .3s linear;
@@ -345,6 +346,11 @@ ul.sections li a {
text-align: center;
text-decoration: none;
border-bottom: 1px solid #2E2246;
&:hover {
span, i {
opacity: 1;
}
}
}
ul.sections li a i {
@@ -367,7 +373,7 @@ ul.sections li.current a i {
}
ul.sections li.current, ul.sections li:hover {
border-left: 4px #00AEA2 solid;
border-left: 4px #f5c1bc solid;
}
.fix-left-menu:hover ul.sections li a span,
@@ -27,6 +27,8 @@
// we need to do some special styling for tabs inside the dashboard header
.umb-dashboard__header .umb-tabs-nav {
margin-bottom: 0;
margin-left: 10px;
margin-right: 10px;
border: none;
}
@@ -17,13 +17,14 @@
}
.umb-editor--animating {
will-change: transform, opacity, width, left;
//will-change: transform, opacity, width, left;
will-change: transform, width, left;
}
// hide all infinite editors by default
// will be shown through animation
.umb-editors .umb-editor {
opacity: 0;
//opacity: 0;
box-shadow: 0px 0 30px 0 rgba(0,0,0,.3);
}
@@ -35,7 +36,14 @@
max-width: 500px;
}
}
@keyframes umb-editor__overlay_fade_opacity {
from {
opacity:0;
}
to {
opacity:1;
}
}
.umb-editor__overlay {
position: absolute;
top: 0;
@@ -44,4 +52,6 @@
left: 0;
background: rgba(0,0,0,0.4);
z-index: @zIndexEditor;
animation:umb-editor__overlay_fade_opacity 600ms;
}
@@ -15,10 +15,6 @@
box-shadow: 0 1px 1px 0 rgba(0,0,0,0.16);
border-radius: 3px;
color: @ui-option-type;
&:hover {
color:@ui-option-type-hover;
}
}
.umb-content-grid__item.-selected {
@@ -70,9 +66,13 @@
.umb-content-grid__item-name {
font-weight: bold;
margin-bottom: 15px;
//color: @black;
line-height: 1.4em;
display: inline-flex;
color: @ui-option-type;
&:hover {
color:@ui-option-type-hover;
}
}
.umb-content-grid__item-name:hover span {
@@ -5,7 +5,7 @@
.umb-layout-selector__active-layout {
box-sizing: border-box;
border: 1px solid transparent;
border: 1px solid @inputBorder;
cursor: pointer;
height: 30px;
width: 30px;
@@ -16,7 +16,7 @@
}
.umb-layout-selector__active-layout:hover {
border-color: @gray-8;
border-color: @inputBorderFocus;
}
.umb-layout-selector__dropdown {
@@ -90,13 +90,13 @@ input.umb-table__input {
.umb-table-body .umb-table-row {
color: @gray-5;
border-top: 1px solid @gray-8;
border-top: 1px solid @gray-9;
cursor: pointer;
font-size: 14px;
position: relative;
min-height: 52px;
&:hover {
background-color: @gray-10;
background-color: @ui-option-hover;
}
}
@@ -151,12 +151,26 @@ input.umb-table__input {
// Show checkmark when checked, hide file icon
.umb-table-row--selected {
/*
.umb-table-body__fileicon {
display: none;
}
.umb-table-body__checkicon {
display: inline-block;
}
*/
&::before {
content: "";
position: absolute;
z-index:1;
top: 1px;
left: 1px;
right: 1px;
bottom: 1px;
border: 2px solid @ui-selected-border;
box-shadow: 0 0 2px 0 fade(@ui-selected-border, 80%);
pointer-events: none;
}
}
// Table Row Styles
@@ -547,7 +547,7 @@
height: 14px;
text-align: center;
border-radius: 20px;
background: @turquoise;
background: @pinkLight;
border: 3px solid @white;
opacity: 0.8;
}
@@ -68,16 +68,7 @@ var app = angular.module("umbraco.preview", ['umbraco.resources', 'umbraco.servi
return;
}
$scope.pageId = $location.search().id || getParameterByName("id");
var culture = $location.search().culture || getParameterByName("culture");
if ($scope.pageId) {
var query = 'id=' + $scope.pageId;
if (culture) {
query += "&culture=" + culture;
}
$scope.pageUrl = "frame?" + query;
}
setPageUrl();
$scope.isOpen = false;
$scope.frameLoaded = false;
@@ -93,6 +84,19 @@ var app = angular.module("umbraco.preview", ['umbraco.resources', 'umbraco.servi
];
$scope.previewDevice = $scope.devices[0];
function setPageUrl(){
$scope.pageId = $location.search().id || getParameterByName("id");
var culture = $location.search().culture || getParameterByName("culture");
if ($scope.pageId) {
var query = 'id=' + $scope.pageId;
if (culture) {
query += "&culture=" + culture;
}
$scope.pageUrl = "frame?" + query;
}
}
/*****************************************************************************/
/* Preview devices */
/*****************************************************************************/
@@ -107,28 +111,41 @@ var app = angular.module("umbraco.preview", ['umbraco.resources', 'umbraco.servi
/*****************************************************************************/
$scope.exitPreview = function () {
window.top.location.href = "../preview/end?redir=%2f" + $scope.pageId;
var culture = $location.search().culture || getParameterByName("culture");
var relativeUrl = "/" + $scope.pageId +'?culture='+ culture;
window.top.location.href = "../preview/end?redir=" + encodeURIComponent(relativeUrl);
};
$scope.onFrameLoaded = function (iframe) {
$scope.frameLoaded = true;
configureSignalR(iframe);
}
};
/*****************************************************************************/
/* Panel managment */
/* Panel management */
/*****************************************************************************/
$scope.openPreviewDevice = function () {
$scope.showDevicesPreview = true;
}
};
/*****************************************************************************/
/* Change culture */
/*****************************************************************************/
$scope.changeCulture = function (culture) {
if($location.search().culture !== culture){
$scope.frameLoaded = false;
$location.search("culture", culture);
setPageUrl();
}
};
})
.component('previewIFrame', {
template: "<div style='width:100%;height:100%;margin:0 auto;overflow:hidden;'><iframe id='resultFrame' src='about:blank' ng-src=\"{{vm.srcDelayed}}\" frameborder='0'></iframe></div>",
template: "<div style='width:100%;height:100%;margin:0 auto;overflow:hidden;'><iframe id='resultFrame' src='about:blank' ng-src=\"{{vm.src}}\" frameborder='0'></iframe></div>",
controller: function ($element, $scope, angularHelper) {
var vm = this;
@@ -136,7 +153,6 @@ var app = angular.module("umbraco.preview", ['umbraco.resources', 'umbraco.servi
vm.$postLink = function () {
var resultFrame = $element.find("#resultFrame");
resultFrame.on("load", iframeReady);
vm.srcDelayed = vm.src;
};
function iframeReady() {
@@ -144,6 +160,7 @@ var app = angular.module("umbraco.preview", ['umbraco.resources', 'umbraco.servi
hideUmbracoPreviewBadge(iframe);
angularHelper.safeApply($scope, function () {
vm.onLoaded({ iframe: iframe });
$scope.frameLoaded = true;
});
}
@@ -153,6 +170,7 @@ var app = angular.module("umbraco.preview", ['umbraco.resources', 'umbraco.servi
}
};
},
controllerAs: "vm",
bindings: {
@@ -1,6 +1,6 @@
<div ng-controller="Umbraco.Editors.MediaPickerController as vm">
<umb-editor-view >
<umb-editor-header
name="model.title"
name-locked="true"
@@ -10,17 +10,17 @@
</umb-editor-header>
<umb-editor-container>
<form id="fileupload" method="POST" enctype="multipart/form-data" umb-image-upload="options">
<div on-drag-leave="dragLeave()" on-drag-end="dragLeave()" on-drag-enter="dragEnter()">
<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 -full-width-input"
@@ -38,111 +38,111 @@
</label>
</div>
</div>
<div class="upload-button">
<umb-button
type="button"
label-key="general_upload"
action="upload()"
<umb-button
type="button"
label-key="general_upload"
action="upload()"
disabled="lockedFolder"
button-style="info">
button-style="action">
</umb-button>
</div>
</div>
<div class="row umb-control-group" ng-show="!searchOptions.filter">
<ul class="umb-breadcrumbs">
<li ng-hide="startNodeId != -1" class="umb-breadcrumbs__ancestor">
<a href ng-click="gotoFolder()" prevent-default>Media</a>
<span class="umb-breadcrumbs__separator">&#47;</span>
</li>
<li ng-repeat="item in path" class="umb-breadcrumbs__ancestor">
<a href ng-click="gotoFolder(item)" prevent-default>{{item.name}}</a>
<span class="umb-breadcrumbs__separator">&#47;</span>
</li>
<li class="umb-breadcrumbs__ancestor" ng-show="!lockedFolder">
<a href ng-hide="showFolderInput" ng-click="showFolderInput = true">
<i class="icon icon-add small"></i>
</a>
<input type="text" class="umb-breadcrumbs__add-ancestor" ng-show="showFolderInput" ng-model="model.newFolderName" ng-keydown="enterSubmitFolder($event)"
ng-blur="submitFolder()" focus-when="{{showFolderInput}}" />
</li>
</ul>
<div class="umb-loader" ng-if="creatingFolder"></div>
</div>
<umb-file-dropzone
ng-if="acceptedMediatypes.length > 0 && !loading && !lockedFolder"
<umb-file-dropzone
ng-if="acceptedMediatypes.length > 0 && !loading && !lockedFolder"
accepted-mediatypes="acceptedMediatypes"
parent-id="{{currentFolder.id}}"
files-uploaded="onUploadComplete"
files-queued="onFilesQueue"
parent-id="{{currentFolder.id}}"
files-uploaded="onUploadComplete"
files-queued="onFilesQueue"
accept="{{acceptedFileTypes}}"
max-file-size="{{maxFileSize}}"
max-file-size="{{maxFileSize}}"
hide-dropzone="{{!activeDrag && images.length > 0 || searchOptions.filter }}"
compact="{{ images.length > 0 }}">
</umb-file-dropzone>
<umb-media-grid
ng-if="!loading"
items="images"
<umb-media-grid
ng-if="!loading"
items="images"
on-click="clickHandler"
on-click-name="clickItemName"
on-click-edit="editMediaItem(item)"
allow-on-click-edit="{{allowMediaEdit}}"
item-max-width="150"
item-max-height="150"
item-min-width="100"
item-min-height="100"
item-max-height="150"
item-min-width="100"
item-min-height="100"
only-images={{onlyImages}}
include-sub-folders={{showChilds}}
current-Folder-id="{{currentFolder.id}}">
</umb-media-grid>
<div class="flex justify-center">
<umb-pagination
ng-if="searchOptions.totalPages > 0 && !loading"
page-number="searchOptions.pageNumber"
<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 ng-if="mediaPickerDetailsOverlay.show" model="mediaPickerDetailsOverlay" position="right">
<div class="umb-control-group">
<div ng-if="target.url">
<umb-image-gravity
src="target.url"
<umb-image-gravity
src="target.url"
center="target.focalPoint">
</umb-image-gravity>
</div>
<div ng-if="cropSize">
<h5>
<localize key="general_preview">Preview</localize>
</h5>
<umb-image-thumbnail center="target.focalPoint" src="target.url" height="{{cropSize.height}}" width="{{cropSize.width}}"
max-size="400">
</umb-image-thumbnail>
</div>
</div>
<div class="umb-control-group">
<label>
<localize key="@general_url"></localize>
@@ -150,17 +150,17 @@
<input type="text" localize="placeholder" placeholder="@general_url" class="umb-property-editor umb-textstring" ng-model="target.url"
ng-disabled="target.id" />
</div>
<div class="umb-control-group">
<label>
<localize key="@content_altTextOptional"></localize>
</label>
<input type="text" class="umb-property-editor umb-textstring" ng-model="target.altText" />
</div>
</umb-overlay>
</form>
</umb-editor-container>
@@ -18,7 +18,7 @@
type="checkbox"
ng-model="variant.publish"
ng-change="vm.changeSelection(variant)"
ng-disabled="(vm.isNew && variant.language.isMandatory) || !variant.canSave"
ng-disabled="(vm.isNew && variant.language.isMandatory) || (variant.canSave === false)"
style="margin-right: 8px;"
val-server-field="{{variant.htmlId}}" />
<div>
@@ -60,8 +60,8 @@ angular.module("umbraco")
start: function (e, ui) {
// Fade out row when sorting
ui.item.context.style.display = "block";
ui.item.context.style.opacity = "0.5";
ui.item[0].style.display = "block";
ui.item[0].style.opacity = "0.5";
draggedRteSettings = {};
ui.item.find(".mceNoEditor").each(function () {
@@ -75,7 +75,7 @@ angular.module("umbraco")
stop: function (e, ui) {
// Fade in row when sorting stops
ui.item.context.style.opacity = "1";
ui.item[0].style.opacity = "1";
// reset all RTEs affected by the dragging
ui.item.parents(".umb-column").find(".mceNoEditor").each(function () {
@@ -185,12 +185,12 @@ angular.module("umbraco")
startingArea = area;
// fade out control when sorting
ui.item.context.style.display = "block";
ui.item.context.style.opacity = "0.5";
ui.item[0].style.display = "block";
ui.item[0].style.opacity = "0.5";
// reset dragged RTE settings in case a RTE isn't dragged
draggedRteSettings = undefined;
ui.item.context.style.display = "block";
ui.item[0].style.display = "block";
ui.item.find(".mceNoEditor").each(function () {
notIncludedRte = [];
var editors = _.findWhere(tinyMCE.editors, { id: $(this).attr("id") });
@@ -210,7 +210,7 @@ angular.module("umbraco")
stop: function (e, ui) {
// Fade in control when sorting stops
ui.item.context.style.opacity = "1";
ui.item[0].style.opacity = "1";
ui.item.offsetParent().find(".mceNoEditor").each(function () {
if ($.inArray($(this).attr("id"), notIncludedRte) < 0) {
@@ -400,7 +400,7 @@ angular.module("umbraco")
}
$scope.editGridItemSettings = function (gridItem, itemType) {
placeHolder = "{0}";
var styles, config;
@@ -658,7 +658,7 @@ angular.module("umbraco")
// *********************************************
$scope.initContent = function () {
var clear = true;
//settings indicator shortcut
if (($scope.model.config.items.config && $scope.model.config.items.config.length > 0) || ($scope.model.config.items.styles && $scope.model.config.items.styles.length > 0)) {
$scope.hasSettings = true;
@@ -755,7 +755,7 @@ angular.module("umbraco")
// Init layout / row
// *********************************************
$scope.initRow = function (row) {
//merge the layout data with the original config data
//if there are no config info on this, splice it out
var original = _.find($scope.model.config.items.layouts, function (o) { return o.name === row.name; });
@@ -909,9 +909,9 @@ angular.module("umbraco")
// needs to be merged in at runtime to ensure that the real config values are used
// if they are ever updated.
var unsubscribe = $scope.$on("formSubmitting", function () {
if ($scope.model.value && $scope.model.value.sections) {
var unsubscribe = $scope.$on("formSubmitting", function (e, args) {
if (args.action === "save" && $scope.model.value && $scope.model.value.sections) {
_.each($scope.model.value.sections, function(section) {
if (section.rows) {
_.each(section.rows, function (row) {
@@ -1,12 +1,9 @@
angular.module("umbraco")
.controller("Umbraco.PropertyEditors.TagsController",
function ($scope, angularHelper) {
function ($scope) {
$scope.valueChanged = function(value) {
$scope.model.value = value;
// the model value seems to be a reference to the same array, so we need
// to set the form as dirty explicitly when the content of the array changes
angularHelper.getCurrentForm($scope).$setDirty();
}
}
@@ -46,6 +46,17 @@
<li ng-repeat="device in devices" ng-class="{ current:previewDevice==device }">
<a href="" ng-click="updatePreviewDevice(device)"><i class="icon {{device.icon}}" title="{{device.title}}"></i><span></span></a>
</li>
@if (Model.Languages != null && Model.Languages.Count() > 1)
{
foreach (var previewLink in Model.Languages)
{
<li>
<a href="" ng-click="changeCulture('@previewLink.IsoCode')" title="Preview in @previewLink.CultureName"><i class="icon icon-globe-europe---africa"></i><span>@previewLink.CultureName</span></a>
</li>
}
}
<li>
<a href="" ng-click="exitPreview()" title="Exit Preview"><i class="icon icon-wrong"></i><span> </span></a>
</li>
+2 -1
View File
@@ -5,7 +5,8 @@
<!-- Used to toggle the loge levels for the main Umbraco log files -->
<!-- Found at /app_data/logs/ -->
<!-- NOTE: Changing this will also flow down into serilog.user.config -->
<add key="serilog:minimum-level" value="Info" />
<!-- VALID Values: Verbose, Debug, Information, Warning, Error, Fatal -->
<add key="serilog:minimum-level" value="Information" />
<!-- To write to new log locations (aka Sinks) such as your own .txt files, ELMAH.io, Elastic, SEQ -->
<!-- Please use the serilog.user.config file to configure your own logging needs -->
@@ -3,7 +3,8 @@
<appSettings>
<!-- Controls log levels for all user-defined child sub-logger sinks configured here (Set this higher than child sinks defined here) -->
<add key="serilog:minimum-level" value="Info" />
<!-- VALID Values: Verbose, Debug, Information, Warning, Error, Fatal -->
<add key="serilog:minimum-level" value="Information" />
<!-- For Different Namespaces - Set different logging levels -->
<!--
+8 -8
View File
@@ -30,14 +30,14 @@
<clientDependency configSource="config\ClientDependency.config" />
<appSettings>
<add key="umbracoConfigurationStatus" value="" />
<add key="umbracoReservedUrls" value="" />
<add key="umbracoReservedPaths" value="" />
<add key="umbracoPath" value="~/umbraco" />
<add key="umbracoHideTopLevelNodeFromPath" value="true" />
<add key="umbracoTimeOutInMinutes" value="20" />
<add key="umbracoDefaultUILanguage" value="en-US" />
<add key="umbracoUseHttps" value="false" />
<add key="Umbraco.Core.ConfigurationStatus" value="" />
<add key="Umbraco.Core.ReservedUrls" value="" />
<add key="Umbraco.Core.ReservedPaths" value="" />
<add key="Umbraco.Core.Path" value="~/umbraco" />
<add key="Umbraco.Core.HideTopLevelNodeFromPath" value="true" />
<add key="Umbraco.Core.TimeOutInMinutes" value="20" />
<add key="Umbraco.Core.DefaultUILanguage" value="en-US" />
<add key="Umbraco.Core.UseHttps" value="false" />
<add key="ValidationSettings:UnobtrusiveValidationMode" value="None" />
<add key="webpages:Enabled" value="false" />
@@ -1,15 +1,22 @@
using Umbraco.Core.Configuration;
using System.Collections.Generic;
using Umbraco.Core.Configuration;
using Umbraco.Core.Models;
using Umbraco.Web.Features;
namespace Umbraco.Web.Editors
{
public class BackOfficePreviewModel : BackOfficeModel
{
public BackOfficePreviewModel(UmbracoFeatures features, IGlobalSettings globalSettings) : base(features, globalSettings)
private readonly UmbracoFeatures _features;
public IEnumerable<ILanguage> Languages { get; }
public BackOfficePreviewModel(UmbracoFeatures features, IGlobalSettings globalSettings, IEnumerable<ILanguage> languages) : base(features, globalSettings)
{
_features = features;
Languages = languages;
}
public bool DisableDevicePreview => Features.Disabled.DisableDevicePreview;
public string PreviewExtendedHeaderView => Features.Enabled.PreviewExtendedView;
public bool DisableDevicePreview => _features.Disabled.DisableDevicePreview;
public string PreviewExtendedHeaderView => _features.Enabled.PreviewExtendedView;
}
}
@@ -259,7 +259,7 @@ namespace Umbraco.Web.Editors
},
{
"tagsDataBaseUrl", _urlHelper.GetUmbracoApiServiceBaseUrl<TagsDataController>(
controller => controller.GetTags("", ""))
controller => controller.GetTags("", "", null))
},
{
"examineMgmtBaseUrl", _urlHelper.GetUmbracoApiServiceBaseUrl<ExamineManagementController>(
+3 -1
View File
@@ -1838,8 +1838,10 @@ namespace Umbraco.Web.Editors
throw new HttpResponseException(HttpStatusCode.NotFound);
}
var contentTypeService = Services.ContentTypeBaseServices.For(parent);
var parentContentType = contentTypeService.Get(parent.ContentTypeId);
//check if the item is allowed under this one
if (parent.ContentType.AllowedContentTypes.Select(x => x.Id).ToArray()
if (parentContentType.AllowedContentTypes.Select(x => x.Id).ToArray()
.Any(x => x.Value == toMove.ContentType.Id) == false)
{
throw new HttpResponseException(
@@ -214,7 +214,7 @@ namespace Umbraco.Web.Editors
? Request.CreateResponse(HttpStatusCode.OK, result.Result) //return the id
: Request.CreateNotificationValidationErrorResponse(result.Exception.Message);
}
public CreatedContentTypeCollectionResult PostCreateCollection(int parentId, string collectionName, bool collectionCreateTemplate, string collectionItemName, bool collectionItemCreateTemplate, string collectionIcon, string collectionItemIcon)
{
// create item doctype
@@ -222,7 +222,7 @@ namespace Umbraco.Web.Editors
itemDocType.Name = collectionItemName;
itemDocType.Alias = collectionItemName.ToSafeAlias(true);
itemDocType.Icon = collectionItemIcon;
// create item doctype template
if (collectionItemCreateTemplate)
{
@@ -243,7 +243,7 @@ namespace Umbraco.Web.Editors
{
new ContentTypeSort(itemDocType.Id, 0)
};
// create collection doctype template
if (collectionCreateTemplate)
{
@@ -403,7 +403,9 @@ namespace Umbraco.Web.Editors
return Enumerable.Empty<ContentTypeBasic>();
}
var ids = contentItem.ContentType.AllowedContentTypes.Select(x => x.Id.Value).ToArray();
var contentTypeService = Services.ContentTypeBaseServices.For(contentItem);
var contentType = contentTypeService.Get(contentItem.ContentTypeId);
var ids = contentType.AllowedContentTypes.Select(x => x.Id.Value).ToArray();
if (ids.Any() == false) return Enumerable.Empty<ContentTypeBasic>();
@@ -497,7 +499,7 @@ namespace Umbraco.Web.Editors
{
return Request.CreateResponse(HttpStatusCode.NotFound);
}
var dataInstaller = new PackageDataInstallation(Logger, Services.FileService, Services.MacroService, Services.LocalizationService,
Services.DataTypeService, Services.EntityService, Services.ContentTypeService, Services.ContentService, _propertyEditors);
@@ -543,7 +545,7 @@ namespace Umbraco.Web.Editors
}
var model = new ContentTypeImportModel();
var file = result.FileData[0];
var fileName = file.Headers.ContentDisposition.FileName.Trim('\"');
var ext = fileName.Substring(fileName.LastIndexOf('.') + 1).ToLower();
@@ -577,6 +579,6 @@ namespace Umbraco.Web.Editors
}
}
}
+5 -10
View File
@@ -43,12 +43,16 @@ namespace Umbraco.Web.Editors
public class EntityController : UmbracoAuthorizedJsonController
{
private readonly ITreeService _treeService;
private readonly UmbracoTreeSearcher _treeSearcher;
private readonly SearchableTreeCollection _searchableTreeCollection;
public EntityController(IGlobalSettings globalSettings, UmbracoContext umbracoContext, ISqlContext sqlContext, ServiceContext services, AppCaches appCaches, IProfilingLogger logger, IRuntimeState runtimeState,
ITreeService treeService)
ITreeService treeService, SearchableTreeCollection searchableTreeCollection, UmbracoTreeSearcher treeSearcher)
: base(globalSettings, umbracoContext, sqlContext, services, appCaches, logger, runtimeState)
{
_treeService = treeService;
_searchableTreeCollection = searchableTreeCollection;
_treeSearcher = treeSearcher;
}
/// <summary>
@@ -69,15 +73,6 @@ namespace Umbraco.Web.Editors
}
}
private readonly UmbracoTreeSearcher _treeSearcher;
private readonly SearchableTreeCollection _searchableTreeCollection;
public EntityController(SearchableTreeCollection searchableTreeCollection, UmbracoTreeSearcher treeSearcher)
{
_searchableTreeCollection = searchableTreeCollection;
_treeSearcher = treeSearcher;
}
/// <summary>
/// Returns an Umbraco alias given a string
/// </summary>
+5 -3
View File
@@ -47,9 +47,10 @@ namespace Umbraco.Web.Editors
[MediaControllerControllerConfiguration]
public class MediaController : ContentControllerBase
{
public MediaController(PropertyEditorCollection propertyEditors)
public MediaController(PropertyEditorCollection propertyEditors, IContentTypeBaseServiceProvider contentTypeBaseServiceProvider)
{
_propertyEditors = propertyEditors ?? throw new ArgumentNullException(nameof(propertyEditors));
_contentTypeBaseServiceProvider = contentTypeBaseServiceProvider;
}
/// <summary>
@@ -233,6 +234,7 @@ namespace Umbraco.Web.Editors
private int[] _userStartNodes;
private readonly PropertyEditorCollection _propertyEditors;
private readonly IContentTypeBaseServiceProvider _contentTypeBaseServiceProvider;
protected int[] UserStartNodes
{
@@ -292,7 +294,7 @@ namespace Umbraco.Web.Editors
else
{
//better to not use this without paging where possible, currently only the sort dialog does
children = Services.MediaService.GetPagedChildren(id, 0, int.MaxValue, out var total).ToList();
children = Services.MediaService.GetPagedChildren(id,0, int.MaxValue, out var total).ToList();
totalChildren = children.Count;
}
@@ -724,7 +726,7 @@ namespace Umbraco.Web.Editors
if (fs == null) throw new InvalidOperationException("Could not acquire file stream");
using (fs)
{
f.SetValue(Constants.Conventions.Media.File, fileName, fs);
f.SetValue(_contentTypeBaseServiceProvider, Constants.Conventions.Media.File,fileName, fs);
}
var saveResult = mediaService.Save(f, Security.CurrentUser.Id);
@@ -592,11 +592,6 @@ namespace Umbraco.Web.Editors
if (builtInAliases.Contains(p.Alias) == false && valueMapped != null)
{
p.SetValue(valueMapped.GetValue());
// FIXME: /task - ok, I give up, at that point tags are dead here, until we figure it out
// p.TagChanges.Behavior = valueMapped.TagChanges.Behavior;
// p.TagChanges.Enable = valueMapped.TagChanges.Enable;
// p.TagChanges.Tags = valueMapped.TagChanges.Tags;
}
}
}
+13 -2
View File
@@ -1,9 +1,11 @@
using System;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using System.Web.UI;
using Umbraco.Core;
using Umbraco.Core.Configuration;
using Umbraco.Core.Services;
using Umbraco.Web.Composing;
using Umbraco.Web.Features;
using Umbraco.Web.JavaScript;
@@ -21,20 +23,29 @@ namespace Umbraco.Web.Editors
private readonly IGlobalSettings _globalSettings;
private readonly IPublishedSnapshotService _publishedSnapshotService;
private readonly UmbracoContext _umbracoContext;
private readonly ILocalizationService _localizationService;
public PreviewController(UmbracoFeatures features, IGlobalSettings globalSettings, IPublishedSnapshotService publishedSnapshotService, UmbracoContext umbracoContext)
public PreviewController(
UmbracoFeatures features,
IGlobalSettings globalSettings,
IPublishedSnapshotService publishedSnapshotService,
UmbracoContext umbracoContext,
ILocalizationService localizationService)
{
_features = features;
_globalSettings = globalSettings;
_publishedSnapshotService = publishedSnapshotService;
_umbracoContext = umbracoContext;
_localizationService = localizationService;
}
[UmbracoAuthorize(redirectToUmbracoLogin: true)]
[DisableBrowserCache]
public ActionResult Index()
{
var model = new BackOfficePreviewModel(_features, _globalSettings);
var availableLanguages = _localizationService.GetAllLanguages();
var model = new BackOfficePreviewModel(_features, _globalSettings, availableLanguages);
if (model.PreviewExtendedHeaderView.IsNullOrWhiteSpace() == false)
{
@@ -102,7 +102,7 @@ namespace Umbraco.Web.Macros
Elements.Add("path", path);
Elements.Add("splitpath", path.Split(','));
}
/// <summary>
/// Puts the properties of the node into the elements table
/// </summary>
@@ -202,7 +202,8 @@ namespace Umbraco.Web.Macros
CreatorName = _inner.GetCreatorProfile().Name;
WriterName = _inner.GetWriterProfile().Name;
ContentType = Current.PublishedContentTypeFactory.CreateContentType(_inner.ContentType);
var contentTypeService = Current.Services.ContentTypeBaseServices.For(_inner);
ContentType = Current.PublishedContentTypeFactory.CreateContentType(contentTypeService.Get(_inner.ContentTypeId));
_properties = ContentType.PropertyTypes
.Select(x =>
@@ -1,4 +1,5 @@
using System;
using System.Collections.Generic;
using System.Linq;
using AutoMapper;
using Umbraco.Core;
@@ -22,6 +23,7 @@ namespace Umbraco.Web.Models.Mapping
IUserService userService,
IContentService contentService,
IContentTypeService contentTypeService,
IContentTypeBaseServiceProvider contentTypeBaseServiceProvider,
ILocalizationService localizationService)
{
// create, capture, cache
@@ -29,7 +31,8 @@ namespace Umbraco.Web.Models.Mapping
var creatorResolver = new CreatorResolver(userService);
var actionButtonsResolver = new ActionButtonsResolver(userService, contentService);
var childOfListViewResolver = new ContentChildOfListViewResolver(contentService, contentTypeService);
var contentTypeBasicResolver = new ContentTypeBasicResolver<IContent, ContentItemDisplay>();
var contentTypeBasicResolver = new ContentTypeBasicResolver<IContent, ContentItemDisplay>(contentTypeBaseServiceProvider);
var allowedTemplatesResolver = new AllowedTemplatesResolver(contentTypeService);
var defaultTemplateResolver = new DefaultTemplateResolver();
var variantResolver = new ContentVariantResolver(localizationService);
var schedPublishReleaseDateResolver = new ScheduledPublishDateResolver(ContentScheduleAction.Release);
@@ -57,10 +60,7 @@ namespace Umbraco.Web.Models.Mapping
.ForMember(dest => dest.Notifications, opt => opt.Ignore())
.ForMember(dest => dest.Errors, opt => opt.Ignore())
.ForMember(dest => dest.DocumentType, opt => opt.ResolveUsing(contentTypeBasicResolver))
.ForMember(dest => dest.AllowedTemplates, opt =>
opt.MapFrom(content => content.ContentType.AllowedTemplates
.Where(t => t.Alias.IsNullOrWhiteSpace() == false && t.Name.IsNullOrWhiteSpace() == false)
.ToDictionary(t => t.Alias, t => t.Name)))
.ForMember(dest => dest.AllowedTemplates, opt => opt.ResolveUsing(allowedTemplatesResolver))
.ForMember(dest => dest.AllowedActions, opt => opt.ResolveUsing(src => actionButtonsResolver.Resolve(src)))
.ForMember(dest => dest.AdditionalData, opt => opt.Ignore());
@@ -141,5 +141,26 @@ namespace Umbraco.Web.Models.Mapping
return source.CultureInfos.TryGetValue(culture, out var name) && !name.Name.IsNullOrWhiteSpace() ? name.Name : $"(({source.Name}))";
}
}
private class AllowedTemplatesResolver : IValueResolver<IContent, ContentItemDisplay, IDictionary<string, string>>
{
private readonly IContentTypeService _contentTypeService;
public AllowedTemplatesResolver(IContentTypeService contentTypeService)
{
_contentTypeService = contentTypeService;
}
public IDictionary<string, string> Resolve(IContent source, ContentItemDisplay destination, IDictionary<string, string> destMember, ResolutionContext context)
{
var contentType = _contentTypeService.Get(source.ContentTypeId);
return contentType.AllowedTemplates
.Where(t => t.Alias.IsNullOrWhiteSpace() == false && t.Name.IsNullOrWhiteSpace() == false)
.ToDictionary(t => t.Alias, t => t.Name);
}
}
}
}
@@ -4,6 +4,7 @@ using System.Web;
using AutoMapper;
using Umbraco.Core;
using Umbraco.Core.Models;
using Umbraco.Core.Services;
using Umbraco.Web.Models.ContentEditing;
namespace Umbraco.Web.Models.Mapping
@@ -15,6 +16,13 @@ namespace Umbraco.Web.Models.Mapping
internal class ContentTypeBasicResolver<TSource, TDestination> : IValueResolver<TSource, TDestination, ContentTypeBasic>
where TSource : IContentBase
{
private readonly IContentTypeBaseServiceProvider _contentTypeBaseServiceProvider;
public ContentTypeBasicResolver(IContentTypeBaseServiceProvider contentTypeBaseServiceProvider)
{
_contentTypeBaseServiceProvider = contentTypeBaseServiceProvider;
}
public ContentTypeBasic Resolve(TSource source, TDestination destination, ContentTypeBasic destMember, ResolutionContext context)
{
// TODO: We can resolve the UmbracoContext from the IValueResolver options!
@@ -22,13 +30,9 @@ namespace Umbraco.Web.Models.Mapping
if (HttpContext.Current != null && UmbracoContext.Current != null && UmbracoContext.Current.Security.CurrentUser != null
&& UmbracoContext.Current.Security.CurrentUser.AllowedSections.Any(x => x.Equals(Constants.Applications.Settings)))
{
ContentTypeBasic contentTypeBasic;
if (source is IContent content)
contentTypeBasic = Mapper.Map<IContentType, ContentTypeBasic>(content.ContentType);
else if (source is IMedia media)
contentTypeBasic = Mapper.Map<IMediaType, ContentTypeBasic>(media.ContentType);
else
throw new NotSupportedException($"Expected TSource to be IContent or IMedia, got {typeof(TSource).Name}.");
var contentTypeService = _contentTypeBaseServiceProvider.For(source);
var contentType = contentTypeService.Get(source.ContentTypeId);
var contentTypeBasic = Mapper.Map<IContentTypeComposition, ContentTypeBasic>(contentType);
return contentTypeBasic;
}
@@ -134,6 +134,10 @@ namespace Umbraco.Web.Models.Mapping
});
CreateMap<IContentTypeComposition, ContentTypeBasic>()
.ForMember(dest => dest.Udi, opt => opt.MapFrom(source => Udi.Create(Constants.UdiEntityType.MemberType, source.Key)))
.ForMember(dest => dest.Blueprints, opt => opt.Ignore())
.ForMember(dest => dest.AdditionalData, opt => opt.Ignore());
CreateMap<IMemberType, ContentTypeBasic>()
.ForMember(dest => dest.Udi, opt => opt.MapFrom(source => Udi.Create(Constants.UdiEntityType.MemberType, source.Key)))
.ForMember(dest => dest.Blueprints, opt => opt.Ignore())

Some files were not shown because too many files have changed in this diff Show More