Compare commits
190 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 4775aff749 | |||
| 9d20ee293b | |||
| a9b820de31 | |||
| 3813653852 | |||
| a4720a2221 | |||
| 728b71c4bd | |||
| 9d7975d970 | |||
| 7505401511 | |||
| 7ee0a278f7 | |||
| 1adbe9ddcb | |||
| d6272b0cdb | |||
| ce7dd19a8f | |||
| 55022e2aaf | |||
| 4ffca2e4bf | |||
| 4a38b8acd1 | |||
| d93b8b869e | |||
| bec4e442fb | |||
| 72cc5ce88b | |||
| 63763d025e | |||
| f76fa6bde6 | |||
| c34a1060f7 | |||
| a231cedd8e | |||
| 20526b40bf | |||
| 5008a2be7f | |||
| 03a395d1f9 | |||
| 734df8685d | |||
| 92dad1af1c | |||
| d897e78b27 | |||
| d79115fcdf | |||
| 992073ab4e | |||
| 3c9b144927 | |||
| b7e4f58503 | |||
| c11dce7b6e | |||
| 004a3e2808 | |||
| d05bfc8983 | |||
| 5bb7223a79 | |||
| c9a816f25e | |||
| 13cfb42287 | |||
| 334fcf38ec | |||
| 8873d0f79d | |||
| b499b45a5c | |||
| d5a71ec1da | |||
| 1402494e47 | |||
| 7c491c1fc1 | |||
| 460dd69884 | |||
| beda99963e | |||
| b06f16f5f7 | |||
| f9d79871b4 | |||
| 777b02b84c | |||
| e322ab6f75 | |||
| d19bebc404 | |||
| 46dd86c745 | |||
| 62af834176 | |||
| 2dac1b3cf5 | |||
| 68fb951283 | |||
| 1ca825de62 | |||
| 54b57f7d51 | |||
| 2f6e161120 | |||
| 379bbe5bc4 | |||
| 5c558b0eeb | |||
| 298e56ad05 | |||
| d74d2cd945 | |||
| e2dc4f36ad | |||
| 9620c902cc | |||
| abda579da6 | |||
| 2e43e97ae2 | |||
| c7ac3e7691 | |||
| a209a2067c | |||
| b1c6276a67 | |||
| 3950b35539 | |||
| 2f63364925 | |||
| 376c78381d | |||
| 0a09810f0f | |||
| 43018e2793 | |||
| ba559f6836 | |||
| a320b63fd6 | |||
| 200497b865 | |||
| 8bd38b3cdd | |||
| f2c7c1e2c6 | |||
| 9f2c428a7c | |||
| a958f946ef | |||
| ac642619e7 | |||
| 688652fb91 | |||
| 4ef1eeb8bc | |||
| 0d7661a779 | |||
| 17f36c62cb | |||
| 5a98150f15 | |||
| d6bc0934ff | |||
| 29caacf3c3 | |||
| f091219f48 | |||
| 372a2f5df4 | |||
| 1397bc6dbf | |||
| 7c5a4d9d67 | |||
| 183103dc16 | |||
| 4b2a5f8768 | |||
| 2c3693ac68 | |||
| 7d90296e15 | |||
| d4c831864d | |||
| 1a56bb9948 | |||
| 4e84260619 | |||
| 62ddce60a5 | |||
| bc8829ce14 | |||
| d582d5c827 | |||
| 604bddabdf | |||
| e5af5bcc22 | |||
| 9f7f920229 | |||
| d1d98372cd | |||
| 9feee42430 | |||
| 876cb374ad | |||
| 16582c8207 | |||
| 2ee1df3dec | |||
| fc862f8434 | |||
| 8d7891d203 | |||
| 5af773d1b0 | |||
| 847ef34281 | |||
| a728f475aa | |||
| 60f91d95e9 | |||
| 821532cbd4 | |||
| e3a639b424 | |||
| 5c49aa9b43 | |||
| f040754547 | |||
| 0da8604639 | |||
| dd09ba3e12 | |||
| 896ea389a3 | |||
| 759c6dfef2 | |||
| 809a3f952e | |||
| dce9dea8f3 | |||
| b2a497ddba | |||
| ea030d990f | |||
| 31767a4152 | |||
| d79134c710 | |||
| 2ed4948619 | |||
| ce08749d85 | |||
| 0e67c787a8 | |||
| 1eea1f5f8f | |||
| ebfb2b536f | |||
| 81010444f3 | |||
| bbbc1949bc | |||
| 7b34e59222 | |||
| 3706405bff | |||
| 8a0efd7790 | |||
| bd2ac3d128 | |||
| c25b710b80 | |||
| 09e060ff92 | |||
| 2248a85876 | |||
| a3f4b2db5d | |||
| 5947f01590 | |||
| 75a006ca87 | |||
| cee5880501 | |||
| f65002ea16 | |||
| bd1bfa416c | |||
| 317f96a1bd | |||
| a42d6b954f | |||
| 71b8674664 | |||
| 9e3ca51286 | |||
| 0e6f2b542e | |||
| 218f523022 | |||
| 50c6fb036a | |||
| bc2115ff0a | |||
| 9eee5c2bc0 | |||
| 038163421b | |||
| 7ce58f6e5f | |||
| c6470decb2 | |||
| 8a28639331 | |||
| 65b2b7cb82 | |||
| 2daf71aee4 | |||
| 339edb2295 | |||
| e117b764fb | |||
| ed3096642d | |||
| 95508c4fb7 | |||
| 4677faff38 | |||
| 725b3c5eca | |||
| bf6d084f82 | |||
| 08ca75bb35 | |||
| d76a0271e9 | |||
| 5deb483b94 | |||
| a409b8b0f7 | |||
| 0512eaa7fd | |||
| e8df5f9eb4 | |||
| af1257d4ae | |||
| c46678c766 | |||
| 00a32c4479 | |||
| 5027757760 | |||
| d4d040d9ec | |||
| 4f1b76f5ff | |||
| 3b3eda5bfc | |||
| becc07c2bd | |||
| 5841377431 | |||
| 5d69ec2391 | |||
| 9f9b4d2e84 |
@@ -0,0 +1,10 @@
|
||||
root=true
|
||||
|
||||
[*]
|
||||
end_of_line = lf
|
||||
indent_style = space
|
||||
indent_size = 2
|
||||
trim_trailing_whitespace = true
|
||||
|
||||
[*.{cs,cshtml,csx,vb,vbx,vbhtml,fs,fsx,txt,ps1,sql}]
|
||||
indent_size = 4
|
||||
@@ -14,12 +14,13 @@
|
||||
<summary>Contains the core assemblies needed to run Umbraco Cms</summary>
|
||||
<language>en-US</language>
|
||||
<tags>umbraco</tags>
|
||||
<dependencies>
|
||||
<!--Must be this way because 2.0.5 is actually 1.2.15.0 and 2.0.6 is actually 2.0.6 !-->
|
||||
<dependency id="log4net" version="[2.0.5,2.0.6)" />
|
||||
<dependencies>
|
||||
<dependency id="log4net" version="[2.0.8,3.0.0)" />
|
||||
<dependency id="Log4Net.Async" version="[2.0.4,3.0.0)" />
|
||||
<dependency id="Microsoft.AspNet.Mvc" version="[5.2.3,6.0.0)" />
|
||||
<dependency id="Microsoft.AspNet.WebApi" version="[5.2.3,6.0.0)" />
|
||||
<dependency id="Microsoft.AspNet.Identity.Owin" version="[2.2.1, 3.0.0)" />
|
||||
<dependency id="Microsoft.AspNet.SignalR.Core" version="[2.2.1, 3.0.0)" />
|
||||
<dependency id="Microsoft.Owin.Security.Cookies" version="[3.0.1, 4.0.0)" />
|
||||
<dependency id="Microsoft.Owin.Security.OAuth" version="[3.0.1, 4.0.0)" />
|
||||
<dependency id="Microsoft.Owin.Host.SystemWeb" version="[3.0.1, 4.0.0)" />
|
||||
@@ -27,19 +28,19 @@
|
||||
<dependency id="HtmlAgilityPack" version="[1.4.9.5, 2.0.0)" />
|
||||
<dependency id="Lucene.Net" version="[2.9.4.1, 3.0.0.0)" />
|
||||
<dependency id="SharpZipLib" version="[0.86.0, 1.0.0)" />
|
||||
<dependency id="MySql.Data" version="[6.9.8, 7.0.0)" />
|
||||
<dependency id="MySql.Data" version="[6.9.9, 7.0.0)" />
|
||||
<dependency id="xmlrpcnet" version="[2.5.0, 3.0.0)" />
|
||||
<dependency id="ClientDependency" version="[1.9.2, 2.0.0)" />
|
||||
<dependency id="ClientDependency-Mvc5" version="[1.8.0.0, 2.0.0)" />
|
||||
<dependency id="AutoMapper" version="[3.3.1, 4.0.0)" />
|
||||
<dependency id="Newtonsoft.Json" version="[9.0.1, 10.0.0)" />
|
||||
<dependency id="Newtonsoft.Json" version="[10.0.2, 11.0.0)" />
|
||||
<dependency id="Examine" version="[0.1.82, 1.0.0)" />
|
||||
<dependency id="ImageProcessor" version="[2.5.2, 3.0.0)" />
|
||||
<dependency id="ImageProcessor.Web" version="[4.8.2, 5.0.0)" />
|
||||
<dependency id="ImageProcessor" version="[2.5.3, 3.0.0)" />
|
||||
<dependency id="ImageProcessor.Web" version="[4.8.3, 5.0.0)" />
|
||||
<dependency id="semver" version="[2.0.4, 3.0.0)" />
|
||||
<!-- Markdown can not be updated due to: https://github.com/hey-red/markdownsharp/issues/71#issuecomment-233585487 -->
|
||||
<dependency id="Markdown" version="[1.14.7, 2.0.0)" />
|
||||
<dependency id="System.Threading.Tasks.Dataflow" version="[4.6.0, 5.0.0)" />
|
||||
<dependency id="System.Threading.Tasks.Dataflow" version="[4.7.0, 5.0.0)" />
|
||||
</dependencies>
|
||||
</metadata>
|
||||
<files>
|
||||
|
||||
@@ -16,8 +16,8 @@
|
||||
<tags>umbraco</tags>
|
||||
<dependencies>
|
||||
<dependency id="UmbracoCms.Core" version="[$version$]" />
|
||||
<dependency id="Newtonsoft.Json" version="[9.0.1, 10.0.0)" />
|
||||
<dependency id="Umbraco.ModelsBuilder" version="[3.0.5, 4.0.0)" />
|
||||
<dependency id="Newtonsoft.Json" version="[10.0.2, 11.0.0)" />
|
||||
<dependency id="Umbraco.ModelsBuilder" version="[3.0.7, 4.0.0)" />
|
||||
<dependency id="Microsoft.AspNet.SignalR.Core" version="[2.2.1, 3.0.0)" />
|
||||
<dependency id="ImageProcessor.Web.Config" version="[2.3.0, 3.0.0)" />
|
||||
</dependencies>
|
||||
|
||||
@@ -8,8 +8,16 @@
|
||||
|
||||
----------------------------------------------------
|
||||
|
||||
Don't forget to build!
|
||||
*** IMPORTANT NOTICE FOR 7.6 UPGRADES ***
|
||||
|
||||
Be sure to read the version specific upgrade information before proceeding:
|
||||
https://our.umbraco.org/documentation/Getting-Started/Setup/Upgrading/version-specific#version-7-6-0
|
||||
|
||||
You will most likely need to make some changes to your web.config and you will need to be
|
||||
aware of the breaking changes listed there to see if these affect your installation.
|
||||
|
||||
|
||||
Don't forget to build!
|
||||
|
||||
We've done our best to transform your configuration files but in case something is not quite right: remember we
|
||||
backed up your files in App_Data\NuGetBackup so you can find the original files before they were transformed.
|
||||
|
||||
@@ -330,6 +330,8 @@
|
||||
<dependentAssembly xdt:Locator="Condition(./_defaultNamespace:assemblyIdentity/@name='Microsoft.Owin.Security')" xdt:Transform="Remove" />
|
||||
<dependentAssembly xdt:Locator="Condition(./_defaultNamespace:assemblyIdentity/@name='Microsoft.Owin.Security.Cookies')" xdt:Transform="Remove" />
|
||||
<dependentAssembly xdt:Locator="Condition(./_defaultNamespace:assemblyIdentity/@name='System.Net.Http.Formatting')" xdt:Transform="Remove" />
|
||||
<dependentAssembly xdt:Locator="Condition(./_defaultNamespace:assemblyIdentity/@name='Microsoft.CodeAnalysis.CSharp')" xdt:Transform="Remove" />
|
||||
<dependentAssembly xdt:Locator="Condition(./_defaultNamespace:assemblyIdentity/@name='log4net')" xdt:Transform="Remove" />
|
||||
</assemblyBinding>
|
||||
</runtime>
|
||||
|
||||
@@ -349,7 +351,7 @@
|
||||
</dependentAssembly>
|
||||
<dependentAssembly xdt:Transform="Insert">
|
||||
<assemblyIdentity name="Newtonsoft.Json" publicKeyToken="30ad4fe6b2a6aeed" culture="neutral" />
|
||||
<bindingRedirect oldVersion="0.0.0.0-6.0.0.0" newVersion="6.0.0.0" />
|
||||
<bindingRedirect oldVersion="0.0.0.0-10.0.0.0" newVersion="10.0.0.0" />
|
||||
</dependentAssembly>
|
||||
<dependentAssembly xdt:Transform="Insert">
|
||||
<assemblyIdentity name="System.Web.Mvc" publicKeyToken="31bf3856ad364e35" culture="neutral" />
|
||||
@@ -383,6 +385,10 @@
|
||||
<assemblyIdentity name="System.Net.Http.Formatting" publicKeyToken="31bf3856ad364e35" culture="neutral" />
|
||||
<bindingRedirect oldVersion="0.0.0.0-5.2.3.0" newVersion="5.2.3.0" />
|
||||
</dependentAssembly>
|
||||
<dependentAssembly xdt:Transform="Insert">
|
||||
<assemblyIdentity name="log4net" publicKeyToken="669e0ddf0bb1aa2a" culture="neutral"/>
|
||||
<bindingRedirect oldVersion="0.0.0.0-2.0.8.0" newVersion="2.0.8.0"/>
|
||||
</dependentAssembly>
|
||||
</assemblyBinding>
|
||||
</runtime>
|
||||
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
# Usage: on line 2 put the release version, on line 3 put the version comment (example: beta)
|
||||
7.6.0
|
||||
beta06
|
||||
RC2
|
||||
@@ -4,7 +4,7 @@
|
||||
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
|
||||
<dependentAssembly>
|
||||
<assemblyIdentity name="Newtonsoft.Json" publicKeyToken="30ad4fe6b2a6aeed" culture="neutral" />
|
||||
<bindingRedirect oldVersion="0.0.0.0-9.0.0.0" newVersion="9.0.0.0" />
|
||||
<bindingRedirect oldVersion="0.0.0.0-10.0.0.0" newVersion="10.0.0.0" />
|
||||
</dependentAssembly>
|
||||
<dependentAssembly>
|
||||
<assemblyIdentity name="System.Web.Mvc" publicKeyToken="31bf3856ad364e35" culture="neutral" />
|
||||
@@ -30,6 +30,10 @@
|
||||
<assemblyIdentity name="Microsoft.Owin.Security.Cookies" publicKeyToken="31bf3856ad364e35" culture="neutral" />
|
||||
<bindingRedirect oldVersion="0.0.0.0-3.0.1.0" newVersion="3.0.1.0" />
|
||||
</dependentAssembly>
|
||||
<dependentAssembly>
|
||||
<assemblyIdentity name="log4net" publicKeyToken="669e0ddf0bb1aa2a" culture="neutral" />
|
||||
<bindingRedirect oldVersion="0.0.0.0-2.0.8.0" newVersion="2.0.8.0" />
|
||||
</dependentAssembly>
|
||||
</assemblyBinding>
|
||||
</runtime>
|
||||
<startup><supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5" /></startup></configuration>
|
||||
|
||||
+1
-1
@@ -12,4 +12,4 @@ using System.Resources;
|
||||
[assembly: AssemblyVersion("1.0.*")]
|
||||
|
||||
[assembly: AssemblyFileVersion("7.6.0")]
|
||||
[assembly: AssemblyInformationalVersion("7.6.0-beta06")]
|
||||
[assembly: AssemblyInformationalVersion("7.6.0-RC2")]
|
||||
@@ -4,12 +4,14 @@ using System.Text.RegularExpressions;
|
||||
using System.Web;
|
||||
using Umbraco.Core;
|
||||
|
||||
[assembly: PreApplicationStartMethod(typeof(BindingRedirects), "Initialize")]
|
||||
|
||||
namespace Umbraco.Core
|
||||
{
|
||||
/// <summary>
|
||||
/// Manages any assembly binding redirects that cannot be done via config
|
||||
/// Manages any assembly binding redirects that cannot be done via config (i.e. unsigned --> signed assemblies)
|
||||
/// </summary>
|
||||
internal class BindingRedirects
|
||||
public sealed class BindingRedirects
|
||||
{
|
||||
public static void Initialize()
|
||||
{
|
||||
@@ -17,12 +19,9 @@ namespace Umbraco.Core
|
||||
AppDomain.CurrentDomain.AssemblyResolve += CurrentDomain_AssemblyResolve;
|
||||
}
|
||||
|
||||
private static readonly Regex Log4NetAssemblyPattern = new Regex("log4net, Version=([\\d\\.]+?), Culture=neutral, PublicKeyToken=null");
|
||||
private const string Log4NetReplacement = "log4net, Version=1.2.15.0, Culture=neutral, PublicKeyToken=669e0ddf0bb1aa2a";
|
||||
|
||||
private static readonly Regex HtmlAgilityAssemblyPattern = new Regex("HtmlAgilityPack, Version=([\\d\\.]+?), Culture=neutral, PublicKeyToken=bd319b19eaf3b43a");
|
||||
private const string HtmlAgilityReplacement = "HtmlAgilityPack, Version=1.4.9.5, Culture=neutral, PublicKeyToken=bd319b19eaf3b43a";
|
||||
|
||||
private static readonly Regex Log4NetAssemblyPattern = new Regex("log4net, Version=([\\d\\.]+?), Culture=neutral, PublicKeyToken=\\w+$", RegexOptions.Compiled);
|
||||
private const string Log4NetReplacement = "log4net, Version=2.0.8.0, Culture=neutral, PublicKeyToken=669e0ddf0bb1aa2a";
|
||||
|
||||
/// <summary>
|
||||
/// This is used to do an assembly binding redirect via code - normally required due to signature changes in assemblies
|
||||
/// </summary>
|
||||
@@ -36,13 +35,7 @@ namespace Umbraco.Core
|
||||
{
|
||||
return Assembly.Load(Log4NetAssemblyPattern.Replace(args.Name, Log4NetReplacement));
|
||||
}
|
||||
|
||||
//HtmlAgility:
|
||||
if (HtmlAgilityAssemblyPattern.IsMatch(args.Name) && args.Name != HtmlAgilityReplacement)
|
||||
{
|
||||
return Assembly.Load(HtmlAgilityAssemblyPattern.Replace(args.Name, HtmlAgilityReplacement));
|
||||
}
|
||||
|
||||
|
||||
//AutoMapper:
|
||||
// ensure the assembly is indeed AutoMapper and that the PublicKeyToken is null before trying to Load again
|
||||
// do NOT just replace this with 'return Assembly', as it will cause an infinite loop -> stackoverflow
|
||||
|
||||
@@ -183,6 +183,12 @@ namespace Umbraco.Core.Configuration.UmbracoSettings
|
||||
get { return GetOptionalTextElement("EnablePropertyValueConverters", false); }
|
||||
}
|
||||
|
||||
[ConfigurationProperty("loginBackgroundImage")]
|
||||
internal InnerTextConfigurationElement<string> LoginBackgroundImage
|
||||
{
|
||||
get { return GetOptionalTextElement("loginBackgroundImage", string.Empty); }
|
||||
}
|
||||
|
||||
string IContentSection.NotificationEmailAddress
|
||||
{
|
||||
get { return Notifications.NotificationEmailAddress; }
|
||||
@@ -336,5 +342,10 @@ namespace Umbraco.Core.Configuration.UmbracoSettings
|
||||
{
|
||||
get { return EnablePropertyValueConverters; }
|
||||
}
|
||||
|
||||
string IContentSection.LoginBackgroundImage
|
||||
{
|
||||
get { return LoginBackgroundImage; }
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -72,5 +72,6 @@ namespace Umbraco.Core.Configuration.UmbracoSettings
|
||||
|
||||
bool EnablePropertyValueConverters { get; }
|
||||
|
||||
string LoginBackgroundImage { get; }
|
||||
}
|
||||
}
|
||||
@@ -24,7 +24,7 @@ namespace Umbraco.Core.Configuration
|
||||
/// Gets the version comment (like beta or RC).
|
||||
/// </summary>
|
||||
/// <value>The version comment.</value>
|
||||
public static string CurrentComment { get { return "beta06"; } }
|
||||
public static string CurrentComment { get { return "RC2"; } }
|
||||
|
||||
// Get the version of the umbraco.dll by looking at a class in that dll
|
||||
// Had to do it like this due to medium trust issues, see: http://haacked.com/archive/2010/11/04/assembly-location-and-medium-trust.aspx
|
||||
|
||||
@@ -124,6 +124,11 @@ namespace Umbraco.Core
|
||||
/// </summary>
|
||||
public const string MemberGroup = "366E63B9-880F-4E13-A61C-98069B029728";
|
||||
|
||||
/// <summary>
|
||||
/// Guid for a Member Group object.
|
||||
/// </summary>
|
||||
public static readonly Guid MemberGroupGuid = new Guid(MemberGroup);
|
||||
|
||||
/// <summary>
|
||||
/// Guid for a Member Type object.
|
||||
/// </summary>
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using umbraco.interfaces;
|
||||
using Umbraco.Core;
|
||||
|
||||
namespace Umbraco.Core.Deploy
|
||||
@@ -8,7 +9,7 @@ namespace Umbraco.Core.Deploy
|
||||
/// <summary>
|
||||
/// Connects to an Umbraco service.
|
||||
/// </summary>
|
||||
public interface IServiceConnector
|
||||
public interface IServiceConnector : IDiscoverable
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets an artifact.
|
||||
|
||||
@@ -4,38 +4,144 @@ using System.IO;
|
||||
|
||||
namespace Umbraco.Core.IO
|
||||
{
|
||||
public interface IFileSystem
|
||||
/// <summary>
|
||||
/// Provides methods allowing the manipulation of files within an Umbraco application.
|
||||
/// </summary>
|
||||
public interface IFileSystem
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets all directories matching the given path.
|
||||
/// </summary>
|
||||
/// <param name="path">The path to the directories.</param>
|
||||
/// <returns>
|
||||
/// The <see cref="IEnumerable{String}"/> representing the matched directories.
|
||||
/// </returns>
|
||||
IEnumerable<string> GetDirectories(string path);
|
||||
|
||||
/// <summary>
|
||||
/// Deletes the specified directory.
|
||||
/// </summary>
|
||||
/// <param name="path">The name of the directory to remove.</param>
|
||||
void DeleteDirectory(string path);
|
||||
|
||||
/// <summary>
|
||||
/// Deletes the specified directory and, if indicated, any subdirectories and files in the directory.
|
||||
/// </summary>
|
||||
/// <remarks>Azure blob storage has no real concept of directories so deletion is always recursive.</remarks>
|
||||
/// <param name="path">The name of the directory to remove.</param>
|
||||
/// <param name="recursive">Whether to remove directories, subdirectories, and files in path.</param>
|
||||
void DeleteDirectory(string path, bool recursive);
|
||||
|
||||
/// <summary>
|
||||
/// Determines whether the specified directory exists.
|
||||
/// </summary>
|
||||
/// <param name="path">The directory to check.</param>
|
||||
/// <returns>
|
||||
/// <c>True</c> if the directory exists and the user has permission to view it; otherwise <c>false</c>.
|
||||
/// </returns>
|
||||
bool DirectoryExists(string path);
|
||||
|
||||
/// <summary>
|
||||
/// Adds a file to the file system.
|
||||
/// </summary>
|
||||
/// <param name="path">The path to the given file.</param>
|
||||
/// <param name="stream">The <see cref="Stream"/> containing the file contents.</param>
|
||||
void AddFile(string path, Stream stream);
|
||||
|
||||
/// <summary>
|
||||
/// Adds a file to the file system.
|
||||
/// </summary>
|
||||
/// <param name="path">The path to the given file.</param>
|
||||
/// <param name="stream">The <see cref="Stream"/> containing the file contents.</param>
|
||||
/// <param name="overrideIfExists">Whether to override the file if it already exists.</param>
|
||||
void AddFile(string path, Stream stream, bool overrideIfExists);
|
||||
|
||||
/// <summary>
|
||||
/// Gets all files matching the given path.
|
||||
/// </summary>
|
||||
/// <param name="path">The path to the files.</param>
|
||||
/// <returns>
|
||||
/// The <see cref="IEnumerable{String}"/> representing the matched files.
|
||||
/// </returns>
|
||||
IEnumerable<string> GetFiles(string path);
|
||||
|
||||
/// <summary>
|
||||
/// Gets all files matching the given path and filter.
|
||||
/// </summary>
|
||||
/// <param name="path">The path to the files.</param>
|
||||
/// <param name="filter">A filter that allows the querying of file extension. <example>*.jpg</example></param>
|
||||
/// <returns>
|
||||
/// The <see cref="IEnumerable{String}"/> representing the matched files.
|
||||
/// </returns>
|
||||
IEnumerable<string> GetFiles(string path, string filter);
|
||||
|
||||
/// <summary>
|
||||
/// Gets a <see cref="Stream"/> representing the file at the gieven path.
|
||||
/// </summary>
|
||||
/// <param name="path">The path to the file.</param>
|
||||
/// <returns>
|
||||
/// <see cref="Stream"/>.
|
||||
/// </returns>
|
||||
Stream OpenFile(string path);
|
||||
|
||||
/// <summary>
|
||||
/// Deletes the specified file.
|
||||
/// </summary>
|
||||
/// <param name="path">The name of the file to remove.</param>
|
||||
void DeleteFile(string path);
|
||||
|
||||
/// <summary>
|
||||
/// Determines whether the specified file exists.
|
||||
/// </summary>
|
||||
/// <param name="path">The file to check.</param>
|
||||
/// <returns>
|
||||
/// <c>True</c> if the file exists and the user has permission to view it; otherwise <c>false</c>.
|
||||
/// </returns>
|
||||
bool FileExists(string path);
|
||||
|
||||
/// <summary>
|
||||
/// Returns the application relative path to the file.
|
||||
/// </summary>
|
||||
/// <param name="fullPathOrUrl">The full path or url.</param>
|
||||
/// <returns>
|
||||
/// The <see cref="string"/> representing the relative path.
|
||||
/// </returns>
|
||||
string GetRelativePath(string fullPathOrUrl);
|
||||
|
||||
/// <summary>
|
||||
/// Gets the full qualified path to the file.
|
||||
/// </summary>
|
||||
/// <param name="path">The file to return the full path for.</param>
|
||||
/// <returns>
|
||||
/// The <see cref="string"/> representing the full path.
|
||||
/// </returns>
|
||||
string GetFullPath(string path);
|
||||
|
||||
/// <summary>
|
||||
/// Returns the application relative url to the file.
|
||||
/// </summary>
|
||||
/// <param name="path">The path to return the url for.</param>
|
||||
/// <returns>
|
||||
/// <see cref="string"/> representing the relative url.
|
||||
/// </returns>
|
||||
string GetUrl(string path);
|
||||
|
||||
/// <summary>
|
||||
/// Gets the last modified date/time of the file, expressed as a UTC value.
|
||||
/// </summary>
|
||||
/// <param name="path">The path to the file.</param>
|
||||
/// <returns>
|
||||
/// <see cref="DateTimeOffset"/>.
|
||||
/// </returns>
|
||||
DateTimeOffset GetLastModified(string path);
|
||||
|
||||
/// <summary>
|
||||
/// Gets the created date/time of the file, expressed as a UTC value.
|
||||
/// </summary>
|
||||
/// <param name="path">The path to the file.</param>
|
||||
/// <returns>
|
||||
/// <see cref="DateTimeOffset"/>.
|
||||
/// </returns>
|
||||
DateTimeOffset GetCreated(string path);
|
||||
}
|
||||
|
||||
|
||||
@@ -31,6 +31,7 @@ namespace Umbraco.Core.IO
|
||||
private long _folderCounter;
|
||||
private bool _folderCounterInitialized;
|
||||
|
||||
[Obsolete("This should no longer be used, image manipulation should be done via ImageProcessor, Umbraco no longer generates '_thumb' files for media")]
|
||||
private static readonly Dictionary<int, string> DefaultSizes = new Dictionary<int, string>
|
||||
{
|
||||
{ 100, "thumb" },
|
||||
@@ -263,7 +264,7 @@ namespace Umbraco.Core.IO
|
||||
var filename = Path.GetFileName(sourcepath);
|
||||
var filepath = GetMediaPath(filename, content.Key, propertyType.Key);
|
||||
this.CopyFile(sourcepath, filepath);
|
||||
CopyThumbnails(sourcepath, filepath);
|
||||
|
||||
return filepath;
|
||||
}
|
||||
|
||||
@@ -312,29 +313,17 @@ namespace Umbraco.Core.IO
|
||||
}
|
||||
}
|
||||
|
||||
// sets a file for the FileUpload property editor
|
||||
// ie generates thumbnails and populates autofill properties
|
||||
/// <summary>
|
||||
/// Sets a file for the FileUpload property editor and populates autofill properties
|
||||
/// </summary>
|
||||
/// <param name="content"></param>
|
||||
/// <param name="property"></param>
|
||||
/// <param name="filepath"></param>
|
||||
/// <param name="filestream"></param>
|
||||
private void SetUploadFile(IContentBase content, Property property, string filepath, Stream filestream)
|
||||
{
|
||||
// check if file is an image (and supports resizing and thumbnails etc)
|
||||
var extension = Path.GetExtension(filepath);
|
||||
var isImage = IsImageFile(extension);
|
||||
|
||||
// specific stuff for images (thumbnails etc)
|
||||
if (isImage)
|
||||
{
|
||||
using (var image = Image.FromStream(filestream))
|
||||
{
|
||||
// use one image for all
|
||||
GenerateThumbnails(image, filepath, property.PropertyType);
|
||||
_uploadAutoFillProperties.Populate(content, property.Alias, filepath, filestream, image);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// will use filepath for extension, and filestream for length
|
||||
_uploadAutoFillProperties.Populate(content, property.Alias, filepath, filestream);
|
||||
}
|
||||
{
|
||||
// will use filepath for extension, and filestream for length
|
||||
_uploadAutoFillProperties.Populate(content, property.Alias, filepath, filestream);
|
||||
}
|
||||
|
||||
#endregion
|
||||
@@ -401,6 +390,7 @@ namespace Umbraco.Core.IO
|
||||
|
||||
// note: this does not find 'custom' thumbnails?
|
||||
// will find _thumb and _big-thumb but NOT _custom?
|
||||
[Obsolete("This should no longer be used, image manipulation should be done via ImageProcessor, Umbraco no longer generates '_thumb' files for media")]
|
||||
public IEnumerable<string> GetThumbnails(string path)
|
||||
{
|
||||
var parentDirectory = Path.GetDirectoryName(path);
|
||||
@@ -421,12 +411,14 @@ namespace Umbraco.Core.IO
|
||||
DeleteThumbnails(path);
|
||||
}
|
||||
|
||||
[Obsolete("This should no longer be used, image manipulation should be done via ImageProcessor, Umbraco no longer generates '_thumb' files for media")]
|
||||
public void DeleteThumbnails(string path)
|
||||
{
|
||||
GetThumbnails(path)
|
||||
.ForEach(x => base.DeleteFile(x));
|
||||
}
|
||||
|
||||
[Obsolete("This should no longer be used, image manipulation should be done via ImageProcessor, Umbraco no longer generates '_thumb' files for media")]
|
||||
public void CopyThumbnails(string sourcePath, string targetPath)
|
||||
{
|
||||
var targetPathBase = Path.GetDirectoryName(targetPath) ?? "";
|
||||
@@ -479,6 +471,7 @@ namespace Umbraco.Core.IO
|
||||
|
||||
#region GenerateThumbnails
|
||||
|
||||
[Obsolete("This should no longer be used, image manipulation should be done via ImageProcessor, Umbraco no longer generates '_thumb' files for media")]
|
||||
public IEnumerable<ResizedImage> GenerateThumbnails(
|
||||
Image image,
|
||||
string filepath,
|
||||
@@ -500,6 +493,7 @@ namespace Umbraco.Core.IO
|
||||
return GenerateThumbnails(image, filepath, additionalSizes);
|
||||
}
|
||||
|
||||
[Obsolete("This should no longer be used, image manipulation should be done via ImageProcessor, Umbraco no longer generates '_thumb' files for media")]
|
||||
public IEnumerable<ResizedImage> GenerateThumbnails(
|
||||
Image image,
|
||||
string filepath,
|
||||
@@ -522,6 +516,7 @@ namespace Umbraco.Core.IO
|
||||
.ToList(); // now
|
||||
}
|
||||
|
||||
[Obsolete("This should no longer be used, image manipulation should be done via ImageProcessor, Umbraco no longer generates '_thumb' files for media")]
|
||||
public IEnumerable<ResizedImage> GenerateThumbnails(
|
||||
Stream filestream,
|
||||
string filepath,
|
||||
@@ -535,6 +530,7 @@ namespace Umbraco.Core.IO
|
||||
}
|
||||
}
|
||||
|
||||
[Obsolete("This should no longer be used, image manipulation should be done via ImageProcessor, Umbraco no longer generates '_thumb' files for media")]
|
||||
public IEnumerable<ResizedImage> GenerateThumbnails(
|
||||
Image image,
|
||||
string filepath,
|
||||
@@ -556,16 +552,19 @@ namespace Umbraco.Core.IO
|
||||
|
||||
#region GenerateResized - Generate at resized filepath derived from origin filepath
|
||||
|
||||
[Obsolete("This should no longer be used, image manipulation should be done via ImageProcessor, Umbraco no longer generates '_thumb' files for media")]
|
||||
public ResizedImage GenerateResized(Image originImage, string originFilepath, string sizeName, int maxWidthHeight)
|
||||
{
|
||||
return GenerateResized(originImage, originFilepath, sizeName, maxWidthHeight, -1, -1);
|
||||
}
|
||||
|
||||
[Obsolete("This should no longer be used, image manipulation should be done via ImageProcessor, Umbraco no longer generates '_thumb' files for media")]
|
||||
public ResizedImage GenerateResized(Image originImage, string originFilepath, string sizeName, int fixedWidth, int fixedHeight)
|
||||
{
|
||||
return GenerateResized(originImage, originFilepath, sizeName, -1, fixedWidth, fixedHeight);
|
||||
}
|
||||
|
||||
[Obsolete("This should no longer be used, image manipulation should be done via ImageProcessor, Umbraco no longer generates '_thumb' files for media")]
|
||||
public ResizedImage GenerateResized(Image originImage, string originFilepath, string sizeName, int maxWidthHeight, int fixedWidth, int fixedHeight)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(sizeName))
|
||||
@@ -581,16 +580,19 @@ namespace Umbraco.Core.IO
|
||||
|
||||
#region GenerateResizedAt - Generate at specified resized filepath
|
||||
|
||||
[Obsolete("This should no longer be used, image manipulation should be done via ImageProcessor, Umbraco no longer generates '_thumb' files for media")]
|
||||
public ResizedImage GenerateResizedAt(Image originImage, string resizedFilepath, int maxWidthHeight)
|
||||
{
|
||||
return GenerateResizedAt(originImage, resizedFilepath, maxWidthHeight, -1, -1);
|
||||
}
|
||||
|
||||
[Obsolete("This should no longer be used, image manipulation should be done via ImageProcessor, Umbraco no longer generates '_thumb' files for media")]
|
||||
public ResizedImage GenerateResizedAt(Image originImage, int fixedWidth, int fixedHeight, string resizedFilepath)
|
||||
{
|
||||
return GenerateResizedAt(originImage, resizedFilepath, -1, fixedWidth, fixedHeight);
|
||||
}
|
||||
|
||||
[Obsolete("This should no longer be used, image manipulation should be done via ImageProcessor, Umbraco no longer generates '_thumb' files for media")]
|
||||
public ResizedImage GenerateResizedAt(Image originImage, string resizedFilepath, int maxWidthHeight, int fixedWidth, int fixedHeight)
|
||||
{
|
||||
// target dimensions
|
||||
@@ -699,6 +701,7 @@ namespace Umbraco.Core.IO
|
||||
|
||||
#region Inner classes
|
||||
|
||||
[Obsolete("This should no longer be used, image manipulation should be done via ImageProcessor, Umbraco no longer generates '_thumb' files for media")]
|
||||
public class ResizedImage
|
||||
{
|
||||
public ResizedImage()
|
||||
|
||||
@@ -158,7 +158,7 @@ namespace Umbraco.Core.IO
|
||||
// if can seek, be safe and go back to start, else...
|
||||
// hope that the stream hasn't been read already
|
||||
if (stream.CanSeek)
|
||||
stream.Seek(0, 0);
|
||||
stream.Seek(0, SeekOrigin.Begin);
|
||||
|
||||
using (var destination = (Stream) File.Create(fullPath))
|
||||
stream.CopyTo(destination);
|
||||
|
||||
@@ -16,7 +16,7 @@ namespace Umbraco.Core.Logging
|
||||
/// This is an old/deprecated logger and has been superceded by ParallelForwardingAppender which is included in Umbraco and
|
||||
/// also by AsyncForwardingAppender in the Log4Net.Async library.
|
||||
/// </summary>
|
||||
[Obsolete("This is superceded by the ParallelForwardingAppender, this will be removed in v8")]
|
||||
[Obsolete("This is superceded by the ParallelForwardingAppender, this will be removed in v8, do not use this")]
|
||||
[EditorBrowsable(EditorBrowsableState.Never)]
|
||||
public class AsynchronousRollingFileAppender : RollingFileAppender
|
||||
{
|
||||
|
||||
@@ -13,301 +13,8 @@ namespace Umbraco.Core.Logging
|
||||
/// <remarks>
|
||||
/// Borrowed from https://github.com/cjbhaines/Log4Net.Async - will reference Nuget packages directly in v8
|
||||
/// </remarks>
|
||||
public class ParallelForwardingAppender : AsyncForwardingAppenderBase, IDisposable
|
||||
[Obsolete("Use the Log4Net.Async.ParallelForwardingAppender instead this will be removed in future versions")]
|
||||
public class ParallelForwardingAppender : Log4Net.Async.ParallelForwardingAppender
|
||||
{
|
||||
#region Private Members
|
||||
|
||||
private const int DefaultBufferSize = 1000;
|
||||
private BlockingCollection<LoggingEventContext> _loggingEvents;
|
||||
private CancellationTokenSource _loggingCancelationTokenSource;
|
||||
private CancellationToken _loggingCancelationToken;
|
||||
private Task _loggingTask;
|
||||
private Double _shutdownFlushTimeout = 2;
|
||||
private TimeSpan _shutdownFlushTimespan = TimeSpan.FromSeconds(2);
|
||||
private static readonly Type ThisType = typeof(ParallelForwardingAppender);
|
||||
private volatile bool shutDownRequested;
|
||||
private int? bufferSize = DefaultBufferSize;
|
||||
|
||||
#endregion Private Members
|
||||
|
||||
#region Properties
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the number of LoggingEvents that will be buffered. Set to null for unlimited.
|
||||
/// </summary>
|
||||
public override int? BufferSize
|
||||
{
|
||||
get { return bufferSize; }
|
||||
set { bufferSize = value; }
|
||||
}
|
||||
|
||||
public int BufferEntryCount
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_loggingEvents == null) return 0;
|
||||
return _loggingEvents.Count;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the time period in which the system will wait for appenders to flush before canceling the background task.
|
||||
/// </summary>
|
||||
public Double ShutdownFlushTimeout
|
||||
{
|
||||
get
|
||||
{
|
||||
return _shutdownFlushTimeout;
|
||||
}
|
||||
set
|
||||
{
|
||||
_shutdownFlushTimeout = value;
|
||||
}
|
||||
}
|
||||
|
||||
protected override string InternalLoggerName
|
||||
{
|
||||
get
|
||||
{
|
||||
{
|
||||
return "ParallelForwardingAppender";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endregion Properties
|
||||
|
||||
#region Startup
|
||||
|
||||
public override void ActivateOptions()
|
||||
{
|
||||
base.ActivateOptions();
|
||||
_shutdownFlushTimespan = TimeSpan.FromSeconds(_shutdownFlushTimeout);
|
||||
StartForwarding();
|
||||
}
|
||||
|
||||
private void StartForwarding()
|
||||
{
|
||||
if (shutDownRequested)
|
||||
{
|
||||
return;
|
||||
}
|
||||
//Create a collection which will block the thread and wait for new entries
|
||||
//if the collection is empty
|
||||
if (BufferSize.HasValue && BufferSize > 0)
|
||||
{
|
||||
_loggingEvents = new BlockingCollection<LoggingEventContext>(BufferSize.Value);
|
||||
}
|
||||
else
|
||||
{
|
||||
//No limit on the number of events.
|
||||
_loggingEvents = new BlockingCollection<LoggingEventContext>();
|
||||
}
|
||||
//The cancellation token is used to cancel a running task gracefully.
|
||||
_loggingCancelationTokenSource = new CancellationTokenSource();
|
||||
_loggingCancelationToken = _loggingCancelationTokenSource.Token;
|
||||
_loggingTask = new Task(SubscriberLoop, _loggingCancelationToken);
|
||||
_loggingTask.Start();
|
||||
}
|
||||
|
||||
#endregion Startup
|
||||
|
||||
#region Shutdown
|
||||
|
||||
private void CompleteSubscriberTask()
|
||||
{
|
||||
shutDownRequested = true;
|
||||
if (_loggingEvents == null || _loggingEvents.IsAddingCompleted)
|
||||
{
|
||||
return;
|
||||
}
|
||||
//Don't allow more entries to be added.
|
||||
_loggingEvents.CompleteAdding();
|
||||
//Allow some time to flush
|
||||
Thread.Sleep(_shutdownFlushTimespan);
|
||||
if (!_loggingTask.IsCompleted && !_loggingCancelationToken.IsCancellationRequested)
|
||||
{
|
||||
_loggingCancelationTokenSource.Cancel();
|
||||
//Wait here so that the error logging messages do not get into a random order.
|
||||
//Don't pass the cancellation token because we are not interested
|
||||
//in catching the OperationCanceledException that results.
|
||||
_loggingTask.Wait();
|
||||
}
|
||||
if (!_loggingEvents.IsCompleted)
|
||||
{
|
||||
ForwardInternalError("The buffer was not able to be flushed before timeout occurred.", null, ThisType);
|
||||
}
|
||||
}
|
||||
|
||||
protected override void OnClose()
|
||||
{
|
||||
CompleteSubscriberTask();
|
||||
base.OnClose();
|
||||
}
|
||||
|
||||
#endregion Shutdown
|
||||
|
||||
#region Appending
|
||||
|
||||
protected override void Append(LoggingEvent loggingEvent)
|
||||
{
|
||||
if (_loggingEvents == null || _loggingEvents.IsAddingCompleted || loggingEvent == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
loggingEvent.Fix = Fix;
|
||||
//In the case where blocking on a full collection, and the task is subsequently completed, the cancellation token
|
||||
//will prevent the entry from attempting to add to the completed collection which would result in an exception.
|
||||
_loggingEvents.Add(new LoggingEventContext(loggingEvent, HttpContext), _loggingCancelationToken);
|
||||
}
|
||||
|
||||
protected override void Append(LoggingEvent[] loggingEvents)
|
||||
{
|
||||
if (_loggingEvents == null || _loggingEvents.IsAddingCompleted || loggingEvents == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
foreach (var loggingEvent in loggingEvents)
|
||||
{
|
||||
Append(loggingEvent);
|
||||
}
|
||||
}
|
||||
|
||||
#endregion Appending
|
||||
|
||||
#region Forwarding
|
||||
|
||||
/// <summary>
|
||||
/// Iterates over a BlockingCollection containing LoggingEvents.
|
||||
/// </summary>
|
||||
private void SubscriberLoop()
|
||||
{
|
||||
Thread.CurrentThread.Name = String.Format("{0} ParallelForwardingAppender Subscriber Task", Name);
|
||||
//The task will continue in a blocking loop until
|
||||
//the queue is marked as adding completed, or the task is canceled.
|
||||
try
|
||||
{
|
||||
//This call blocks until an item is available or until adding is completed
|
||||
foreach (var entry in _loggingEvents.GetConsumingEnumerable(_loggingCancelationToken))
|
||||
{
|
||||
HttpContext = entry.HttpContext;
|
||||
ForwardLoggingEvent(entry.LoggingEvent, ThisType);
|
||||
}
|
||||
}
|
||||
catch (OperationCanceledException ex)
|
||||
{
|
||||
//The thread was canceled before all entries could be forwarded and the collection completed.
|
||||
ForwardInternalError("Subscriber task was canceled before completion.", ex, ThisType);
|
||||
//Cancellation is called in the CompleteSubscriberTask so don't call that again.
|
||||
}
|
||||
catch (ThreadAbortException ex)
|
||||
{
|
||||
//Thread abort may occur on domain unload.
|
||||
ForwardInternalError("Subscriber task was aborted.", ex, ThisType);
|
||||
//Cannot recover from a thread abort so complete the task.
|
||||
CompleteSubscriberTask();
|
||||
//The exception is swallowed because we don't want the client application
|
||||
//to halt due to a logging issue.
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
//On exception, try to log the exception
|
||||
ForwardInternalError("Subscriber task error in forwarding loop.", ex, ThisType);
|
||||
//Any error in the loop is going to be some sort of extenuating circumstance from which we
|
||||
//probably cannot recover anyway. Complete subscribing.
|
||||
CompleteSubscriberTask();
|
||||
}
|
||||
}
|
||||
|
||||
#endregion Forwarding
|
||||
|
||||
#region IDisposable Implementation
|
||||
|
||||
private bool _disposed = false;
|
||||
|
||||
//Implement IDisposable.
|
||||
public void Dispose()
|
||||
{
|
||||
Dispose(true);
|
||||
GC.SuppressFinalize(this);
|
||||
}
|
||||
|
||||
protected virtual void Dispose(bool disposing)
|
||||
{
|
||||
if (!_disposed)
|
||||
{
|
||||
if (disposing)
|
||||
{
|
||||
if (_loggingTask != null)
|
||||
{
|
||||
if (!(_loggingTask.IsCanceled || _loggingTask.IsCompleted || _loggingTask.IsFaulted))
|
||||
{
|
||||
try
|
||||
{
|
||||
CompleteSubscriberTask();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogLog.Error(ThisType, "Exception Completing Subscriber Task in Dispose Method", ex);
|
||||
}
|
||||
}
|
||||
try
|
||||
{
|
||||
_loggingTask.Dispose();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogLog.Error(ThisType, "Exception Disposing Logging Task", ex);
|
||||
}
|
||||
finally
|
||||
{
|
||||
_loggingTask = null;
|
||||
}
|
||||
}
|
||||
if (_loggingEvents != null)
|
||||
{
|
||||
try
|
||||
{
|
||||
_loggingEvents.Dispose();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogLog.Error(ThisType, "Exception Disposing BlockingCollection", ex);
|
||||
}
|
||||
finally
|
||||
{
|
||||
_loggingEvents = null;
|
||||
}
|
||||
}
|
||||
if (_loggingCancelationTokenSource != null)
|
||||
{
|
||||
try
|
||||
{
|
||||
_loggingCancelationTokenSource.Dispose();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogLog.Error(ThisType, "Exception Disposing CancellationTokenSource", ex);
|
||||
}
|
||||
finally
|
||||
{
|
||||
_loggingCancelationTokenSource = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
_disposed = true;
|
||||
}
|
||||
}
|
||||
|
||||
// Use C# destructor syntax for finalization code.
|
||||
~ParallelForwardingAppender()
|
||||
{
|
||||
// Simply call Dispose(false).
|
||||
Dispose(false);
|
||||
}
|
||||
|
||||
#endregion IDisposable Implementation
|
||||
}
|
||||
}
|
||||
@@ -1,8 +1,14 @@
|
||||
using System.Collections.Generic;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Umbraco.Core.Media
|
||||
{
|
||||
public interface IImageUrlProvider
|
||||
// note: because this interface is obsolete is is *not* IDiscoverable, and in case the
|
||||
// PluginManager is asked to find types implementing this interface it will fall back
|
||||
// to a complete scan.
|
||||
|
||||
[Obsolete("IImageUrlProvider is no longer used and will be removed in future versions")]
|
||||
public interface IImageUrlProvider // IDiscoverable
|
||||
{
|
||||
string Name { get; }
|
||||
string GetImageUrlFromMedia(int mediaId, IDictionary<string, string> parameters);
|
||||
|
||||
@@ -1,6 +1,13 @@
|
||||
namespace Umbraco.Core.Media
|
||||
using System;
|
||||
|
||||
namespace Umbraco.Core.Media
|
||||
{
|
||||
public interface IThumbnailProvider
|
||||
// note: because this interface is obsolete is is *not* IDiscoverable, and in case the
|
||||
// PluginManager is asked to find types implementing this interface it will fall back
|
||||
// to a complete scan.
|
||||
|
||||
[Obsolete("Thumbnails are generated by ImageProcessor, use that instead")]
|
||||
public interface IThumbnailProvider // : IDiscoverable
|
||||
{
|
||||
bool CanProvideThumbnail(string fileUrl);
|
||||
string GetThumbnailUrl(string fileUrl);
|
||||
|
||||
@@ -96,8 +96,7 @@ namespace Umbraco.Core.Media
|
||||
/// <param name="propertyTypeAlias">The property type alias.</param>
|
||||
/// <param name="filepath">The filesystem-relative filepath, or null to clear properties.</param>
|
||||
/// <param name="filestream">The stream containing the file data.</param>
|
||||
/// <param name="image">The file data as an image object.</param>
|
||||
public void Populate(IContentBase content, string propertyTypeAlias, string filepath, Stream filestream, Image image = null)
|
||||
public void Populate(IContentBase content, string propertyTypeAlias, string filepath, Stream filestream)
|
||||
{
|
||||
if (content == null) throw new ArgumentNullException("content");
|
||||
if (propertyTypeAlias == null) throw new ArgumentNullException("propertyTypeAlias");
|
||||
@@ -110,7 +109,7 @@ namespace Umbraco.Core.Media
|
||||
if (autoFillConfig == null) return; // nothing
|
||||
|
||||
// populate
|
||||
Populate(content, autoFillConfig, filepath, filestream, image);
|
||||
Populate(content, autoFillConfig, filepath, filestream);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -158,8 +157,7 @@ namespace Umbraco.Core.Media
|
||||
/// <param name="autoFillConfig"></param>
|
||||
/// <param name="filepath">The filesystem-relative filepath, or null to clear properties.</param>
|
||||
/// <param name="filestream">The stream containing the file data.</param>
|
||||
/// <param name="image">The file data as an image object.</param>
|
||||
public void Populate(IContentBase content, IImagingAutoFillUploadField autoFillConfig, string filepath, Stream filestream, Image image = null)
|
||||
public void Populate(IContentBase content, IImagingAutoFillUploadField autoFillConfig, string filepath, Stream filestream)
|
||||
{
|
||||
if (content == null) throw new ArgumentNullException("content");
|
||||
if (autoFillConfig == null) throw new ArgumentNullException("autoFillConfig");
|
||||
@@ -172,11 +170,7 @@ namespace Umbraco.Core.Media
|
||||
else
|
||||
{
|
||||
var extension = (Path.GetExtension(filepath) ?? "").TrimStart('.');
|
||||
Size? size;
|
||||
if (image == null)
|
||||
size = _mediaFileSystem.IsImageFile(extension) ? (Size?) _mediaFileSystem.GetDimensions(filestream) : null;
|
||||
else
|
||||
size = new Size(image.Width, image.Height);
|
||||
var size = _mediaFileSystem.IsImageFile(extension) ? (Size?)_mediaFileSystem.GetDimensions(filestream) : null;
|
||||
SetProperties(content, autoFillConfig, size, filestream.Length, extension);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -63,49 +63,6 @@ namespace Umbraco.Core.ObjectResolution
|
||||
}
|
||||
}
|
||||
|
||||
// NOTE - the ugly code below exists only because of umbraco.BusinessLogic.Actions.Action.ReRegisterActionsAndHandlers
|
||||
// which wants to re-register actions and handlers instead of properly restarting the application. Don't even think
|
||||
// about using it for anything else. Also, while the backdoor is open, the resolution system is locked so nothing
|
||||
// can work properly => deadlocks. Therefore, open the backdoor, do resolution changes EXCLUSIVELY, and close the door!
|
||||
|
||||
/// <summary>
|
||||
/// Returns a disposable object that reprents dirty access to temporarily unfrozen resolution configuration.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// <para>Should not be used.</para>
|
||||
/// <para>Should be used in a <c>using(Resolution.DirtyBackdoorToConfiguration) { ... }</c> mode.</para>
|
||||
/// <para>Because we just lift the frozen state, and we don't actually re-freeze, the <c>Frozen</c> event does not trigger.</para>
|
||||
/// </remarks>
|
||||
internal static IDisposable DirtyBackdoorToConfiguration
|
||||
{
|
||||
get { return new DirtyBackdoor(); }
|
||||
}
|
||||
|
||||
// keep the class here because it needs write-access to Resolution.IsFrozen
|
||||
private class DirtyBackdoor : IDisposable
|
||||
{
|
||||
|
||||
private readonly IDisposable _lock;
|
||||
private readonly bool _frozen;
|
||||
|
||||
public DirtyBackdoor()
|
||||
{
|
||||
LogHelper.Debug(typeof(DirtyBackdoor), "Creating back door for resolution");
|
||||
|
||||
_lock = new WriteLock(ConfigurationLock);
|
||||
_frozen = _isFrozen;
|
||||
_isFrozen = false;
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
LogHelper.Debug(typeof(DirtyBackdoor), "Disposing back door for resolution");
|
||||
|
||||
_isFrozen = _frozen;
|
||||
_lock.Dispose();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Freezes resolution.
|
||||
/// </summary>
|
||||
|
||||
@@ -2,11 +2,12 @@
|
||||
using System.Collections.Concurrent;
|
||||
using System.Linq.Expressions;
|
||||
using System.Reflection;
|
||||
using umbraco.interfaces;
|
||||
using Umbraco.Core.Persistence.SqlSyntax;
|
||||
|
||||
namespace Umbraco.Core.Persistence.Mappers
|
||||
{
|
||||
public abstract class BaseMapper
|
||||
public abstract class BaseMapper : IDiscoverable
|
||||
{
|
||||
private readonly ISqlSyntaxProvider _sqlSyntax;
|
||||
|
||||
|
||||
@@ -1,9 +1,11 @@
|
||||
namespace Umbraco.Core.Persistence.Migrations
|
||||
using umbraco.interfaces;
|
||||
|
||||
namespace Umbraco.Core.Persistence.Migrations
|
||||
{
|
||||
/// <summary>
|
||||
/// Marker interface for database migrations
|
||||
/// </summary>
|
||||
public interface IMigration
|
||||
public interface IMigration : IDiscoverable
|
||||
{
|
||||
void Up();
|
||||
void Down();
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using Umbraco.Core.Persistence.Migrations.Syntax.Alter.Column;
|
||||
using System;
|
||||
using Umbraco.Core.Persistence.Migrations.Syntax.Alter.Column;
|
||||
using Umbraco.Core.Persistence.Migrations.Syntax.Alter.Expressions;
|
||||
using Umbraco.Core.Persistence.Migrations.Syntax.Alter.Table;
|
||||
using Umbraco.Core.Persistence.SqlSyntax;
|
||||
@@ -25,6 +26,15 @@ namespace Umbraco.Core.Persistence.Migrations.Syntax.Alter
|
||||
return new AlterTableBuilder(_context, _databaseProviders, expression);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The problem with this is that only under particular circumstances is the expression added to the context
|
||||
/// so you wouldn't actually know if you are using it correctly or not and chances are you are not and therefore
|
||||
/// the statement won't even execute whereas using the IAlterTableSyntax to modify a column is guaranteed to add
|
||||
/// the expression to the context.
|
||||
/// </summary>
|
||||
/// <param name="columnName"></param>
|
||||
/// <returns></returns>
|
||||
[Obsolete("Use the IAlterTableSyntax to modify a column instead, this will be removed in future versions")]
|
||||
public IAlterColumnSyntax Column(string columnName)
|
||||
{
|
||||
var expression = new AlterColumnExpression(_context.CurrentDatabaseProvider, _databaseProviders, _sqlSyntax) {Column = {Name = columnName}};
|
||||
|
||||
@@ -1,11 +1,22 @@
|
||||
using Umbraco.Core.Persistence.Migrations.Syntax.Alter.Column;
|
||||
using System;
|
||||
using Umbraco.Core.Persistence.Migrations.Syntax.Alter.Column;
|
||||
using Umbraco.Core.Persistence.Migrations.Syntax.Alter.Table;
|
||||
|
||||
namespace Umbraco.Core.Persistence.Migrations.Syntax.Alter
|
||||
{
|
||||
public interface IAlterSyntaxBuilder : IFluentSyntax
|
||||
{
|
||||
IAlterTableSyntax Table(string tableName);
|
||||
IAlterTableSyntax Table(string tableName);
|
||||
|
||||
/// <summary>
|
||||
/// The problem with this is that only under particular circumstances is the expression added to the context
|
||||
/// so you wouldn't actually know if you are using it correctly or not and chances are you are not and therefore
|
||||
/// the statement won't even execute whereas using the IAlterTableSyntax to modify a column is guaranteed to add
|
||||
/// the expression to the context.
|
||||
/// </summary>
|
||||
/// <param name="columnName"></param>
|
||||
/// <returns></returns>
|
||||
[Obsolete("Use the IAlterTableSyntax to modify a column instead, this will be removed in future versions")]
|
||||
IAlterColumnSyntax Column(string columnName);
|
||||
}
|
||||
}
|
||||
+37
-12
@@ -4,7 +4,7 @@ using Umbraco.Core.Persistence.SqlSyntax;
|
||||
|
||||
namespace Umbraco.Core.Persistence.Migrations.Upgrades.TargetVersionSevenSixZero
|
||||
{
|
||||
[Migration("7.6.0", 0, Constants.System.UmbracoMigrationName)]
|
||||
[Migration("7.6.0", 3, Constants.System.UmbracoMigrationName)]
|
||||
public class AddIndexToCmsMemberLoginName : MigrationBase
|
||||
{
|
||||
public AddIndexToCmsMemberLoginName(ISqlSyntaxProvider sqlSyntax, ILogger logger)
|
||||
@@ -12,18 +12,43 @@ namespace Umbraco.Core.Persistence.Migrations.Upgrades.TargetVersionSevenSixZero
|
||||
{ }
|
||||
|
||||
public override void Up()
|
||||
{
|
||||
var dbIndexes = SqlSyntax.GetDefinedIndexesDefinitions(Context.Database);
|
||||
|
||||
//make sure it doesn't already exist
|
||||
if (dbIndexes.Any(x => x.IndexName.InvariantEquals("IX_cmsMember_LoginName")) == false)
|
||||
{
|
||||
Execute.Code(database =>
|
||||
{
|
||||
Create.Index("IX_cmsMember_LoginName").OnTable("cmsMember")
|
||||
.OnColumn("LoginName")
|
||||
.Ascending()
|
||||
.WithOptions()
|
||||
.NonClustered();
|
||||
}
|
||||
//Now we need to check if we can actually d6 this because we won't be able to if there's data in there that is too long
|
||||
//http://issues.umbraco.org/issue/U4-9758
|
||||
|
||||
var colLen = (SqlSyntax is MySqlSyntaxProvider)
|
||||
? database.ExecuteScalar<int?>("select max(LENGTH(LoginName)) from cmsMember")
|
||||
: database.ExecuteScalar<int?>("select max(datalength(LoginName)) from cmsMember");
|
||||
|
||||
if (colLen < 900 == false && colLen != null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
var dbIndexes = SqlSyntax.GetDefinedIndexesDefinitions(Context.Database);
|
||||
|
||||
//make sure it doesn't already exist
|
||||
if (dbIndexes.Any(x => x.IndexName.InvariantEquals("IX_cmsMember_LoginName")) == false)
|
||||
{
|
||||
var localContext = new LocalMigrationContext(Context.CurrentDatabaseProvider, database, SqlSyntax, Logger);
|
||||
|
||||
//we can apply the index
|
||||
localContext.Create.Index("IX_cmsMember_LoginName").OnTable("cmsMember")
|
||||
.OnColumn("LoginName")
|
||||
.Ascending()
|
||||
.WithOptions()
|
||||
.NonClustered();
|
||||
|
||||
return localContext.GetSql();
|
||||
}
|
||||
|
||||
return null;
|
||||
|
||||
});
|
||||
|
||||
|
||||
}
|
||||
|
||||
public override void Down()
|
||||
|
||||
+3
-4
@@ -1,11 +1,10 @@
|
||||
using Umbraco.Core.Configuration;
|
||||
using Umbraco.Core.Logging;
|
||||
using Umbraco.Core.Logging;
|
||||
using Umbraco.Core.Models.Rdbms;
|
||||
using Umbraco.Core.Persistence.SqlSyntax;
|
||||
|
||||
namespace Umbraco.Core.Persistence.Migrations.Upgrades.TargetVersionSevenFiveFive
|
||||
namespace Umbraco.Core.Persistence.Migrations.Upgrades.TargetVersionSevenSixZero
|
||||
{
|
||||
[Migration("7.5.5", 101, Constants.System.UmbracoMigrationName)]
|
||||
[Migration("7.6.0", 101, Constants.System.UmbracoMigrationName)]
|
||||
public class AddLockObjects : MigrationBase
|
||||
{
|
||||
public AddLockObjects(ISqlSyntaxProvider sqlSyntax, ILogger logger)
|
||||
+2
-3
@@ -1,11 +1,10 @@
|
||||
using System.Linq;
|
||||
using Umbraco.Core.Configuration;
|
||||
using Umbraco.Core.Logging;
|
||||
using Umbraco.Core.Persistence.SqlSyntax;
|
||||
|
||||
namespace Umbraco.Core.Persistence.Migrations.Upgrades.TargetVersionSevenFiveFive
|
||||
namespace Umbraco.Core.Persistence.Migrations.Upgrades.TargetVersionSevenSixZero
|
||||
{
|
||||
[Migration("7.5.5", 100, Constants.System.UmbracoMigrationName)]
|
||||
[Migration("7.6.0", 100, Constants.System.UmbracoMigrationName)]
|
||||
public class AddLockTable : MigrationBase
|
||||
{
|
||||
public AddLockTable(ISqlSyntaxProvider sqlSyntax, ILogger logger)
|
||||
+48
@@ -0,0 +1,48 @@
|
||||
using System;
|
||||
using System.Linq;
|
||||
using Umbraco.Core.Logging;
|
||||
using Umbraco.Core.Persistence.SqlSyntax;
|
||||
|
||||
namespace Umbraco.Core.Persistence.Migrations.Upgrades.TargetVersionSevenSixZero
|
||||
{
|
||||
[Migration("7.6.0", 0, Constants.System.UmbracoMigrationName)]
|
||||
public class NormalizeTemplateGuids : MigrationBase
|
||||
{
|
||||
public NormalizeTemplateGuids(ISqlSyntaxProvider sqlSyntax, ILogger logger)
|
||||
: base(sqlSyntax, logger)
|
||||
{ }
|
||||
|
||||
public override void Up()
|
||||
{
|
||||
Execute.Code(UpdateTemplateGuids);
|
||||
}
|
||||
|
||||
private static string UpdateTemplateGuids(Database database)
|
||||
{
|
||||
// we need this migration because ppl running pre-7.6 on Cloud and Courier have templates in different
|
||||
// environments having different GUIDs (Courier does not sync template GUIDs) and we need to normalize
|
||||
// these GUIDs so templates with the same alias on different environments have the same GUID.
|
||||
// however, if already running a prerelease version of 7.6, we do NOT want to normalize the GUIDs as quite
|
||||
// probably, we are already running Deploy and the GUIDs are OK. assuming noone is running a prerelease
|
||||
// of 7.6 on Courier.
|
||||
// so... testing if we already have a 7.6.0 version installed. not pretty but...?
|
||||
//
|
||||
var version = database.FirstOrDefault<string>("SELECT version FROM umbracoMigration WHERE name=@name ORDER BY version DESC", new { name = Constants.System.UmbracoMigrationName });
|
||||
if (version != null && version.StartsWith("7.6.0")) return string.Empty;
|
||||
|
||||
var updates = database.Query<dynamic>("SELECT id, text FROM umbracoNode WHERE nodeObjectType = @guid", new { guid = Constants.ObjectTypes.TemplateTypeGuid})
|
||||
.Select(template => Tuple.Create((int) template.id, ("template____" + (string) template.text).ToGuid()))
|
||||
.ToList();
|
||||
|
||||
foreach (var update in updates)
|
||||
database.Execute("UPDATE umbracoNode set uniqueId=@guid WHERE id=@id", new { guid = update.Item2, id = update.Item1 });
|
||||
|
||||
return string.Empty;
|
||||
}
|
||||
|
||||
public override void Down()
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
}
|
||||
+52
@@ -0,0 +1,52 @@
|
||||
using System.Linq;
|
||||
using Umbraco.Core.Logging;
|
||||
using Umbraco.Core.Persistence.SqlSyntax;
|
||||
|
||||
namespace Umbraco.Core.Persistence.Migrations.Upgrades.TargetVersionSevenSixZero
|
||||
{
|
||||
[Migration("7.6.0", 2, Constants.System.UmbracoMigrationName)]
|
||||
public class ReduceLoginNameColumnsSize : MigrationBase
|
||||
{
|
||||
public ReduceLoginNameColumnsSize(ISqlSyntaxProvider sqlSyntax, ILogger logger)
|
||||
: base(sqlSyntax, logger)
|
||||
{ }
|
||||
|
||||
public override void Up()
|
||||
{
|
||||
//Now we need to check if we can actually d6 this because we won't be able to if there's data in there that is too long
|
||||
//http://issues.umbraco.org/issue/U4-9758
|
||||
|
||||
Execute.Code(database =>
|
||||
{
|
||||
var dbIndexes = SqlSyntax.GetDefinedIndexesDefinitions(database);
|
||||
|
||||
var colLen = (SqlSyntax is MySqlSyntaxProvider)
|
||||
? database.ExecuteScalar<int?>("select max(LENGTH(LoginName)) from cmsMember")
|
||||
: database.ExecuteScalar<int?>("select max(datalength(LoginName)) from cmsMember");
|
||||
|
||||
if (colLen < 900 == false) return null;
|
||||
|
||||
var localContext = new LocalMigrationContext(Context.CurrentDatabaseProvider, database, SqlSyntax, Logger);
|
||||
|
||||
//if it exists we need to drop it first
|
||||
if (dbIndexes.Any(x => x.IndexName.InvariantEquals("IX_cmsMember_LoginName")))
|
||||
{
|
||||
localContext.Delete.Index("IX_cmsMember_LoginName").OnTable("cmsMember");
|
||||
}
|
||||
|
||||
//we can apply the col length change
|
||||
localContext.Alter.Table("cmsMember")
|
||||
.AlterColumn("LoginName")
|
||||
.AsString(225)
|
||||
.NotNullable();
|
||||
|
||||
return localContext.GetSql();
|
||||
});
|
||||
}
|
||||
|
||||
public override void Down()
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -29,7 +29,7 @@ namespace Umbraco.Core.Persistence.Migrations.Upgrades.TargetVersionSevenThreeZe
|
||||
}).ToArray();
|
||||
|
||||
//must be non-nullable
|
||||
Alter.Column("uniqueID").OnTable("umbracoNode").AsGuid().NotNullable();
|
||||
Alter.Table("umbracoNode").AlterColumn("uniqueID").AsGuid().NotNullable();
|
||||
|
||||
//make sure it already exists
|
||||
if (dbIndexes.Any(x => x.IndexName.InvariantEquals("IX_umbracoNodeUniqueID")))
|
||||
|
||||
@@ -132,6 +132,11 @@ namespace Umbraco.Core.Persistence.Repositories
|
||||
|
||||
Database.Update(dto);
|
||||
|
||||
foreach (var removedRule in entity.RemovedRules)
|
||||
{
|
||||
Database.Delete<AccessRuleDto>("WHERE id=@Id", new { Id = removedRule });
|
||||
}
|
||||
|
||||
foreach (var rule in entity.Rules)
|
||||
{
|
||||
if (rule.HasIdentity)
|
||||
@@ -157,10 +162,6 @@ namespace Umbraco.Core.Persistence.Repositories
|
||||
rule.Id = rule.Key.GetHashCode();
|
||||
}
|
||||
}
|
||||
foreach (var removedRule in entity.RemovedRules)
|
||||
{
|
||||
Database.Delete<AccessRuleDto>("WHERE id=@Id", new {Id = removedRule});
|
||||
}
|
||||
|
||||
entity.ClearRemovedRules();
|
||||
|
||||
|
||||
+706
-631
File diff suppressed because it is too large
Load Diff
@@ -1,8 +1,9 @@
|
||||
using System.Collections.Generic;
|
||||
using umbraco.interfaces;
|
||||
|
||||
namespace Umbraco.Core.PropertyEditors
|
||||
{
|
||||
public interface IParameterEditor
|
||||
public interface IParameterEditor : IDiscoverable
|
||||
{
|
||||
/// <summary>
|
||||
/// The id of the property editor
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using System;
|
||||
using umbraco.interfaces;
|
||||
|
||||
namespace Umbraco.Core.PropertyEditors
|
||||
{
|
||||
@@ -7,8 +8,8 @@ namespace Umbraco.Core.PropertyEditors
|
||||
/// </summary>
|
||||
// todo: drop IPropertyEditorValueConverter support (when?).
|
||||
[Obsolete("Use IPropertyValueConverter.")]
|
||||
public interface IPropertyEditorValueConverter
|
||||
{
|
||||
public interface IPropertyEditorValueConverter : IDiscoverable
|
||||
{
|
||||
/// <summary>
|
||||
/// Returns a value indicating whether this provider applies to the specified property.
|
||||
/// </summary>
|
||||
|
||||
@@ -1,11 +1,12 @@
|
||||
using Umbraco.Core.Models.PublishedContent;
|
||||
using umbraco.interfaces;
|
||||
using Umbraco.Core.Models.PublishedContent;
|
||||
|
||||
namespace Umbraco.Core.PropertyEditors
|
||||
{
|
||||
/// <summary>
|
||||
/// Provides published content properties conversion service.
|
||||
/// </summary>
|
||||
public interface IPropertyValueConverter
|
||||
public interface IPropertyValueConverter : IDiscoverable
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets a value indicating whether the converter supports a property type.
|
||||
|
||||
@@ -14,13 +14,13 @@ namespace Umbraco.Core.PropertyEditors
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This resolver will contain any parameter editors defined in manifests as well as any property editors defined in manifests
|
||||
/// that have the IsParameterEditorFlag = true and any PropertyEditors found in c# that have this flag as well.
|
||||
/// that have the IsParameterEditorFlag = true and any PropertyEditors found in c# that have this flag as well.
|
||||
/// </remarks>
|
||||
internal class ParameterEditorResolver : LazyManyObjectsResolverBase<ParameterEditorResolver, IParameterEditor>
|
||||
{
|
||||
private readonly ManifestBuilder _builder;
|
||||
private readonly IContentSection _contentSection;
|
||||
|
||||
|
||||
public ParameterEditorResolver(IServiceProvider serviceProvider, ILogger logger, Func<IEnumerable<Type>> typeListProducerList, ManifestBuilder builder)
|
||||
: base(serviceProvider, logger, typeListProducerList, ObjectLifetimeScope.Application)
|
||||
{
|
||||
@@ -33,47 +33,51 @@ namespace Umbraco.Core.PropertyEditors
|
||||
/// </summary>
|
||||
public IEnumerable<IParameterEditor> ParameterEditors
|
||||
{
|
||||
get
|
||||
get { return GetParameterEditors(); }
|
||||
}
|
||||
|
||||
public IEnumerable<IParameterEditor> GetParameterEditors(bool includeDeprecated = false)
|
||||
{
|
||||
// all property editors and parameter editors
|
||||
// except property editors where !IsParameterEditor
|
||||
var values = Values
|
||||
.Where(x => x is PropertyEditor == false || ((PropertyEditor) x).IsParameterEditor);
|
||||
|
||||
// union all manifest parameter editors
|
||||
values = values
|
||||
.Union(_builder.ParameterEditors);
|
||||
|
||||
// union all manifest property editors where IsParameterEditor
|
||||
values = values
|
||||
.Union(_builder.PropertyEditors.Where(x => x.IsParameterEditor));
|
||||
|
||||
if (includeDeprecated == false && _contentSection.ShowDeprecatedPropertyEditors == false)
|
||||
{
|
||||
// all property editors and parameter editors
|
||||
// except property editors where !IsParameterEditor
|
||||
var values = Values
|
||||
.Where(x => x is PropertyEditor == false || ((PropertyEditor) x).IsParameterEditor);
|
||||
|
||||
// union all manifest parameter editors
|
||||
// except deprecated property editors
|
||||
values = values
|
||||
.Union(_builder.ParameterEditors);
|
||||
|
||||
// union all manifest property editors where IsParameterEditor
|
||||
values = values
|
||||
.Union(_builder.PropertyEditors.Where(x => x.IsParameterEditor));
|
||||
|
||||
if (_contentSection.ShowDeprecatedPropertyEditors == false)
|
||||
{
|
||||
// except deprecated property editors
|
||||
values = values
|
||||
.Where(x => x is PropertyEditor == false || ((PropertyEditor) x).IsDeprecated == false);
|
||||
}
|
||||
|
||||
return values;
|
||||
.Where(x => x is PropertyEditor == false || ((PropertyEditor) x).IsDeprecated == false);
|
||||
}
|
||||
|
||||
return values;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns a property editor by alias
|
||||
/// </summary>
|
||||
/// <param name="alias"></param>
|
||||
/// <param name="includeDeprecated"></param>
|
||||
/// <returns></returns>
|
||||
public IParameterEditor GetByAlias(string alias)
|
||||
public IParameterEditor GetByAlias(string alias, bool includeDeprecated = false)
|
||||
{
|
||||
var found = ParameterEditors.SingleOrDefault(x => x.Alias == alias);
|
||||
var paramEditors = GetParameterEditors(includeDeprecated).ToArray();
|
||||
var found = paramEditors.SingleOrDefault(x => x.Alias == alias);
|
||||
if (found != null) return found;
|
||||
|
||||
|
||||
//couldn't find one, so try the map
|
||||
var mapped = LegacyParameterEditorAliasConverter.GetNewAliasFromLegacyAlias(alias);
|
||||
return mapped == null
|
||||
? null
|
||||
: ParameterEditors.SingleOrDefault(x => x.Alias == mapped);
|
||||
return mapped == null
|
||||
? null
|
||||
: paramEditors.SingleOrDefault(x => x.Alias == mapped);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,5 @@
|
||||
using System;
|
||||
using System.Linq;
|
||||
using Umbraco.Core.Logging;
|
||||
using Umbraco.Core.Models;
|
||||
using Umbraco.Core.Services;
|
||||
@@ -26,12 +27,16 @@ namespace Umbraco.Core.Publishing
|
||||
public int CheckPendingAndProcess()
|
||||
{
|
||||
var counter = 0;
|
||||
foreach (var d in _contentService.GetContentForRelease())
|
||||
var contentForRelease = _contentService.GetContentForRelease().ToArray();
|
||||
if (contentForRelease.Length > 0)
|
||||
LogHelper.Debug<ScheduledPublisher>(string.Format("There's {0} item(s) of content to be published", contentForRelease.Length));
|
||||
foreach (var d in contentForRelease)
|
||||
{
|
||||
try
|
||||
{
|
||||
d.ReleaseDate = null;
|
||||
var result = _contentService.SaveAndPublishWithStatus(d, (int)d.GetWriterProfile().Id);
|
||||
LogHelper.Debug<ContentService>(string.Format("Result of publish attempt: {0}", result.Result.StatusType));
|
||||
if (result.Success == false)
|
||||
{
|
||||
if (result.Exception != null)
|
||||
@@ -54,7 +59,11 @@ namespace Umbraco.Core.Publishing
|
||||
throw;
|
||||
}
|
||||
}
|
||||
foreach (var d in _contentService.GetContentForExpiration())
|
||||
|
||||
var contentForExpiration = _contentService.GetContentForExpiration().ToArray();
|
||||
if (contentForExpiration.Length > 0)
|
||||
LogHelper.Debug<ScheduledPublisher>(string.Format("There's {0} item(s) of content to be unpublished", contentForExpiration.Length));
|
||||
foreach (var d in contentForExpiration)
|
||||
{
|
||||
try
|
||||
{
|
||||
|
||||
@@ -80,7 +80,41 @@ namespace Umbraco.Core.Security
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This will return the current back office identity if the IPrincipal is the correct type
|
||||
/// </summary>
|
||||
/// <param name="user"></param>
|
||||
/// <returns></returns>
|
||||
internal static UmbracoBackOfficeIdentity GetUmbracoIdentity(this IPrincipal user)
|
||||
{
|
||||
//If it's already a UmbracoBackOfficeIdentity
|
||||
var backOfficeIdentity = user.Identity as UmbracoBackOfficeIdentity;
|
||||
if (backOfficeIdentity != null) return backOfficeIdentity;
|
||||
|
||||
//Check if there's more than one identity assigned and see if it's a UmbracoBackOfficeIdentity and use that
|
||||
var claimsPrincipal = user as ClaimsPrincipal;
|
||||
if (claimsPrincipal != null)
|
||||
{
|
||||
backOfficeIdentity = claimsPrincipal.Identities.OfType<UmbracoBackOfficeIdentity>().FirstOrDefault();
|
||||
if (backOfficeIdentity != null) return backOfficeIdentity;
|
||||
}
|
||||
|
||||
//Otherwise convert to a UmbracoBackOfficeIdentity if it's auth'd and has the back office session
|
||||
var claimsIdentity = user.Identity as ClaimsIdentity;
|
||||
if (claimsIdentity != null && claimsIdentity.IsAuthenticated && claimsIdentity.HasClaim(x => x.Type == Constants.Security.SessionIdClaimType))
|
||||
{
|
||||
try
|
||||
{
|
||||
return UmbracoBackOfficeIdentity.FromClaimsIdentity(claimsIdentity);
|
||||
}
|
||||
catch (InvalidOperationException)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This will return the current back office identity.
|
||||
@@ -100,31 +134,8 @@ namespace Umbraco.Core.Security
|
||||
if (http.User == null) return null; //there's no user at all so no identity
|
||||
|
||||
//If it's already a UmbracoBackOfficeIdentity
|
||||
var backOfficeIdentity = http.User.Identity as UmbracoBackOfficeIdentity;
|
||||
if (backOfficeIdentity != null) return backOfficeIdentity;
|
||||
|
||||
//Check if there's more than one identity assigned and see if it's a UmbracoBackOfficeIdentity and use that
|
||||
var claimsPrincipal = http.User as ClaimsPrincipal;
|
||||
if (claimsPrincipal != null)
|
||||
{
|
||||
backOfficeIdentity = claimsPrincipal.Identities.OfType<UmbracoBackOfficeIdentity>().FirstOrDefault();
|
||||
if (backOfficeIdentity != null) return backOfficeIdentity;
|
||||
}
|
||||
|
||||
//Otherwise convert to a UmbracoBackOfficeIdentity if it's auth'd and has the back office session
|
||||
var claimsIdentity = http.User.Identity as ClaimsIdentity;
|
||||
if (claimsIdentity != null && claimsIdentity.IsAuthenticated && claimsIdentity.HasClaim(x => x.Type == Constants.Security.SessionIdClaimType))
|
||||
{
|
||||
try
|
||||
{
|
||||
return UmbracoBackOfficeIdentity.FromClaimsIdentity(claimsIdentity);
|
||||
}
|
||||
catch (InvalidOperationException ex)
|
||||
{
|
||||
//This will occur if the required claim types are missing which would mean something strange is going on
|
||||
LogHelper.Error(typeof(AuthenticationExtensions), "The current identity cannot be converted to " + typeof(UmbracoBackOfficeIdentity), ex);
|
||||
}
|
||||
}
|
||||
var backOfficeIdentity = GetUmbracoIdentity(http.User);
|
||||
if (backOfficeIdentity != null) return backOfficeIdentity;
|
||||
|
||||
if (authenticateRequestIfNotFound == false) return null;
|
||||
|
||||
|
||||
@@ -9,6 +9,7 @@ using System.Web.Configuration;
|
||||
using System.Web.Hosting;
|
||||
using System.Web.Security;
|
||||
using Umbraco.Core.Logging;
|
||||
using Umbraco.Core.Models;
|
||||
|
||||
namespace Umbraco.Core.Security
|
||||
{
|
||||
@@ -520,7 +521,11 @@ namespace Umbraco.Core.Security
|
||||
|
||||
public override string ResetPassword(string username, string answer)
|
||||
{
|
||||
if (EnablePasswordReset == false)
|
||||
var userService = ApplicationContext.Current == null ? null : ApplicationContext.Current.Services.UserService;
|
||||
|
||||
var canReset = this.CanResetPassword(userService);
|
||||
|
||||
if (canReset == false)
|
||||
{
|
||||
throw new NotSupportedException("Password reset is not supported");
|
||||
}
|
||||
|
||||
@@ -9,12 +9,45 @@ using System.Web;
|
||||
using System.Web.Hosting;
|
||||
using System.Web.Security;
|
||||
using Umbraco.Core.Configuration;
|
||||
using Umbraco.Core.Models;
|
||||
using Umbraco.Core.Security;
|
||||
using Umbraco.Core.Services;
|
||||
|
||||
namespace Umbraco.Core.Security
|
||||
{
|
||||
public static class MembershipProviderExtensions
|
||||
{
|
||||
/// <summary>
|
||||
/// Extension method to check if a password can be reset based on a given provider and the current request (logged in user)
|
||||
/// </summary>
|
||||
/// <param name="provider"></param>
|
||||
/// <param name="userService"></param>
|
||||
/// <returns></returns>
|
||||
internal static bool CanResetPassword(this MembershipProvider provider, IUserService userService)
|
||||
{
|
||||
if (provider == null) throw new ArgumentNullException("provider");
|
||||
|
||||
var canReset = provider.EnablePasswordReset;
|
||||
|
||||
if (userService == null) return canReset;
|
||||
|
||||
//we need to check for the special case in which a user is an admin - in which acse they can reset the password even if EnablePasswordReset == false
|
||||
if (provider.EnablePasswordReset == false)
|
||||
{
|
||||
var identity = Thread.CurrentPrincipal.GetUmbracoIdentity();
|
||||
if (identity != null)
|
||||
{
|
||||
var user = userService.GetByUsername(identity.Username);
|
||||
var userIsAdmin = user.IsAdmin();
|
||||
if (userIsAdmin)
|
||||
{
|
||||
canReset = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return canReset;
|
||||
}
|
||||
|
||||
internal static MembershipUserCollection FindUsersByName(this MembershipProvider provider, string usernameToMatch)
|
||||
{
|
||||
int totalRecords = 0;
|
||||
|
||||
@@ -1124,7 +1124,9 @@ namespace Umbraco.Core.Services
|
||||
/// <returns>True if unpublishing succeeded, otherwise False</returns>
|
||||
public bool UnPublish(IContent content, int userId = 0)
|
||||
{
|
||||
return ((IContentServiceOperations)this).UnPublish(content, userId).Success;
|
||||
var attempt = ((IContentServiceOperations)this).UnPublish(content, userId);
|
||||
LogHelper.Debug<ContentService>(string.Format("Result of unpublish attempt: {0}", attempt.Result.StatusType));
|
||||
return attempt.Success;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -19,14 +19,15 @@ namespace Umbraco.Core.Services
|
||||
/// </summary>
|
||||
public class ContentTypeService : ContentTypeServiceBase, IContentTypeService
|
||||
{
|
||||
private readonly IContentService _contentService;
|
||||
private readonly IContentService _contentService;
|
||||
private readonly IMediaService _mediaService;
|
||||
|
||||
//Support recursive locks because some of the methods that require locking call other methods that require locking.
|
||||
//for example, the Move method needs to be locked but this calls the Save method which also needs to be locked.
|
||||
private static readonly ReaderWriterLockSlim Locker = new ReaderWriterLockSlim(LockRecursionPolicy.SupportsRecursion);
|
||||
|
||||
public ContentTypeService(IDatabaseUnitOfWorkProvider provider, RepositoryFactory repositoryFactory, ILogger logger, IEventMessagesFactory eventMessagesFactory, IContentService contentService, IMediaService mediaService)
|
||||
public ContentTypeService(IDatabaseUnitOfWorkProvider provider, RepositoryFactory repositoryFactory, ILogger logger, IEventMessagesFactory eventMessagesFactory, IContentService contentService,
|
||||
IMediaService mediaService)
|
||||
: base(provider, repositoryFactory, logger, eventMessagesFactory)
|
||||
{
|
||||
if (contentService == null) throw new ArgumentNullException("contentService");
|
||||
@@ -210,7 +211,7 @@ namespace Umbraco.Core.Services
|
||||
|
||||
public IEnumerable<EntityContainer> GetMediaTypeContainers(IMediaType mediaType)
|
||||
{
|
||||
var ancestorIds = mediaType.Path.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries)
|
||||
var ancestorIds = mediaType.Path.Split(new[] {','}, StringSplitOptions.RemoveEmptyEntries)
|
||||
.Select(x =>
|
||||
{
|
||||
var asInt = x.TryConvertTo<int>();
|
||||
@@ -297,7 +298,7 @@ namespace Umbraco.Core.Services
|
||||
repo.Delete(container);
|
||||
uow.Commit();
|
||||
|
||||
uow.Events.Dispatch(DeletedContentTypeContainer, this, new DeleteEventArgs<EntityContainer>(container, evtMsgs));
|
||||
uow.Events.Dispatch(DeletedContentTypeContainer, this, new DeleteEventArgs<EntityContainer>(container, evtMsgs), "DeletedContentTypeContainer");
|
||||
|
||||
return OperationStatus.Success(evtMsgs);
|
||||
//TODO: Audit trail ?
|
||||
@@ -425,7 +426,7 @@ namespace Umbraco.Core.Services
|
||||
|
||||
clone.Name = name;
|
||||
|
||||
var compositionAliases = clone.CompositionAliases().Except(new[] { alias }).ToList();
|
||||
var compositionAliases = clone.CompositionAliases().Except(new[] {alias}).ToList();
|
||||
//remove all composition that is not it's current alias
|
||||
foreach (var a in compositionAliases)
|
||||
{
|
||||
@@ -712,7 +713,7 @@ namespace Umbraco.Core.Services
|
||||
var comparer = new DelegateEqualityComparer<IContentTypeComposition>((x, y) => x.Id == y.Id, x => x.Id);
|
||||
var dependencies = new HashSet<IContentTypeComposition>(compositions, comparer);
|
||||
var stack = new Stack<IContentTypeComposition>();
|
||||
indirectReferences.ForEach(stack.Push);//Push indirect references to a stack, so we can add recursively
|
||||
indirectReferences.ForEach(stack.Push); //Push indirect references to a stack, so we can add recursively
|
||||
while (stack.Count > 0)
|
||||
{
|
||||
var indirectReference = stack.Pop();
|
||||
@@ -770,6 +771,8 @@ namespace Umbraco.Core.Services
|
||||
|
||||
ValidateLocked(contentType); // throws if invalid
|
||||
contentType.CreatorId = userId;
|
||||
if (contentType.Description == string.Empty)
|
||||
contentType.Description = null;
|
||||
repository.AddOrUpdate(contentType);
|
||||
|
||||
uow.Commit();
|
||||
@@ -812,6 +815,8 @@ namespace Umbraco.Core.Services
|
||||
foreach (var contentType in asArray)
|
||||
{
|
||||
contentType.CreatorId = userId;
|
||||
if (contentType.Description == string.Empty)
|
||||
contentType.Description = null;
|
||||
repository.AddOrUpdate(contentType);
|
||||
}
|
||||
|
||||
@@ -1233,6 +1238,8 @@ namespace Umbraco.Core.Services
|
||||
|
||||
ValidateLocked(mediaType); // throws if invalid
|
||||
mediaType.CreatorId = userId;
|
||||
if (mediaType.Description == string.Empty)
|
||||
mediaType.Description = null;
|
||||
repository.AddOrUpdate(mediaType);
|
||||
uow.Commit();
|
||||
|
||||
@@ -1274,6 +1281,8 @@ namespace Umbraco.Core.Services
|
||||
foreach (var mediaType in asArray)
|
||||
{
|
||||
mediaType.CreatorId = userId;
|
||||
if (mediaType.Description == string.Empty)
|
||||
mediaType.Description = null;
|
||||
repository.AddOrUpdate(mediaType);
|
||||
}
|
||||
|
||||
@@ -1452,40 +1461,40 @@ namespace Umbraco.Core.Services
|
||||
/// </summary>
|
||||
public static event TypedEventHandler<IContentTypeService, DeleteEventArgs<IContentType>> DeletingContentType;
|
||||
|
||||
/// <summary>
|
||||
/// Occurs after Delete
|
||||
/// </summary>
|
||||
public static event TypedEventHandler<IContentTypeService, DeleteEventArgs<IContentType>> DeletedContentType;
|
||||
/// <summary>
|
||||
/// Occurs after Delete
|
||||
/// </summary>
|
||||
public static event TypedEventHandler<IContentTypeService, DeleteEventArgs<IContentType>> DeletedContentType;
|
||||
|
||||
/// <summary>
|
||||
/// Occurs before Delete
|
||||
/// </summary>
|
||||
public static event TypedEventHandler<IContentTypeService, DeleteEventArgs<IMediaType>> DeletingMediaType;
|
||||
/// <summary>
|
||||
/// Occurs before Delete
|
||||
/// </summary>
|
||||
public static event TypedEventHandler<IContentTypeService, DeleteEventArgs<IMediaType>> DeletingMediaType;
|
||||
|
||||
/// <summary>
|
||||
/// Occurs after Delete
|
||||
/// </summary>
|
||||
public static event TypedEventHandler<IContentTypeService, DeleteEventArgs<IMediaType>> DeletedMediaType;
|
||||
/// <summary>
|
||||
/// Occurs after Delete
|
||||
/// </summary>
|
||||
public static event TypedEventHandler<IContentTypeService, DeleteEventArgs<IMediaType>> DeletedMediaType;
|
||||
|
||||
/// <summary>
|
||||
/// Occurs before Save
|
||||
/// </summary>
|
||||
public static event TypedEventHandler<IContentTypeService, SaveEventArgs<IContentType>> SavingContentType;
|
||||
public static event TypedEventHandler<IContentTypeService, SaveEventArgs<IContentType>> SavingContentType;
|
||||
|
||||
/// <summary>
|
||||
/// Occurs after Save
|
||||
/// </summary>
|
||||
public static event TypedEventHandler<IContentTypeService, SaveEventArgs<IContentType>> SavedContentType;
|
||||
public static event TypedEventHandler<IContentTypeService, SaveEventArgs<IContentType>> SavedContentType;
|
||||
|
||||
/// <summary>
|
||||
/// Occurs before Save
|
||||
/// </summary>
|
||||
public static event TypedEventHandler<IContentTypeService, SaveEventArgs<IMediaType>> SavingMediaType;
|
||||
/// <summary>
|
||||
/// Occurs before Save
|
||||
/// </summary>
|
||||
public static event TypedEventHandler<IContentTypeService, SaveEventArgs<IMediaType>> SavingMediaType;
|
||||
|
||||
/// <summary>
|
||||
/// Occurs after Save
|
||||
/// </summary>
|
||||
public static event TypedEventHandler<IContentTypeService, SaveEventArgs<IMediaType>> SavedMediaType;
|
||||
/// <summary>
|
||||
/// Occurs after Save
|
||||
/// </summary>
|
||||
public static event TypedEventHandler<IContentTypeService, SaveEventArgs<IMediaType>> SavedMediaType;
|
||||
|
||||
/// <summary>
|
||||
/// Occurs before Move
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Umbraco.Core.Cache;
|
||||
using Umbraco.Core.CodeAnnotations;
|
||||
using Umbraco.Core.Events;
|
||||
@@ -81,28 +80,16 @@ namespace Umbraco.Core.Services
|
||||
{
|
||||
using (var uow = UowProvider.GetUnitOfWork(readOnly:true))
|
||||
{
|
||||
switch (umbracoObjectType)
|
||||
{
|
||||
case UmbracoObjectTypes.Document:
|
||||
case UmbracoObjectTypes.MemberType:
|
||||
case UmbracoObjectTypes.Media:
|
||||
case UmbracoObjectTypes.Template:
|
||||
case UmbracoObjectTypes.MediaType:
|
||||
case UmbracoObjectTypes.DocumentType:
|
||||
case UmbracoObjectTypes.Member:
|
||||
case UmbracoObjectTypes.DataType:
|
||||
case UmbracoObjectTypes.DocumentTypeContainer:
|
||||
return uow.Database.ExecuteScalar<int?>(new Sql().Select("id").From<NodeDto>().Where<NodeDto>(dto => dto.UniqueId == key));
|
||||
case UmbracoObjectTypes.RecycleBin:
|
||||
case UmbracoObjectTypes.Stylesheet:
|
||||
case UmbracoObjectTypes.MemberGroup:
|
||||
case UmbracoObjectTypes.ContentItem:
|
||||
case UmbracoObjectTypes.ContentItemType:
|
||||
case UmbracoObjectTypes.ROOT:
|
||||
case UmbracoObjectTypes.Unknown:
|
||||
default:
|
||||
throw new NotSupportedException();
|
||||
}
|
||||
var nodeObjectType = GetNodeObjectTypeGuid(umbracoObjectType);
|
||||
|
||||
var sql = new Sql()
|
||||
.Select("id")
|
||||
.From<NodeDto>()
|
||||
.Where<NodeDto>(
|
||||
dto =>
|
||||
dto.UniqueId == key &&
|
||||
dto.NodeObjectType == nodeObjectType);
|
||||
return uow.Database.ExecuteScalar<int?>(sql);
|
||||
}
|
||||
});
|
||||
return result.HasValue ? Attempt.Succeed(result.Value) : Attempt<int>.Fail();
|
||||
@@ -120,32 +107,54 @@ namespace Umbraco.Core.Services
|
||||
{
|
||||
using (var uow = UowProvider.GetUnitOfWork(readOnly:true))
|
||||
{
|
||||
switch (umbracoObjectType)
|
||||
{
|
||||
case UmbracoObjectTypes.Document:
|
||||
case UmbracoObjectTypes.MemberType:
|
||||
case UmbracoObjectTypes.Media:
|
||||
case UmbracoObjectTypes.Template:
|
||||
case UmbracoObjectTypes.MediaType:
|
||||
case UmbracoObjectTypes.DocumentType:
|
||||
case UmbracoObjectTypes.Member:
|
||||
case UmbracoObjectTypes.DataType:
|
||||
return uow.Database.ExecuteScalar<Guid?>(new Sql().Select("uniqueID").From<NodeDto>().Where<NodeDto>(dto => dto.NodeId == id));
|
||||
case UmbracoObjectTypes.RecycleBin:
|
||||
case UmbracoObjectTypes.Stylesheet:
|
||||
case UmbracoObjectTypes.MemberGroup:
|
||||
case UmbracoObjectTypes.ContentItem:
|
||||
case UmbracoObjectTypes.ContentItemType:
|
||||
case UmbracoObjectTypes.ROOT:
|
||||
case UmbracoObjectTypes.Unknown:
|
||||
default:
|
||||
throw new NotSupportedException("Unsupported object type (" + umbracoObjectType + ").");
|
||||
}
|
||||
var nodeObjectType = GetNodeObjectTypeGuid(umbracoObjectType);
|
||||
|
||||
var sql = new Sql()
|
||||
.Select("uniqueID")
|
||||
.From<NodeDto>()
|
||||
.Where<NodeDto>(
|
||||
dto =>
|
||||
dto.NodeId == id &&
|
||||
dto.NodeObjectType == nodeObjectType);
|
||||
return uow.Database.ExecuteScalar<Guid?>(sql);
|
||||
}
|
||||
});
|
||||
return result.HasValue ? Attempt.Succeed(result.Value) : Attempt<Guid>.Fail();
|
||||
}
|
||||
|
||||
private static Guid GetNodeObjectTypeGuid(UmbracoObjectTypes umbracoObjectType)
|
||||
{
|
||||
switch (umbracoObjectType)
|
||||
{
|
||||
case UmbracoObjectTypes.Document:
|
||||
return Constants.ObjectTypes.DocumentGuid;
|
||||
case UmbracoObjectTypes.MemberType:
|
||||
return Constants.ObjectTypes.MemberTypeGuid;
|
||||
case UmbracoObjectTypes.Media:
|
||||
return Constants.ObjectTypes.MediaGuid;
|
||||
case UmbracoObjectTypes.Template:
|
||||
return Constants.ObjectTypes.TemplateTypeGuid;
|
||||
case UmbracoObjectTypes.MediaType:
|
||||
return Constants.ObjectTypes.MediaTypeGuid;
|
||||
case UmbracoObjectTypes.DocumentType:
|
||||
return Constants.ObjectTypes.DocumentTypeGuid;
|
||||
case UmbracoObjectTypes.Member:
|
||||
return Constants.ObjectTypes.MemberGuid;
|
||||
case UmbracoObjectTypes.DataType:
|
||||
return Constants.ObjectTypes.DataTypeGuid;
|
||||
case UmbracoObjectTypes.MemberGroup:
|
||||
return Constants.ObjectTypes.MemberGroupGuid;
|
||||
case UmbracoObjectTypes.RecycleBin:
|
||||
case UmbracoObjectTypes.Stylesheet:
|
||||
case UmbracoObjectTypes.ContentItem:
|
||||
case UmbracoObjectTypes.ContentItemType:
|
||||
case UmbracoObjectTypes.ROOT:
|
||||
case UmbracoObjectTypes.Unknown:
|
||||
default:
|
||||
throw new NotSupportedException("Unsupported object type (" + umbracoObjectType + ").");
|
||||
}
|
||||
}
|
||||
|
||||
public IUmbracoEntity GetByKey(Guid key, bool loadBaseType = true)
|
||||
{
|
||||
if (loadBaseType)
|
||||
|
||||
@@ -468,12 +468,7 @@ namespace Umbraco.Core.Services
|
||||
/// <param name="filepath">The filesystem path to the media.</param>
|
||||
void DeleteMediaFile(string filepath);
|
||||
|
||||
/// <summary>
|
||||
/// Generates thumbnails.
|
||||
/// </summary>
|
||||
/// <param name="filepath">The filesystem-relative path to the original image.</param>
|
||||
/// <param name="propertyType">The property type.</param>
|
||||
/// <remarks>This should be obsoleted, we should not generate thumbnails.</remarks>
|
||||
[Obsolete("This should no longer be used, thumbnail generation should be done via ImageProcessor, Umbraco no longer generates '_thumb' files for media")]
|
||||
void GenerateThumbnails(string filepath, PropertyType propertyType);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1431,6 +1431,7 @@ namespace Umbraco.Core.Services
|
||||
_mediaFileSystem.DeleteFile(filepath, true);
|
||||
}
|
||||
|
||||
[Obsolete("This should no longer be used, thumbnail generation should be done via ImageProcessor, Umbraco no longer generates '_thumb' files for media")]
|
||||
public void GenerateThumbnails(string filepath, PropertyType propertyType)
|
||||
{
|
||||
using (var filestream = _mediaFileSystem.OpenFile(filepath))
|
||||
|
||||
@@ -93,6 +93,8 @@ namespace Umbraco.Core.Services
|
||||
|
||||
var repository = RepositoryFactory.CreateMemberTypeRepository(uow);
|
||||
memberType.CreatorId = userId;
|
||||
if (memberType.Description == string.Empty)
|
||||
memberType.Description = null;
|
||||
repository.AddOrUpdate(memberType);
|
||||
uow.Commit(); // flush, so that the db contains the saved value
|
||||
|
||||
@@ -121,6 +123,8 @@ namespace Umbraco.Core.Services
|
||||
foreach (var memberType in asArray)
|
||||
{
|
||||
memberType.CreatorId = userId;
|
||||
if (memberType.Description == string.Empty)
|
||||
memberType.Description = null;
|
||||
repository.AddOrUpdate(memberType);
|
||||
}
|
||||
uow.Commit(); // flush, so that the db contains the saved values
|
||||
|
||||
+118
-225
@@ -1,32 +1,24 @@
|
||||
using System;
|
||||
using System.Collections.Concurrent;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Linq.Expressions;
|
||||
using System.Reflection;
|
||||
using System.Security;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
using System.Web;
|
||||
using System.Web.Compilation;
|
||||
using System.Web.Hosting;
|
||||
using Umbraco.Core.Configuration;
|
||||
using Umbraco.Core.IO;
|
||||
using Umbraco.Core.Logging;
|
||||
|
||||
namespace Umbraco.Core
|
||||
{
|
||||
|
||||
/// <summary>
|
||||
/// A utility class to find all classes of a certain type by reflection in the current bin folder
|
||||
/// of the web application.
|
||||
/// </summary>
|
||||
public static class TypeFinder
|
||||
{
|
||||
private static volatile HashSet<Assembly> _localFilteredAssemblyCache = null;
|
||||
private static volatile HashSet<Assembly> _localFilteredAssemblyCache;
|
||||
private static readonly object LocalFilteredAssemblyCacheLocker = new object();
|
||||
|
||||
/// <summary>
|
||||
@@ -63,7 +55,7 @@ namespace Umbraco.Core
|
||||
}
|
||||
catch (InvalidOperationException e)
|
||||
{
|
||||
if (!(e.InnerException is SecurityException))
|
||||
if ((e.InnerException is SecurityException) == false)
|
||||
throw;
|
||||
}
|
||||
|
||||
@@ -99,7 +91,7 @@ namespace Umbraco.Core
|
||||
}
|
||||
|
||||
//if for some reason they are still no assemblies, then use the AppDomain to load in already loaded assemblies.
|
||||
if (!assemblies.Any())
|
||||
if (assemblies.Any() == false)
|
||||
{
|
||||
foreach (var a in AppDomain.CurrentDomain.GetAssemblies())
|
||||
{
|
||||
@@ -111,12 +103,12 @@ namespace Umbraco.Core
|
||||
var fileExtensions = new[] { ".cs", ".vb" }; //only vb and cs files are supported
|
||||
var appCodeFolder = new DirectoryInfo(IOHelper.MapPath(IOHelper.ResolveUrl("~/App_code")));
|
||||
//check if the folder exists and if there are any files in it with the supported file extensions
|
||||
if (appCodeFolder.Exists && (fileExtensions.Any(x => appCodeFolder.GetFiles("*" + x).Any())))
|
||||
if (appCodeFolder.Exists && fileExtensions.Any(x => appCodeFolder.GetFiles("*" + x).Any()))
|
||||
{
|
||||
try
|
||||
{
|
||||
var appCodeAssembly = Assembly.Load("App_Code");
|
||||
if (!assemblies.Contains(appCodeAssembly)) // BuildManager will find App_Code already
|
||||
if (assemblies.Contains(appCodeAssembly) == false) // BuildManager will find App_Code already
|
||||
assemblies.Add(appCodeAssembly);
|
||||
}
|
||||
catch (FileNotFoundException ex)
|
||||
@@ -128,7 +120,7 @@ namespace Umbraco.Core
|
||||
}
|
||||
catch (InvalidOperationException e)
|
||||
{
|
||||
if (!(e.InnerException is SecurityException))
|
||||
if (e.InnerException is SecurityException == false)
|
||||
throw;
|
||||
}
|
||||
|
||||
@@ -145,23 +137,15 @@ namespace Umbraco.Core
|
||||
internal static HashSet<Assembly> GetAssembliesWithKnownExclusions(
|
||||
IEnumerable<Assembly> excludeFromResults = null)
|
||||
{
|
||||
if (_localFilteredAssemblyCache == null)
|
||||
lock (LocalFilteredAssemblyCacheLocker)
|
||||
{
|
||||
lock (LocalFilteredAssemblyCacheLocker)
|
||||
{
|
||||
//double check
|
||||
if (_localFilteredAssemblyCache == null)
|
||||
{
|
||||
_localFilteredAssemblyCache = new HashSet<Assembly>();
|
||||
var assemblies = GetFilteredAssemblies(excludeFromResults, KnownAssemblyExclusionFilter);
|
||||
foreach (var a in assemblies)
|
||||
{
|
||||
_localFilteredAssemblyCache.Add(a);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (_localFilteredAssemblyCache != null)
|
||||
return _localFilteredAssemblyCache;
|
||||
|
||||
var assemblies = GetFilteredAssemblies(excludeFromResults, KnownAssemblyExclusionFilter);
|
||||
_localFilteredAssemblyCache = new HashSet<Assembly>(assemblies);
|
||||
return _localFilteredAssemblyCache;
|
||||
}
|
||||
return _localFilteredAssemblyCache;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -180,9 +164,9 @@ namespace Umbraco.Core
|
||||
exclusionFilter = new string[] { };
|
||||
|
||||
return GetAllAssemblies()
|
||||
.Where(x => !excludeFromResults.Contains(x)
|
||||
&& !x.GlobalAssemblyCache
|
||||
&& !exclusionFilter.Any(f => x.FullName.StartsWith(f)));
|
||||
.Where(x => excludeFromResults.Contains(x) == false
|
||||
&& x.GlobalAssemblyCache == false
|
||||
&& exclusionFilter.Any(f => x.FullName.StartsWith(f)) == false);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -298,7 +282,7 @@ namespace Umbraco.Core
|
||||
{
|
||||
if (assemblies == null) throw new ArgumentNullException("assemblies");
|
||||
|
||||
return GetClasses(assignTypeFrom, assemblies, onlyConcreteClasses,
|
||||
return GetClassesWithBaseType(assignTypeFrom, assemblies, onlyConcreteClasses,
|
||||
//the additional filter will ensure that any found types also have the attribute applied.
|
||||
t => t.GetCustomAttributes<TAttribute>(false).Any());
|
||||
}
|
||||
@@ -324,7 +308,7 @@ namespace Umbraco.Core
|
||||
{
|
||||
if (assemblies == null) throw new ArgumentNullException("assemblies");
|
||||
|
||||
return GetClasses(typeof(T), assemblies, onlyConcreteClasses);
|
||||
return GetClassesWithBaseType(typeof(T), assemblies, onlyConcreteClasses);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -363,105 +347,9 @@ namespace Umbraco.Core
|
||||
IEnumerable<Assembly> assemblies,
|
||||
bool onlyConcreteClasses)
|
||||
{
|
||||
if (assemblies == null) throw new ArgumentNullException("assemblies");
|
||||
|
||||
if (TypeHelper.IsTypeAssignableFrom<Attribute>(attributeType) == false)
|
||||
throw new ArgumentException("The type specified: " + attributeType + " is not an Attribute type");
|
||||
|
||||
var foundAttributedTypes = new HashSet<Type>();
|
||||
|
||||
var assemblyList = assemblies.ToArray();
|
||||
|
||||
//find all assembly references that are referencing the attribute type's assembly since we
|
||||
//should only be scanning those assemblies because any other assembly will definitely not
|
||||
//contain a class that has this attribute.
|
||||
var referencedAssemblies = TypeHelper.GetReferencedAssemblies(attributeType, assemblyList);
|
||||
|
||||
//get a list of non-referenced assemblies (we'll use this when we recurse below)
|
||||
var otherAssemblies = assemblyList.Where(x => referencedAssemblies.Contains(x) == false).ToArray();
|
||||
|
||||
//loop through the referenced assemblies
|
||||
foreach (var a in referencedAssemblies)
|
||||
{
|
||||
//get all types in this assembly
|
||||
var allTypes = GetTypesWithFormattedException(a)
|
||||
.ToArray();
|
||||
|
||||
var attributedTypes = new Type[] { };
|
||||
try
|
||||
{
|
||||
//now filter the types based on the onlyConcreteClasses flag, not interfaces, not static classes but have
|
||||
//the specified attribute
|
||||
attributedTypes = allTypes
|
||||
.Where(t => (TypeHelper.IsNonStaticClass(t)
|
||||
&& (onlyConcreteClasses == false || t.IsAbstract == false))
|
||||
//the type must have this attribute
|
||||
&& t.GetCustomAttributes(attributeType, false).Any())
|
||||
.ToArray();
|
||||
}
|
||||
catch (TypeLoadException ex)
|
||||
{
|
||||
LogHelper.Error(typeof(TypeFinder), string.Format("Could not query types on {0} assembly, this is most likely due to this assembly not being compatible with the current Umbraco version", a), ex);
|
||||
continue;
|
||||
}
|
||||
|
||||
//add the types to our list to return
|
||||
foreach (var t in attributedTypes)
|
||||
{
|
||||
foundAttributedTypes.Add(t);
|
||||
}
|
||||
|
||||
//get all attributes of the type being searched for
|
||||
var allAttributeTypes = allTypes.Where(attributeType.IsAssignableFrom);
|
||||
|
||||
//now we need to include types that may be inheriting from sub classes of the attribute type being searched for
|
||||
//so we will search in assemblies that reference those types too.
|
||||
foreach (var subTypesInAssembly in allAttributeTypes.GroupBy(x => x.Assembly))
|
||||
{
|
||||
|
||||
//So that we are not scanning too much, we need to group the sub types:
|
||||
// * if there is more than 1 sub type in the same assembly then we should only search on the 'lowest base' type.
|
||||
// * We should also not search for sub types if the type is sealed since you cannot inherit from a sealed class
|
||||
// * We should not search for sub types if the type is static since you cannot inherit from them.
|
||||
var subTypeList = subTypesInAssembly
|
||||
.Where(t => t.IsSealed == false && TypeHelper.IsStaticClass(t) == false)
|
||||
.ToArray();
|
||||
|
||||
var baseClassAttempt = TypeHelper.GetLowestBaseType(subTypeList);
|
||||
|
||||
//if there's a base class amongst the types then we'll only search for that type.
|
||||
//otherwise we'll have to search for all of them.
|
||||
var subTypesToSearch = new HashSet<Type>();
|
||||
if (baseClassAttempt.Success)
|
||||
{
|
||||
subTypesToSearch.Add(baseClassAttempt.Result);
|
||||
}
|
||||
else
|
||||
{
|
||||
foreach (var t in subTypeList)
|
||||
{
|
||||
subTypesToSearch.Add(t);
|
||||
}
|
||||
}
|
||||
|
||||
foreach (var typeToSearch in subTypesToSearch)
|
||||
{
|
||||
//recursively find the types inheriting from this sub type in the other non-scanned assemblies.
|
||||
var foundTypes = FindClassesWithAttribute(typeToSearch, otherAssemblies, onlyConcreteClasses);
|
||||
|
||||
foreach (var f in foundTypes)
|
||||
{
|
||||
foundAttributedTypes.Add(f);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
return foundAttributedTypes;
|
||||
return GetClassesWithAttribute(attributeType, assemblies, onlyConcreteClasses);
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Finds the classes with attribute.
|
||||
/// </summary>
|
||||
@@ -485,122 +373,129 @@ namespace Umbraco.Core
|
||||
return FindClassesWithAttribute<T>(GetAssembliesWithKnownExclusions());
|
||||
}
|
||||
|
||||
|
||||
#region Private methods
|
||||
|
||||
private static IEnumerable<Type> GetClassesWithAttribute(
|
||||
Type attributeType,
|
||||
IEnumerable<Assembly> assemblies,
|
||||
bool onlyConcreteClasses)
|
||||
{
|
||||
if (typeof(Attribute).IsAssignableFrom(attributeType) == false)
|
||||
throw new ArgumentException("Type " + attributeType + " is not an Attribute type.");
|
||||
|
||||
var candidateAssemblies = new HashSet<Assembly>(assemblies);
|
||||
var attributeAssemblyIsCandidate = candidateAssemblies.Contains(attributeType.Assembly);
|
||||
candidateAssemblies.Remove(attributeType.Assembly);
|
||||
var types = new List<Type>();
|
||||
|
||||
var stack = new Stack<Assembly>();
|
||||
stack.Push(attributeType.Assembly);
|
||||
|
||||
while (stack.Count > 0)
|
||||
{
|
||||
var assembly = stack.Pop();
|
||||
|
||||
Type[] assemblyTypes = null;
|
||||
if (assembly != attributeType.Assembly || attributeAssemblyIsCandidate)
|
||||
{
|
||||
// get all assembly types that can be assigned to baseType
|
||||
try
|
||||
{
|
||||
assemblyTypes = GetTypesWithFormattedException(assembly)
|
||||
.ToArray(); // in try block
|
||||
}
|
||||
catch (TypeLoadException ex)
|
||||
{
|
||||
LogHelper.Error(typeof(TypeFinder), string.Format("Could not query types on {0} assembly, this is most likely due to this assembly not being compatible with the current Umbraco version", assembly), ex);
|
||||
continue;
|
||||
}
|
||||
|
||||
types.AddRange(assemblyTypes.Where(x =>
|
||||
x.IsClass // only classes
|
||||
&& (x.IsAbstract == false || x.IsSealed == false) // ie non-static, static is abstract and sealed
|
||||
&& x.IsNestedPrivate == false // exclude nested private
|
||||
&& (onlyConcreteClasses == false || x.IsAbstract == false) // exclude abstract
|
||||
&& x.GetCustomAttribute<HideFromTypeFinderAttribute>() == null // exclude hidden
|
||||
&& x.GetCustomAttributes(attributeType, false).Any())); // marked with the attribute
|
||||
}
|
||||
|
||||
if (assembly != attributeType.Assembly && assemblyTypes.Where(attributeType.IsAssignableFrom).Any() == false)
|
||||
continue;
|
||||
|
||||
foreach (var referencing in TypeHelper.GetReferencingAssemblies(assembly, candidateAssemblies))
|
||||
{
|
||||
candidateAssemblies.Remove(referencing);
|
||||
stack.Push(referencing);
|
||||
}
|
||||
}
|
||||
|
||||
return types;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Finds types that are assignable from the assignTypeFrom parameter and will scan for these types in the assembly
|
||||
/// list passed in, however we will only scan assemblies that have a reference to the assignTypeFrom Type or any type
|
||||
/// deriving from the base type.
|
||||
/// </summary>
|
||||
/// <param name="assignTypeFrom"></param>
|
||||
/// <param name="baseType"></param>
|
||||
/// <param name="assemblies"></param>
|
||||
/// <param name="onlyConcreteClasses"></param>
|
||||
/// <param name="additionalFilter">An additional filter to apply for what types will actually be included in the return value</param>
|
||||
/// <returns></returns>
|
||||
private static IEnumerable<Type> GetClasses(
|
||||
Type assignTypeFrom,
|
||||
private static IEnumerable<Type> GetClassesWithBaseType(
|
||||
Type baseType,
|
||||
IEnumerable<Assembly> assemblies,
|
||||
bool onlyConcreteClasses,
|
||||
Func<Type, bool> additionalFilter = null)
|
||||
{
|
||||
//the default filter will always return true.
|
||||
if (additionalFilter == null)
|
||||
var candidateAssemblies = new HashSet<Assembly>(assemblies);
|
||||
var baseTypeAssemblyIsCandidate = candidateAssemblies.Contains(baseType.Assembly);
|
||||
candidateAssemblies.Remove(baseType.Assembly);
|
||||
var types = new List<Type>();
|
||||
|
||||
var stack = new Stack<Assembly>();
|
||||
stack.Push(baseType.Assembly);
|
||||
|
||||
while (stack.Count > 0)
|
||||
{
|
||||
additionalFilter = type => true;
|
||||
}
|
||||
var assembly = stack.Pop();
|
||||
|
||||
var foundAssignableTypes = new HashSet<Type>();
|
||||
|
||||
var assemblyList = assemblies.ToArray();
|
||||
|
||||
//find all assembly references that are referencing the current type's assembly since we
|
||||
//should only be scanning those assemblies because any other assembly will definitely not
|
||||
//contain sub type's of the one we're currently looking for
|
||||
var referencedAssemblies = TypeHelper.GetReferencedAssemblies(assignTypeFrom, assemblyList);
|
||||
|
||||
//get a list of non-referenced assemblies (we'll use this when we recurse below)
|
||||
var otherAssemblies = assemblyList.Where(x => referencedAssemblies.Contains(x) == false).ToArray();
|
||||
|
||||
//loop through the referenced assemblies
|
||||
foreach (var a in referencedAssemblies)
|
||||
{
|
||||
//get all types in the assembly that are sub types of the current type
|
||||
var allSubTypes = GetTypesWithFormattedException(a)
|
||||
.Where(assignTypeFrom.IsAssignableFrom)
|
||||
.ToArray();
|
||||
|
||||
var filteredTypes = new Type[] { };
|
||||
try
|
||||
// get all assembly types that can be assigned to baseType
|
||||
Type[] assemblyTypes = null;
|
||||
if (assembly != baseType.Assembly || baseTypeAssemblyIsCandidate)
|
||||
{
|
||||
//now filter the types based on the onlyConcreteClasses flag, not interfaces, not static classes
|
||||
filteredTypes = allSubTypes
|
||||
.Where(t => (TypeHelper.IsNonStaticClass(t)
|
||||
//Do not include nested private classes - since we are in full trust now this will find those too!
|
||||
&& t.IsNestedPrivate == false
|
||||
&& (onlyConcreteClasses == false || t.IsAbstract == false)
|
||||
//Do not include classes that are flagged to hide from the type finder
|
||||
&& t.GetCustomAttribute<HideFromTypeFinderAttribute>() == null
|
||||
&& additionalFilter(t)))
|
||||
.ToArray();
|
||||
try
|
||||
{
|
||||
assemblyTypes = GetTypesWithFormattedException(assembly)
|
||||
.Where(baseType.IsAssignableFrom)
|
||||
.ToArray(); // in try block
|
||||
}
|
||||
catch (TypeLoadException ex)
|
||||
{
|
||||
LogHelper.Error(typeof(TypeFinder), string.Format("Could not query types on {0} assembly, this is most likely due to this assembly not being compatible with the current Umbraco version", assembly), ex);
|
||||
continue;
|
||||
}
|
||||
|
||||
types.AddRange(assemblyTypes.Where(x =>
|
||||
x.IsClass // only classes
|
||||
&& (x.IsAbstract == false || x.IsSealed == false) // ie non-static, static is abstract and sealed
|
||||
&& x.IsNestedPrivate == false // exclude nested private
|
||||
&& (onlyConcreteClasses == false || x.IsAbstract == false) // exclude abstract
|
||||
&& x.GetCustomAttribute<HideFromTypeFinderAttribute>() == null // exclude hidden
|
||||
&& (additionalFilter == null || additionalFilter(x)))); // filter
|
||||
}
|
||||
catch (TypeLoadException ex)
|
||||
{
|
||||
LogHelper.Error(typeof(TypeFinder), string.Format("Could not query types on {0} assembly, this is most likely due to this assembly not being compatible with the current Umbraco version", a), ex);
|
||||
|
||||
if (assembly != baseType.Assembly && assemblyTypes.All(x => x.IsSealed))
|
||||
continue;
|
||||
}
|
||||
|
||||
//add the types to our list to return
|
||||
foreach (var t in filteredTypes)
|
||||
foreach (var referencing in TypeHelper.GetReferencingAssemblies(assembly, candidateAssemblies))
|
||||
{
|
||||
foundAssignableTypes.Add(t);
|
||||
candidateAssemblies.Remove(referencing);
|
||||
stack.Push(referencing);
|
||||
}
|
||||
|
||||
//now we need to include types that may be inheriting from sub classes of the type being searched for
|
||||
//so we will search in assemblies that reference those types too.
|
||||
foreach (var subTypesInAssembly in allSubTypes.GroupBy(x => x.Assembly))
|
||||
{
|
||||
|
||||
//So that we are not scanning too much, we need to group the sub types:
|
||||
// * if there is more than 1 sub type in the same assembly then we should only search on the 'lowest base' type.
|
||||
// * We should also not search for sub types if the type is sealed since you cannot inherit from a sealed class
|
||||
// * We should not search for sub types if the type is static since you cannot inherit from them.
|
||||
var subTypeList = subTypesInAssembly
|
||||
.Where(t => t.IsSealed == false && TypeHelper.IsStaticClass(t) == false)
|
||||
.ToArray();
|
||||
|
||||
var baseClassAttempt = TypeHelper.GetLowestBaseType(subTypeList);
|
||||
|
||||
//if there's a base class amongst the types then we'll only search for that type.
|
||||
//otherwise we'll have to search for all of them.
|
||||
var subTypesToSearch = new HashSet<Type>();
|
||||
if (baseClassAttempt.Success)
|
||||
{
|
||||
subTypesToSearch.Add(baseClassAttempt.Result);
|
||||
}
|
||||
else
|
||||
{
|
||||
foreach (var t in subTypeList)
|
||||
{
|
||||
subTypesToSearch.Add(t);
|
||||
}
|
||||
}
|
||||
|
||||
foreach (var typeToSearch in subTypesToSearch)
|
||||
{
|
||||
//recursively find the types inheriting from this sub type in the other non-scanned assemblies.
|
||||
var foundTypes = GetClasses(typeToSearch, otherAssemblies, onlyConcreteClasses, additionalFilter);
|
||||
|
||||
foreach (var f in foundTypes)
|
||||
{
|
||||
foundAssignableTypes.Add(f);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
return foundAssignableTypes;
|
||||
|
||||
return types;
|
||||
}
|
||||
|
||||
internal static IEnumerable<Type> GetTypesWithFormattedException(Assembly a)
|
||||
@@ -666,7 +561,6 @@ namespace Umbraco.Core
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
public static Type GetTypeByName(string typeName)
|
||||
{
|
||||
var type = BuildManager.GetType(typeName, false);
|
||||
@@ -684,6 +578,5 @@ namespace Umbraco.Core
|
||||
.Select(x => x.GetType(typeName))
|
||||
.FirstOrDefault(x => x != null);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,9 +13,12 @@ namespace Umbraco.Core
|
||||
/// </summary>
|
||||
internal static class TypeHelper
|
||||
{
|
||||
|
||||
private static readonly ConcurrentDictionary<Type, FieldInfo[]> GetFieldsCache = new ConcurrentDictionary<Type, FieldInfo[]>();
|
||||
private static readonly ConcurrentDictionary<Tuple<Type, bool, bool, bool>, PropertyInfo[]> GetPropertiesCache = new ConcurrentDictionary<Tuple<Type, bool, bool, bool>, PropertyInfo[]>();
|
||||
private static readonly ConcurrentDictionary<Tuple<Type, bool, bool, bool>, PropertyInfo[]> GetPropertiesCache
|
||||
= new ConcurrentDictionary<Tuple<Type, bool, bool, bool>, PropertyInfo[]>();
|
||||
private static readonly ConcurrentDictionary<Type, FieldInfo[]> GetFieldsCache
|
||||
= new ConcurrentDictionary<Type, FieldInfo[]>();
|
||||
|
||||
private static readonly Assembly[] EmptyAssemblies = new Assembly[0];
|
||||
|
||||
/// <summary>
|
||||
/// Checks if the method is actually overriding a base method
|
||||
@@ -30,44 +33,40 @@ namespace Umbraco.Core
|
||||
/// <summary>
|
||||
/// Find all assembly references that are referencing the assignTypeFrom Type's assembly found in the assemblyList
|
||||
/// </summary>
|
||||
/// <param name="assignTypeFrom"></param>
|
||||
/// <param name="assemblies"></param>
|
||||
/// <param name="assembly">The referenced assembly.</param>
|
||||
/// <param name="assemblies">A list of assemblies.</param>
|
||||
/// <returns></returns>
|
||||
/// <remarks>
|
||||
/// If the assembly of the assignTypeFrom Type is in the App_Code assembly, then we return nothing since things cannot
|
||||
/// reference that assembly, same with the global.asax assembly.
|
||||
/// </remarks>
|
||||
public static Assembly[] GetReferencedAssemblies(Type assignTypeFrom, IEnumerable<Assembly> assemblies)
|
||||
public static Assembly[] GetReferencingAssemblies(Assembly assembly, IEnumerable<Assembly> assemblies)
|
||||
{
|
||||
//check if it is the app_code assembly.
|
||||
//check if it is App_global.asax assembly
|
||||
if (assignTypeFrom.Assembly.IsAppCodeAssembly() || assignTypeFrom.Assembly.IsGlobalAsaxAssembly())
|
||||
{
|
||||
return Enumerable.Empty<Assembly>().ToArray();
|
||||
}
|
||||
if (assembly.IsAppCodeAssembly() || assembly.IsGlobalAsaxAssembly())
|
||||
return EmptyAssemblies;
|
||||
|
||||
|
||||
//find all assembly references that are referencing the current type's assembly since we
|
||||
//should only be scanning those assemblies because any other assembly will definitely not
|
||||
//contain sub type's of the one we're currently looking for
|
||||
return assemblies
|
||||
.Where(assembly =>
|
||||
assembly == assignTypeFrom.Assembly
|
||||
|| HasReferenceToAssemblyWithName(assembly, assignTypeFrom.Assembly.GetName().Name))
|
||||
.ToArray();
|
||||
// find all assembly references that are referencing the current type's assembly since we
|
||||
// should only be scanning those assemblies because any other assembly will definitely not
|
||||
// contain sub type's of the one we're currently looking for
|
||||
var name = assembly.GetName().Name;
|
||||
return assemblies.Where(x => x == assembly || HasReference(x, name)).ToArray();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// checks if the assembly has a reference with the same name as the expected assembly name.
|
||||
/// Determines if an assembly references another assembly.
|
||||
/// </summary>
|
||||
/// <param name="assembly"></param>
|
||||
/// <param name="expectedAssemblyName"></param>
|
||||
/// <param name="name"></param>
|
||||
/// <returns></returns>
|
||||
private static bool HasReferenceToAssemblyWithName(Assembly assembly, string expectedAssemblyName)
|
||||
{
|
||||
return assembly
|
||||
.GetReferencedAssemblies()
|
||||
.Select(a => a.Name)
|
||||
.Contains(expectedAssemblyName, StringComparer.Ordinal);
|
||||
public static bool HasReference(Assembly assembly, string name)
|
||||
{
|
||||
// ReSharper disable once LoopCanBeConvertedToQuery - no!
|
||||
foreach (var a in assembly.GetReferencedAssemblies())
|
||||
{
|
||||
if (string.Equals(a.Name, name, StringComparison.Ordinal)) return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -106,13 +105,10 @@ namespace Umbraco.Core
|
||||
public static Attempt<Type> GetLowestBaseType(params Type[] types)
|
||||
{
|
||||
if (types.Length == 0)
|
||||
{
|
||||
return Attempt<Type>.Fail();
|
||||
}
|
||||
if (types.Length == 1)
|
||||
{
|
||||
|
||||
if (types.Length == 1)
|
||||
return Attempt.Succeed(types[0]);
|
||||
}
|
||||
|
||||
foreach (var curr in types)
|
||||
{
|
||||
@@ -196,20 +192,15 @@ namespace Umbraco.Core
|
||||
/// <param name="includeIndexed"></param>
|
||||
/// <param name="caseSensitive"> </param>
|
||||
/// <returns></returns>
|
||||
public static PropertyInfo GetProperty(Type type, string name,
|
||||
bool mustRead = true,
|
||||
bool mustWrite = true,
|
||||
public static PropertyInfo GetProperty(Type type, string name,
|
||||
bool mustRead = true,
|
||||
bool mustWrite = true,
|
||||
bool includeIndexed = false,
|
||||
bool caseSensitive = true)
|
||||
{
|
||||
return CachedDiscoverableProperties(type, mustRead, mustWrite, includeIndexed)
|
||||
.FirstOrDefault(x =>
|
||||
{
|
||||
if (caseSensitive)
|
||||
return x.Name == name;
|
||||
return x.Name.InvariantEquals(name);
|
||||
});
|
||||
}
|
||||
return CachedDiscoverableProperties(type, mustRead, mustWrite, includeIndexed)
|
||||
.FirstOrDefault(x => caseSensitive ? (x.Name == name) : x.Name.InvariantEquals(name));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets (and caches) <see cref="FieldInfo"/> discoverable in the current <see cref="AppDomain"/> for a given <paramref name="type"/>.
|
||||
@@ -222,7 +213,7 @@ namespace Umbraco.Core
|
||||
type,
|
||||
x => type
|
||||
.GetFields(BindingFlags.Public | BindingFlags.Instance)
|
||||
.Where(y => !y.IsInitOnly)
|
||||
.Where(y => y.IsInitOnly == false)
|
||||
.ToArray());
|
||||
}
|
||||
|
||||
@@ -240,13 +231,12 @@ namespace Umbraco.Core
|
||||
new Tuple<Type, bool, bool, bool>(type, mustRead, mustWrite, includeIndexed),
|
||||
x => type
|
||||
.GetProperties(BindingFlags.Public | BindingFlags.Instance)
|
||||
.Where(y => (!mustRead || y.CanRead)
|
||||
&& (!mustWrite || y.CanWrite)
|
||||
&& (includeIndexed || !y.GetIndexParameters().Any()))
|
||||
.Where(y => (mustRead == false || y.CanRead)
|
||||
&& (mustWrite == false || y.CanWrite)
|
||||
&& (includeIndexed || y.GetIndexParameters().Any() == false))
|
||||
.ToArray());
|
||||
}
|
||||
|
||||
|
||||
#region Match Type
|
||||
|
||||
//TODO: Need to determine if these methods should replace/combine/merge etc with IsTypeAssignableFrom, IsAssignableFromGeneric
|
||||
@@ -337,9 +327,9 @@ namespace Umbraco.Core
|
||||
|
||||
// not a generic type, not a generic parameter
|
||||
// so normal class or interface
|
||||
// fixme structs? enums? array types?
|
||||
// about primitive types, value types, etc:
|
||||
// http://stackoverflow.com/questions/1827425/how-to-check-programatically-if-a-type-is-a-struct-or-a-class
|
||||
// if it's a primitive type... it needs to be ==
|
||||
|
||||
if (implementation == contract) return true;
|
||||
if (contract.IsClass && implementation.IsClass && implementation.IsSubclassOf(contract)) return true;
|
||||
|
||||
@@ -53,13 +53,14 @@
|
||||
<HintPath>..\packages\SharpZipLib.0.86.0\lib\20\ICSharpCode.SharpZipLib.dll</HintPath>
|
||||
<Private>True</Private>
|
||||
</Reference>
|
||||
<Reference Include="ImageProcessor, Version=2.5.2.0, Culture=neutral, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\ImageProcessor.2.5.2\lib\net45\ImageProcessor.dll</HintPath>
|
||||
<Private>True</Private>
|
||||
<Reference Include="ImageProcessor, Version=2.5.3.0, Culture=neutral, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\ImageProcessor.2.5.3\lib\net45\ImageProcessor.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="log4net, Version=1.2.15.0, Culture=neutral, PublicKeyToken=669e0ddf0bb1aa2a, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\log4net.2.0.5\lib\net45-full\log4net.dll</HintPath>
|
||||
<Private>True</Private>
|
||||
<Reference Include="log4net, Version=2.0.8.0, Culture=neutral, PublicKeyToken=669e0ddf0bb1aa2a, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\log4net.2.0.8\lib\net45-full\log4net.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Log4Net.Async, Version=2.0.4.0, Culture=neutral, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\Log4Net.Async.2.0.4\lib\net40\Log4Net.Async.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Microsoft.AspNet.Identity.Core, Version=2.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\Microsoft.AspNet.Identity.Core.2.2.1\lib\net45\Microsoft.AspNet.Identity.Core.dll</HintPath>
|
||||
@@ -89,13 +90,11 @@
|
||||
<HintPath>..\packages\MiniProfiler.2.1.0\lib\net40\MiniProfiler.dll</HintPath>
|
||||
<Private>True</Private>
|
||||
</Reference>
|
||||
<Reference Include="MySql.Data, Version=6.9.8.0, Culture=neutral, PublicKeyToken=c5687fc88969c44d, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\MySql.Data.6.9.8\lib\net45\MySql.Data.dll</HintPath>
|
||||
<Private>True</Private>
|
||||
<Reference Include="MySql.Data, Version=6.9.9.0, Culture=neutral, PublicKeyToken=c5687fc88969c44d, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\MySql.Data.6.9.9\lib\net45\MySql.Data.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Newtonsoft.Json, Version=9.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\Newtonsoft.Json.9.0.1\lib\net45\Newtonsoft.Json.dll</HintPath>
|
||||
<Private>True</Private>
|
||||
<Reference Include="Newtonsoft.Json, Version=10.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\Newtonsoft.Json.10.0.2\lib\net45\Newtonsoft.Json.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Owin, Version=1.0.0.0, Culture=neutral, PublicKeyToken=f0ebd12fd5e55cc5, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\Owin.1.0\lib\net40\Owin.dll</HintPath>
|
||||
@@ -496,8 +495,8 @@
|
||||
<Compile Include="Persistence\Mappers\MigrationEntryMapper.cs" />
|
||||
<Compile Include="Persistence\Migrations\LocalMigrationContext.cs" />
|
||||
<Compile Include="Persistence\Migrations\Upgrades\TargetVersionFourOneZero\AddPreviewXmlTable.cs" />
|
||||
<Compile Include="Persistence\Migrations\Upgrades\TargetVersionSevenFiveFive\AddLockObjects.cs" />
|
||||
<Compile Include="Persistence\Migrations\Upgrades\TargetVersionSevenFiveFive\AddLockTable.cs" />
|
||||
<Compile Include="Persistence\Migrations\Upgrades\TargetVersionSevenSixZero\AddLockObjects.cs" />
|
||||
<Compile Include="Persistence\Migrations\Upgrades\TargetVersionSevenSixZero\AddLockTable.cs" />
|
||||
<Compile Include="Persistence\Migrations\Upgrades\TargetVersionSevenFiveFive\UpdateAllowedMediaTypesAtRoot.cs" />
|
||||
<Compile Include="Persistence\Migrations\Upgrades\TargetVersionSevenFiveZero\EnsureServersLockObject.cs" />
|
||||
<Compile Include="Persistence\Migrations\Upgrades\TargetVersionSevenFiveZero\AddRedirectUrlTable.cs" />
|
||||
@@ -515,6 +514,8 @@
|
||||
<Compile Include="Persistence\Migrations\Upgrades\TargetVersionSevenSixZero\AddIndexToUser2NodePermission.cs" />
|
||||
<Compile Include="Persistence\Migrations\Upgrades\TargetVersionSevenSixZero\AddRelationTypeUniqueIdColumn.cs" />
|
||||
<Compile Include="Persistence\Migrations\Upgrades\TargetVersionSevenSixZero\AddMacroUniqueIdColumn.cs" />
|
||||
<Compile Include="Persistence\Migrations\Upgrades\TargetVersionSevenSixZero\ReduceLoginNameColumnsSize.cs" />
|
||||
<Compile Include="Persistence\Migrations\Upgrades\TargetVersionSevenSixZero\NormalizeTemplateGuids.cs" />
|
||||
<Compile Include="Persistence\Migrations\Upgrades\TargetVersionSevenSixZero\RemovePropertyDataIdIndex.cs" />
|
||||
<Compile Include="Persistence\Migrations\Upgrades\TargetVersionSevenSixZero\RemoveUmbracoDeployTables.cs" />
|
||||
<Compile Include="Persistence\Migrations\Upgrades\TargetVersionSevenThreeTwo\EnsureMigrationsTableIdentityIsCorrect.cs" />
|
||||
|
||||
@@ -49,8 +49,6 @@ namespace Umbraco.Core
|
||||
LogHelper.Error<UmbracoApplicationBase>(msg, exception);
|
||||
};
|
||||
|
||||
BindingRedirects.Initialize();
|
||||
|
||||
//boot up the application
|
||||
GetBootManager()
|
||||
.Initialize()
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
|
||||
<dependentAssembly>
|
||||
<assemblyIdentity name="Newtonsoft.Json" publicKeyToken="30ad4fe6b2a6aeed" culture="neutral" />
|
||||
<bindingRedirect oldVersion="0.0.0.0-9.0.0.0" newVersion="9.0.0.0" />
|
||||
<bindingRedirect oldVersion="0.0.0.0-10.0.0.0" newVersion="10.0.0.0" />
|
||||
</dependentAssembly>
|
||||
<dependentAssembly>
|
||||
<assemblyIdentity name="System.Web.Mvc" publicKeyToken="31bf3856ad364e35" culture="neutral" />
|
||||
@@ -30,11 +30,15 @@
|
||||
<assemblyIdentity name="Microsoft.Owin.Security.Cookies" publicKeyToken="31bf3856ad364e35" culture="neutral" />
|
||||
<bindingRedirect oldVersion="0.0.0.0-3.0.1.0" newVersion="3.0.1.0" />
|
||||
</dependentAssembly>
|
||||
<dependentAssembly>
|
||||
<assemblyIdentity name="log4net" publicKeyToken="669e0ddf0bb1aa2a" culture="neutral" />
|
||||
<bindingRedirect oldVersion="0.0.0.0-2.0.8.0" newVersion="2.0.8.0" />
|
||||
</dependentAssembly>
|
||||
</assemblyBinding>
|
||||
</runtime>
|
||||
<startup><supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5" /></startup><system.data>
|
||||
<DbProviderFactories>
|
||||
<remove invariant="MySql.Data.MySqlClient" />
|
||||
<add name="MySQL Data Provider" invariant="MySql.Data.MySqlClient" description=".Net Framework Data Provider for MySQL" type="MySql.Data.MySqlClient.MySqlClientFactory, MySql.Data, Version=6.9.8.0, Culture=neutral, PublicKeyToken=c5687fc88969c44d" />
|
||||
<add name="MySQL Data Provider" invariant="MySql.Data.MySqlClient" description=".Net Framework Data Provider for MySQL" type="MySql.Data.MySqlClient.MySqlClientFactory, MySql.Data, Version=6.9.9.0, Culture=neutral, PublicKeyToken=c5687fc88969c44d" />
|
||||
</DbProviderFactories>
|
||||
</system.data></configuration>
|
||||
|
||||
@@ -2,8 +2,9 @@
|
||||
<packages>
|
||||
<package id="AutoMapper" version="3.3.1" targetFramework="net45" />
|
||||
<package id="HtmlAgilityPack" version="1.4.9.5" targetFramework="net45" />
|
||||
<package id="ImageProcessor" version="2.5.2" targetFramework="net45" />
|
||||
<package id="log4net" version="2.0.5" targetFramework="net45" />
|
||||
<package id="ImageProcessor" version="2.5.3" targetFramework="net45" />
|
||||
<package id="log4net" version="2.0.8" targetFramework="net45" />
|
||||
<package id="Log4Net.Async" version="2.0.4" targetFramework="net45" />
|
||||
<package id="Microsoft.AspNet.Identity.Core" version="2.2.1" targetFramework="net45" />
|
||||
<package id="Microsoft.AspNet.Identity.Owin" version="2.2.1" targetFramework="net45" />
|
||||
<package id="Microsoft.Owin" version="3.0.1" targetFramework="net45" />
|
||||
@@ -11,14 +12,14 @@
|
||||
<package id="Microsoft.Owin.Security.Cookies" version="3.0.1" targetFramework="net45" />
|
||||
<package id="Microsoft.Owin.Security.OAuth" version="3.0.1" targetFramework="net45" />
|
||||
<package id="MiniProfiler" version="2.1.0" targetFramework="net45" />
|
||||
<package id="MySql.Data" version="6.9.8" targetFramework="net45" />
|
||||
<package id="Newtonsoft.Json" version="9.0.1" targetFramework="net45" />
|
||||
<package id="MySql.Data" version="6.9.9" targetFramework="net45" />
|
||||
<package id="Newtonsoft.Json" version="10.0.2" targetFramework="net45" />
|
||||
<package id="Owin" version="1.0" targetFramework="net45" />
|
||||
<package id="Semver" version="2.0.4" targetFramework="net45" />
|
||||
<package id="SharpZipLib" version="0.86.0" targetFramework="net45" />
|
||||
<package id="SqlServerCE" version="4.0.0.1" targetFramework="net45" />
|
||||
<package id="System.Runtime" version="4.1.0" targetFramework="net45" />
|
||||
<package id="System.Runtime.Extensions" version="4.1.0" targetFramework="net45" />
|
||||
<package id="System.Runtime.InteropServices" version="4.1.0" targetFramework="net45" />
|
||||
<package id="System.Text.RegularExpressions" version="4.1.0" targetFramework="net45" />
|
||||
<package id="System.Runtime" version="4.3.0" targetFramework="net45" />
|
||||
<package id="System.Runtime.Extensions" version="4.3.0" targetFramework="net45" />
|
||||
<package id="System.Runtime.InteropServices" version="4.3.0" targetFramework="net45" />
|
||||
<package id="System.Text.RegularExpressions" version="4.3.0" targetFramework="net45" />
|
||||
</packages>
|
||||
@@ -45,7 +45,7 @@
|
||||
</dependentAssembly>
|
||||
<dependentAssembly>
|
||||
<assemblyIdentity name="Newtonsoft.Json" publicKeyToken="30ad4fe6b2a6aeed" culture="neutral" />
|
||||
<bindingRedirect oldVersion="0.0.0.0-9.0.0.0" newVersion="9.0.0.0" />
|
||||
<bindingRedirect oldVersion="0.0.0.0-10.0.0.0" newVersion="10.0.0.0" />
|
||||
</dependentAssembly>
|
||||
<dependentAssembly>
|
||||
<assemblyIdentity name="System.Collections.Immutable" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
|
||||
@@ -71,6 +71,10 @@
|
||||
<assemblyIdentity name="System.Runtime.Extensions" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
|
||||
<bindingRedirect oldVersion="0.0.0.0-4.1.0.0" newVersion="4.1.0.0" />
|
||||
</dependentAssembly>
|
||||
<dependentAssembly>
|
||||
<assemblyIdentity name="log4net" publicKeyToken="669e0ddf0bb1aa2a" culture="neutral" />
|
||||
<bindingRedirect oldVersion="0.0.0.0-2.0.8.0" newVersion="2.0.8.0" />
|
||||
</dependentAssembly>
|
||||
</assemblyBinding>
|
||||
</runtime>
|
||||
</configuration>
|
||||
|
||||
@@ -69,8 +69,8 @@
|
||||
<HintPath>..\packages\Microsoft.Diagnostics.Tracing.TraceEvent.1.0.41\lib\net40\Microsoft.Diagnostics.Tracing.TraceEvent.dll</HintPath>
|
||||
<Private>True</Private>
|
||||
</Reference>
|
||||
<Reference Include="Moq, Version=4.7.0.0, Culture=neutral, PublicKeyToken=69f491c39445e920, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\Moq.4.7.0\lib\net45\Moq.dll</HintPath>
|
||||
<Reference Include="Moq, Version=4.1.1309.919, Culture=neutral, PublicKeyToken=69f491c39445e920, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\Moq.4.1.1309.0919\lib\net40\Moq.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="System" />
|
||||
<Reference Include="System.Collections.Immutable, Version=1.2.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
<package id="Microsoft.CodeAnalysis.CSharp" version="1.3.2" targetFramework="net45" />
|
||||
<package id="Microsoft.Diagnostics.Tracing.TraceEvent" version="1.0.41" targetFramework="net45" />
|
||||
<package id="Microsoft.SqlServer.Compact" version="4.0.8854.1" targetFramework="net45" />
|
||||
<package id="Moq" version="4.7.0" targetFramework="net45" />
|
||||
<package id="Moq" version="4.1.1309.0919" targetFramework="net45" />
|
||||
<package id="SqlServerCE" version="4.0.0.1" targetFramework="net45" />
|
||||
<package id="System.Collections" version="4.0.11" targetFramework="net45" />
|
||||
<package id="System.Collections.Concurrent" version="4.0.12" targetFramework="net45" />
|
||||
|
||||
@@ -124,7 +124,7 @@
|
||||
|
||||
<assemblyIdentity name="Newtonsoft.Json" publicKeyToken="30ad4fe6b2a6aeed" culture="neutral" />
|
||||
|
||||
<bindingRedirect oldVersion="0.0.0.0-9.0.0.0" newVersion="9.0.0.0" />
|
||||
<bindingRedirect oldVersion="0.0.0.0-10.0.0.0" newVersion="10.0.0.0" />
|
||||
|
||||
</dependentAssembly>
|
||||
|
||||
@@ -200,6 +200,14 @@
|
||||
|
||||
</dependentAssembly>
|
||||
|
||||
<dependentAssembly>
|
||||
|
||||
<assemblyIdentity name="log4net" publicKeyToken="669e0ddf0bb1aa2a" culture="neutral" />
|
||||
|
||||
<bindingRedirect oldVersion="0.0.0.0-2.0.8.0" newVersion="2.0.8.0" />
|
||||
|
||||
</dependentAssembly>
|
||||
|
||||
</assemblyBinding>
|
||||
|
||||
</runtime>
|
||||
|
||||
@@ -35,7 +35,7 @@ namespace Umbraco.Tests.CodeFirst
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
[Test]
|
||||
@@ -84,10 +84,7 @@ namespace Umbraco.Tests.CodeFirst
|
||||
var foundTypes = _pluginManager.ResolveContentTypeBaseTypes();
|
||||
|
||||
Assert.That(foundTypes.Count(), Is.EqualTo(15));
|
||||
Assert.AreEqual(1,
|
||||
_pluginManager.GetTypeLists()
|
||||
.Count(x => x.IsTypeList<ContentTypeBase>(PluginManager.TypeResolutionKind.FindAllTypes)));
|
||||
Assert.AreEqual(1, _pluginManager.TypeLists.Count(x => x.BaseType == typeof (ContentTypeBase) && x.AttributeType == null));
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -1,168 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Threading;
|
||||
using log4net;
|
||||
using log4net.Config;
|
||||
using log4net.Core;
|
||||
using log4net.Layout;
|
||||
using log4net.Repository;
|
||||
using NUnit.Framework;
|
||||
using Umbraco.Core;
|
||||
using Umbraco.Core.Logging;
|
||||
|
||||
namespace Umbraco.Tests.Logging
|
||||
{
|
||||
[TestFixture]
|
||||
public class AsyncRollingFileAppenderTest
|
||||
{
|
||||
private const string ErrorMessage = "TEST ERROR MESSAGE";
|
||||
private const string FileFolderPath = @"c:\LogTesting\";
|
||||
private readonly Level ErrorLevel = Level.Error;
|
||||
private AsynchronousRollingFileAppender appender;
|
||||
private ILoggerRepository rep;
|
||||
private Guid fileGuid;
|
||||
|
||||
private string GetFilePath()
|
||||
{
|
||||
return string.Format("{0}{1}.log", FileFolderPath, fileGuid);
|
||||
}
|
||||
|
||||
[SetUp]
|
||||
public void SetUp()
|
||||
{
|
||||
fileGuid = Guid.NewGuid();
|
||||
if (File.Exists(GetFilePath()))
|
||||
{
|
||||
File.Delete(GetFilePath());
|
||||
}
|
||||
|
||||
appender = new AsynchronousRollingFileAppender();
|
||||
appender.Threshold = ErrorLevel;
|
||||
appender.File = GetFilePath();
|
||||
appender.Layout = new PatternLayout("%d|%-5level|%logger| %message %exception%n");
|
||||
appender.StaticLogFileName = true;
|
||||
appender.AppendToFile = true;
|
||||
appender.ActivateOptions();
|
||||
|
||||
rep = LogManager.CreateRepository(Guid.NewGuid().ToString());
|
||||
BasicConfigurator.Configure(rep, appender);
|
||||
}
|
||||
|
||||
[TearDown]
|
||||
public void TearDown()
|
||||
{
|
||||
rep.Shutdown();
|
||||
if (File.Exists(GetFilePath()))
|
||||
{
|
||||
File.Delete(GetFilePath());
|
||||
}
|
||||
}
|
||||
|
||||
[TestFixtureTearDown]
|
||||
public void FixtureTearDown()
|
||||
{
|
||||
foreach (string file in Directory.GetFiles(FileFolderPath))
|
||||
{
|
||||
try
|
||||
{
|
||||
File.Delete(file);
|
||||
}
|
||||
catch { }
|
||||
}
|
||||
}
|
||||
|
||||
private void ReleaseFileLocks()
|
||||
{
|
||||
rep.Shutdown();
|
||||
appender.Close();
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void CanWriteToFile()
|
||||
{
|
||||
// Arrange
|
||||
ILog log = LogManager.GetLogger(rep.Name, "CanWriteToDatabase");
|
||||
|
||||
// Act
|
||||
log.Error(ErrorMessage);
|
||||
Thread.Sleep(200); // let background thread finish
|
||||
|
||||
// Assert
|
||||
ReleaseFileLocks();
|
||||
Assert.That(File.Exists(GetFilePath()), Is.True);
|
||||
IEnumerable<string> readLines = File.ReadLines(GetFilePath());
|
||||
Assert.That(readLines.Count(), Is.GreaterThanOrEqualTo(1));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void ReturnsQuicklyAfterLogging100Messages()
|
||||
{
|
||||
// Arrange
|
||||
ILog log = LogManager.GetLogger(rep.Name, "ReturnsQuicklyAfterLogging100Messages");
|
||||
|
||||
// Act
|
||||
DateTime startTime = DateTime.UtcNow;
|
||||
100.Times(i => log.Error(ErrorMessage));
|
||||
DateTime endTime = DateTime.UtcNow;
|
||||
|
||||
// Give background thread time to finish
|
||||
Thread.Sleep(500);
|
||||
|
||||
// Assert
|
||||
ReleaseFileLocks();
|
||||
Assert.That(endTime - startTime, Is.LessThan(TimeSpan.FromMilliseconds(100)));
|
||||
Assert.That(File.Exists(GetFilePath()), Is.True);
|
||||
IEnumerable<string> readLines = File.ReadLines(GetFilePath());
|
||||
Assert.That(readLines.Count(), Is.GreaterThanOrEqualTo(100));
|
||||
}
|
||||
|
||||
[Test]
|
||||
[Ignore]
|
||||
public void CanLogAtleast1000MessagesASecond()
|
||||
{
|
||||
// Arrange
|
||||
ILog log = LogManager.GetLogger(rep.Name, "CanLogAtLeast1000MessagesASecond");
|
||||
|
||||
int logCount = 0;
|
||||
bool logging = true;
|
||||
bool logsCounted = false;
|
||||
|
||||
var logTimer = new Timer(s =>
|
||||
{
|
||||
logging = false;
|
||||
|
||||
if (File.Exists(GetFilePath()))
|
||||
{
|
||||
ReleaseFileLocks();
|
||||
IEnumerable<string> readLines = File.ReadLines(GetFilePath());
|
||||
logCount = readLines.Count();
|
||||
}
|
||||
logsCounted = true;
|
||||
}, null, TimeSpan.FromSeconds(3), TimeSpan.FromMilliseconds(-1));
|
||||
|
||||
// Act
|
||||
DateTime startTime = DateTime.UtcNow;
|
||||
while (logging)
|
||||
{
|
||||
log.Error(ErrorMessage);
|
||||
}
|
||||
TimeSpan testDuration = DateTime.UtcNow - startTime;
|
||||
|
||||
while (!logsCounted)
|
||||
{
|
||||
Thread.Sleep(1);
|
||||
}
|
||||
|
||||
logTimer.Dispose();
|
||||
|
||||
// Assert
|
||||
var logsPerSecond = logCount / testDuration.TotalSeconds;
|
||||
|
||||
Debug.Print("{0} messages logged in {1}s => {2}/s", logCount, testDuration.TotalSeconds, logsPerSecond);
|
||||
Assert.That(logsPerSecond, Is.GreaterThan(1000), "Must log at least 1000 messages per second");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,25 +0,0 @@
|
||||
using System;
|
||||
using System.Threading;
|
||||
using log4net.Appender;
|
||||
using log4net.Core;
|
||||
|
||||
namespace Umbraco.Tests.Logging
|
||||
{
|
||||
/// <summary>
|
||||
/// Borrowed from https://github.com/cjbhaines/Log4Net.Async - will reference Nuget packages directly in v8
|
||||
/// </summary>
|
||||
public class DebugAppender : MemoryAppender
|
||||
{
|
||||
public TimeSpan AppendDelay { get; set; }
|
||||
public int LoggedEventCount { get { return m_eventsList.Count; } }
|
||||
|
||||
protected override void Append(LoggingEvent loggingEvent)
|
||||
{
|
||||
if (AppendDelay > TimeSpan.Zero)
|
||||
{
|
||||
Thread.Sleep(AppendDelay);
|
||||
}
|
||||
base.Append(loggingEvent);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,327 +0,0 @@
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.Security.Principal;
|
||||
using System.Threading;
|
||||
using log4net;
|
||||
using log4net.Appender;
|
||||
using log4net.Config;
|
||||
using log4net.Core;
|
||||
using log4net.Filter;
|
||||
using log4net.Repository;
|
||||
using Moq;
|
||||
using NUnit.Framework;
|
||||
using Umbraco.Core.Logging;
|
||||
|
||||
namespace Umbraco.Tests.Logging
|
||||
{
|
||||
/// <summary>
|
||||
/// Borrowed from https://github.com/cjbhaines/Log4Net.Async - will reference Nuget packages directly in v8
|
||||
/// </summary>
|
||||
[TestFixture]
|
||||
public class ParallelForwarderTest : IDisposable
|
||||
{
|
||||
private ParallelForwardingAppender asyncForwardingAppender;
|
||||
private DebugAppender debugAppender;
|
||||
private ILoggerRepository repository;
|
||||
private ILog log;
|
||||
|
||||
[SetUp]
|
||||
public void TestFixtureSetUp()
|
||||
{
|
||||
debugAppender = new DebugAppender();
|
||||
debugAppender.ActivateOptions();
|
||||
|
||||
asyncForwardingAppender = new ParallelForwardingAppender();
|
||||
asyncForwardingAppender.AddAppender(debugAppender);
|
||||
asyncForwardingAppender.ActivateOptions();
|
||||
|
||||
repository = LogManager.CreateRepository(Guid.NewGuid().ToString());
|
||||
BasicConfigurator.Configure(repository, asyncForwardingAppender);
|
||||
|
||||
log = LogManager.GetLogger(repository.Name, "TestLogger");
|
||||
}
|
||||
|
||||
[TearDown]
|
||||
public void TearDown()
|
||||
{
|
||||
LogManager.Shutdown();
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void CanHandleNullLoggingEvent()
|
||||
{
|
||||
// Arrange
|
||||
|
||||
// Act
|
||||
asyncForwardingAppender.DoAppend((LoggingEvent)null);
|
||||
log.Info("SusequentMessage");
|
||||
asyncForwardingAppender.Close();
|
||||
|
||||
// Assert - should not have had an exception from previous call
|
||||
Assert.That(debugAppender.LoggedEventCount, Is.EqualTo(1), "Expected subsequent message only");
|
||||
Assert.That(debugAppender.GetEvents()[0].MessageObject, Is.EqualTo("SusequentMessage"));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void CanHandleNullLoggingEvents()
|
||||
{
|
||||
// Arrange
|
||||
|
||||
// Act
|
||||
asyncForwardingAppender.DoAppend((LoggingEvent[])null);
|
||||
log.Info("SusequentMessage");
|
||||
asyncForwardingAppender.Close();
|
||||
|
||||
// Assert - should not have had an exception from previous call
|
||||
Assert.That(debugAppender.LoggedEventCount, Is.EqualTo(1), "Expected subsequent message only");
|
||||
Assert.That(debugAppender.GetEvents()[0].MessageObject, Is.EqualTo("SusequentMessage"));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void CanHandleAppenderThrowing()
|
||||
{
|
||||
// Arrange
|
||||
var badAppender = new Mock<IAppender>();
|
||||
asyncForwardingAppender.AddAppender(badAppender.Object);
|
||||
|
||||
badAppender
|
||||
.Setup(ba => ba.DoAppend(It.IsAny<LoggingEvent>()))
|
||||
.Throws(new Exception("Bad Appender"));
|
||||
//.Verifiable();
|
||||
|
||||
// Act
|
||||
log.Info("InitialMessage");
|
||||
log.Info("SusequentMessage");
|
||||
asyncForwardingAppender.Close();
|
||||
|
||||
// Assert
|
||||
Assert.That(debugAppender.LoggedEventCount, Is.EqualTo(2));
|
||||
Assert.That(debugAppender.GetEvents()[1].MessageObject, Is.EqualTo("SusequentMessage"));
|
||||
badAppender.Verify(appender => appender.DoAppend(It.IsAny<LoggingEvent>()), Times.Exactly(2));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void WillLogFastWhenThereIsASlowAppender()
|
||||
{
|
||||
const int testSize = 1000;
|
||||
|
||||
// Arrange
|
||||
debugAppender.AppendDelay = TimeSpan.FromSeconds(30);
|
||||
var watch = new Stopwatch();
|
||||
|
||||
// Act
|
||||
watch.Start();
|
||||
for (int i = 0; i < testSize; i++)
|
||||
{
|
||||
log.Error("Exception");
|
||||
}
|
||||
watch.Stop();
|
||||
|
||||
// Assert
|
||||
Assert.That(debugAppender.LoggedEventCount, Is.EqualTo(0));
|
||||
Assert.That(watch.ElapsedMilliseconds, Is.LessThan(testSize));
|
||||
Debug.Print("Logged {0} errors in {1}ms", testSize, watch.ElapsedMilliseconds);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void WillNotOverflow()
|
||||
{
|
||||
const int testSize = 1000;
|
||||
|
||||
// Arrange
|
||||
debugAppender.AppendDelay = TimeSpan.FromMilliseconds(1);
|
||||
asyncForwardingAppender.BufferSize = 100;
|
||||
|
||||
// Act
|
||||
for (int i = 0; i < testSize; i++)
|
||||
{
|
||||
log.Error("Exception");
|
||||
}
|
||||
|
||||
while (asyncForwardingAppender.BufferEntryCount > 0) ;
|
||||
asyncForwardingAppender.Close();
|
||||
|
||||
// Assert
|
||||
Assert.That(debugAppender.LoggedEventCount, Is.EqualTo(testSize));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void WillTryToFlushBufferOnShutdown()
|
||||
{
|
||||
const int testSize = 250;
|
||||
|
||||
// Arrange
|
||||
debugAppender.AppendDelay = TimeSpan.FromMilliseconds(1);
|
||||
|
||||
// Act
|
||||
for (int i = 0; i < testSize; i++)
|
||||
{
|
||||
log.Error("Exception");
|
||||
}
|
||||
|
||||
Thread.Sleep(50);
|
||||
|
||||
var numberLoggedBeforeClose = debugAppender.LoggedEventCount;
|
||||
asyncForwardingAppender.Close();
|
||||
var numberLoggedAfterClose = debugAppender.LoggedEventCount;
|
||||
|
||||
// Assert
|
||||
//We can't use specific numbers here because the timing and counts will be different on different systems.
|
||||
Assert.That(numberLoggedBeforeClose, Is.GreaterThan(0), "Some number of Logging events should be logged prior to appender close.");
|
||||
//On some systems, we may not be able to flush all events prior to close, but it is reasonable to assume in this test case
|
||||
//that some events should be logged after close.
|
||||
Assert.That(numberLoggedAfterClose, Is.GreaterThan(numberLoggedBeforeClose), "Some number of LoggingEvents should be logged after close.");
|
||||
Debug.Print("Flushed {0} events during shutdown", numberLoggedAfterClose - numberLoggedBeforeClose);
|
||||
}
|
||||
|
||||
[Test, Explicit("Long-running")]
|
||||
public void WillShutdownIfBufferCannotBeFlushedFastEnough()
|
||||
{
|
||||
const int testSize = 250;
|
||||
|
||||
// Arrange
|
||||
debugAppender.AppendDelay = TimeSpan.FromSeconds(1);
|
||||
Stopwatch watch = new Stopwatch();
|
||||
|
||||
// Act
|
||||
for (int i = 0; i < testSize; i++)
|
||||
{
|
||||
log.Error("Exception");
|
||||
}
|
||||
|
||||
Thread.Sleep(TimeSpan.FromSeconds(2));
|
||||
var numberLoggedBeforeClose = debugAppender.LoggedEventCount;
|
||||
|
||||
watch.Start();
|
||||
asyncForwardingAppender.Close();
|
||||
watch.Stop();
|
||||
|
||||
var numberLoggedAfterClose = debugAppender.LoggedEventCount;
|
||||
|
||||
// Assert
|
||||
Assert.That(numberLoggedBeforeClose, Is.GreaterThan(0));
|
||||
Assert.That(numberLoggedAfterClose, Is.GreaterThan(numberLoggedBeforeClose));
|
||||
Assert.That(numberLoggedAfterClose, Is.LessThan(testSize));
|
||||
//We can't assume what the shutdown time will be. It will vary from system to system. Don't test shutdown time.
|
||||
var events = debugAppender.GetEvents();
|
||||
var evnt = events[events.Length - 1];
|
||||
Assert.That(evnt.MessageObject, Is.EqualTo("The buffer was not able to be flushed before timeout occurred."));
|
||||
Debug.Print("Flushed {0} events during shutdown which lasted {1}ms", numberLoggedAfterClose - numberLoggedBeforeClose, watch.ElapsedMilliseconds);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void ThreadContextPropertiesArePreserved()
|
||||
{
|
||||
// Arrange
|
||||
ThreadContext.Properties["TestProperty"] = "My Value";
|
||||
Assert.That(asyncForwardingAppender.Fix & FixFlags.Properties, Is.EqualTo(FixFlags.Properties), "Properties must be fixed if they are to be preserved");
|
||||
|
||||
// Act
|
||||
log.Info("Information");
|
||||
asyncForwardingAppender.Close();
|
||||
|
||||
// Assert
|
||||
var lastLoggedEvent = debugAppender.GetEvents()[0];
|
||||
Assert.That(lastLoggedEvent.Properties["TestProperty"], Is.EqualTo("My Value"));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void MessagesExcludedByFilterShouldNotBeAppended()
|
||||
{
|
||||
// Arrange
|
||||
var levelFilter =
|
||||
new LevelRangeFilter
|
||||
{
|
||||
LevelMin = Level.Warn,
|
||||
LevelMax = Level.Error,
|
||||
};
|
||||
|
||||
asyncForwardingAppender.AddFilter(levelFilter);
|
||||
|
||||
// Act
|
||||
log.Info("Info");
|
||||
log.Warn("Warn");
|
||||
log.Error("Error");
|
||||
log.Fatal("Fatal");
|
||||
|
||||
asyncForwardingAppender.Close();
|
||||
|
||||
//Assert
|
||||
Assert.That(debugAppender.LoggedEventCount, Is.EqualTo(2));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void HelperCanGenerateLoggingEventWithAllProperties()
|
||||
{
|
||||
// Arrange
|
||||
var helper = new LoggingEventHelper("TestLoggerName", FixFlags.All);
|
||||
ThreadContext.Properties["MyProperty"] = "MyValue";
|
||||
var exception = new Exception("SomeError");
|
||||
|
||||
var stackFrame = new StackFrame(0);
|
||||
var currentUser = WindowsIdentity.GetCurrent();
|
||||
var loggingTime = DateTime.Now; // Log4Net does not seem to be using UtcNow
|
||||
|
||||
// Act
|
||||
var loggingEvent = helper.CreateLoggingEvent(Level.Emergency, "Who's on live support?", exception);
|
||||
Thread.Sleep(50); // to make sure the time stamp is actually captured
|
||||
|
||||
// Assert
|
||||
Assert.That(loggingEvent.Domain, Is.EqualTo(AppDomain.CurrentDomain.FriendlyName), "Domain");
|
||||
//The identity assigned to new threads is dependent upon AppDomain principal policy.
|
||||
//Background information here:http://www.neovolve.com/post/2010/10/21/Unit-testing-a-workflow-that-relies-on-ThreadCurrentPrincipalIdentityName.aspx
|
||||
//VS2013 does have a principal assigned to new threads in the unit test.
|
||||
//It's probably best not to test that the identity has been set.
|
||||
//Assert.That(loggingEvent.Identity, Is.Empty, "Identity: always empty for some reason");
|
||||
Assert.That(loggingEvent.UserName, Is.EqualTo(currentUser == null ? String.Empty : currentUser.Name), "UserName");
|
||||
Assert.That(loggingEvent.ThreadName, Is.EqualTo(Thread.CurrentThread.Name), "ThreadName");
|
||||
|
||||
Assert.That(loggingEvent.Repository, Is.Null, "Repository: Helper does not have access to this");
|
||||
Assert.That(loggingEvent.LoggerName, Is.EqualTo("TestLoggerName"), "LoggerName");
|
||||
|
||||
Assert.That(loggingEvent.Level, Is.EqualTo(Level.Emergency), "Level");
|
||||
//Raised time to within 10 ms. However, this may not be a valid test. The time is going to vary from system to system. The
|
||||
//tolerance setting here is arbitrary.
|
||||
Assert.That(loggingEvent.TimeStamp, Is.EqualTo(loggingTime).Within(TimeSpan.FromMilliseconds(10)), "TimeStamp");
|
||||
Assert.That(loggingEvent.ExceptionObject, Is.EqualTo(exception), "ExceptionObject");
|
||||
Assert.That(loggingEvent.MessageObject, Is.EqualTo("Who's on live support?"), "MessageObject");
|
||||
|
||||
Assert.That(loggingEvent.LocationInformation.MethodName, Is.EqualTo(stackFrame.GetMethod().Name), "LocationInformation");
|
||||
Assert.That(loggingEvent.Properties["MyProperty"], Is.EqualTo("MyValue"), "Properties");
|
||||
}
|
||||
|
||||
private bool _disposed = false;
|
||||
|
||||
//Implement IDisposable.
|
||||
public void Dispose()
|
||||
{
|
||||
Dispose(true);
|
||||
GC.SuppressFinalize(this);
|
||||
}
|
||||
|
||||
protected virtual void Dispose(bool disposing)
|
||||
{
|
||||
if (!_disposed)
|
||||
{
|
||||
if (disposing)
|
||||
{
|
||||
if (asyncForwardingAppender != null)
|
||||
{
|
||||
asyncForwardingAppender.Dispose();
|
||||
asyncForwardingAppender = null;
|
||||
}
|
||||
}
|
||||
// Free your own state (unmanaged objects).
|
||||
// Set large fields to null.
|
||||
_disposed = true;
|
||||
}
|
||||
}
|
||||
|
||||
// Use C# destructor syntax for finalization code.
|
||||
~ParallelForwarderTest()
|
||||
{
|
||||
// Simply call Dispose(false).
|
||||
Dispose(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,150 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using NUnit.Framework;
|
||||
using Umbraco.Core.Logging;
|
||||
using Umbraco.Tests.TestHelpers;
|
||||
|
||||
namespace Umbraco.Tests.Logging
|
||||
{
|
||||
/// <summary>
|
||||
/// Borrowed from https://github.com/cjbhaines/Log4Net.Async - will reference Nuget packages directly in v8
|
||||
/// </summary>
|
||||
[TestFixture]
|
||||
public class RingBufferTest
|
||||
{
|
||||
[Test]
|
||||
public void PerfTest()
|
||||
{
|
||||
RingBuffer<string> ringBuffer = new RingBuffer<string>(1000);
|
||||
Stopwatch ringWatch = new Stopwatch();
|
||||
ringWatch.Start();
|
||||
for (int i = 0; i < 1000000; i++)
|
||||
{
|
||||
ringBuffer.Enqueue("StringOfFun");
|
||||
}
|
||||
ringWatch.Stop();
|
||||
|
||||
Assert.That(ringWatch.ElapsedMilliseconds, Is.LessThan(150));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void PerfTestThreads()
|
||||
{
|
||||
RingBuffer<string> ringBuffer = new RingBuffer<string>(1000);
|
||||
|
||||
Stopwatch ringWatch = new Stopwatch();
|
||||
List<Task> ringTasks = new List<Task>();
|
||||
CancellationTokenSource cancelationTokenSource = new CancellationTokenSource();
|
||||
CancellationToken cancelationToken = cancelationTokenSource.Token;
|
||||
for (int t = 0; t < 10; t++)
|
||||
{
|
||||
ringTasks.Add(new Task(() =>
|
||||
{
|
||||
for (int i = 0; i < 1000000; i++)
|
||||
{
|
||||
ringBuffer.Enqueue("StringOfFun");
|
||||
}
|
||||
}, cancelationToken));
|
||||
}
|
||||
ringWatch.Start();
|
||||
ringTasks.ForEach(t => t.Start());
|
||||
var allTasks = ringTasks.ToArray();
|
||||
Task.WaitAny(allTasks);
|
||||
ringWatch.Stop();
|
||||
//Cancel tasks to avoid System.AppDominUnloadException which is caused when the domain is unloaded
|
||||
//and threads created in the domain are not stopped.
|
||||
//Do this before assertions because they may throw an exception causing the thread cancellation to not happen.
|
||||
cancelationTokenSource.Cancel();
|
||||
try
|
||||
{
|
||||
Task.WaitAll(allTasks);
|
||||
}
|
||||
catch (AggregateException)
|
||||
{
|
||||
//Don't care about cancellation Exceptions.
|
||||
}
|
||||
//Tolerance at 500 was too low
|
||||
ringTasks.ForEach(t => t.Dispose());
|
||||
Assert.That(ringWatch.ElapsedMilliseconds, Is.LessThan(1000));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void PerfTestThreadsWithDequeues()
|
||||
{
|
||||
RingBuffer<string> ringBuffer = new RingBuffer<string>(1000);
|
||||
|
||||
Stopwatch ringWatch = new Stopwatch();
|
||||
List<Task> ringTasks = new List<Task>();
|
||||
CancellationTokenSource cancelationTokenSource = new CancellationTokenSource();
|
||||
CancellationToken cancelationToken = cancelationTokenSource.Token;
|
||||
for (int t = 0; t < 10; t++)
|
||||
{
|
||||
ringTasks.Add(new Task(() =>
|
||||
{
|
||||
for (int i = 0; i < 1000000; i++)
|
||||
{
|
||||
ringBuffer.Enqueue("StringOfFun");
|
||||
}
|
||||
}, cancelationToken));
|
||||
}
|
||||
for (int t = 0; t < 10; t++)
|
||||
{
|
||||
ringTasks.Add(new Task(() =>
|
||||
{
|
||||
for (int i = 0; i < 1000000; i++)
|
||||
{
|
||||
string foo;
|
||||
ringBuffer.TryDequeue(out foo);
|
||||
}
|
||||
}));
|
||||
}
|
||||
ringWatch.Start();
|
||||
ringTasks.ForEach(t => t.Start());
|
||||
var allTasks = ringTasks.ToArray();
|
||||
Task.WaitAny(allTasks);
|
||||
ringWatch.Stop();
|
||||
//Cancel tasks to avoid System.AppDominUnloadException which is caused when the domain is unloaded
|
||||
//and threads created in the domain are not stopped.
|
||||
//Do this before assertions because they may throw an exception causing the thread cancellation to not happen.
|
||||
cancelationTokenSource.Cancel();
|
||||
try
|
||||
{
|
||||
Task.WaitAll(allTasks);
|
||||
}
|
||||
catch (AggregateException)
|
||||
{
|
||||
//Don't care about cancellation Exceptions.
|
||||
}
|
||||
ringTasks.ForEach(t => t.Dispose());
|
||||
Assert.That(ringWatch.ElapsedMilliseconds, Is.LessThan(800));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void WhenRingSizeLimitIsHit_ItemsAreDequeued()
|
||||
{
|
||||
// Arrange
|
||||
const int limit = 2;
|
||||
object object1 = "one";
|
||||
object object2 = "two";
|
||||
object object3 = "three";
|
||||
RingBuffer<object> queue = new RingBuffer<object>(limit);
|
||||
|
||||
// Act
|
||||
queue.Enqueue(object1);
|
||||
queue.Enqueue(object2);
|
||||
queue.Enqueue(object3);
|
||||
|
||||
// Assert
|
||||
object value;
|
||||
queue.TryDequeue(out value);
|
||||
Assert.That(value, Is.EqualTo(object2));
|
||||
queue.TryDequeue(out value);
|
||||
Assert.That(value, Is.EqualTo(object3));
|
||||
queue.TryDequeue(out value);
|
||||
Assert.That(value, Is.Null);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -18,6 +18,7 @@ using Umbraco.Core.Profiling;
|
||||
using Umbraco.Core.PropertyEditors;
|
||||
using umbraco.DataLayer;
|
||||
using umbraco.editorControls;
|
||||
using umbraco.interfaces;
|
||||
using umbraco.MacroEngines;
|
||||
using umbraco.uicontrols;
|
||||
using Umbraco.Web;
|
||||
@@ -34,14 +35,14 @@ namespace Umbraco.Tests.Plugins
|
||||
public void Initialize()
|
||||
{
|
||||
//this ensures its reset
|
||||
_manager = new PluginManager(new ActivatorServiceProvider(), new NullCacheProvider(),
|
||||
_manager = new PluginManager(new ActivatorServiceProvider(), new NullCacheProvider(),
|
||||
new ProfilingLogger(Mock.Of<ILogger>(), Mock.Of<IProfiler>()));
|
||||
|
||||
//for testing, we'll specify which assemblies are scanned for the PluginTypeResolver
|
||||
//TODO: Should probably update this so it only searches this assembly and add custom types to be found
|
||||
_manager.AssembliesToScan = new[]
|
||||
{
|
||||
this.GetType().Assembly,
|
||||
this.GetType().Assembly,
|
||||
typeof(ApplicationStartupHandler).Assembly,
|
||||
typeof(SqlCEHelper).Assembly,
|
||||
typeof(CMSNode).Assembly,
|
||||
@@ -160,7 +161,7 @@ namespace Umbraco.Tests.Plugins
|
||||
public void Detect_Legacy_Plugin_File_List()
|
||||
{
|
||||
var tempFolder = IOHelper.MapPath("~/App_Data/TEMP/PluginCache");
|
||||
|
||||
|
||||
var filePath= Path.Combine(tempFolder, string.Format("umbraco-plugins.{0}.list", NetworkHelper.FileSafeMachineName));
|
||||
|
||||
File.WriteAllText(filePath, @"<?xml version=""1.0"" encoding=""utf-8""?>
|
||||
@@ -169,12 +170,11 @@ namespace Umbraco.Tests.Plugins
|
||||
<add type=""umbraco.macroCacheRefresh, umbraco, Version=6.0.0.0, Culture=neutral, PublicKeyToken=null"" />
|
||||
</baseType>
|
||||
</plugins>");
|
||||
|
||||
Assert.IsTrue(_manager.DetectLegacyPluginListFile());
|
||||
|
||||
Assert.IsEmpty(_manager.ReadCache()); // uber-legacy cannot be read
|
||||
|
||||
File.Delete(filePath);
|
||||
|
||||
//now create a valid one
|
||||
File.WriteAllText(filePath, @"<?xml version=""1.0"" encoding=""utf-8""?>
|
||||
<plugins>
|
||||
<baseType type=""umbraco.interfaces.ICacheRefresher"" resolutionType=""FindAllTypes"">
|
||||
@@ -182,19 +182,32 @@ namespace Umbraco.Tests.Plugins
|
||||
</baseType>
|
||||
</plugins>");
|
||||
|
||||
Assert.IsFalse(_manager.DetectLegacyPluginListFile());
|
||||
Assert.IsEmpty(_manager.ReadCache()); // legacy cannot be read
|
||||
|
||||
File.Delete(filePath);
|
||||
|
||||
File.WriteAllText(filePath, @"IContentFinder
|
||||
|
||||
MyContentFinder
|
||||
AnotherContentFinder
|
||||
|
||||
");
|
||||
|
||||
Assert.IsNotNull(_manager.ReadCache()); // works
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Create_Cached_Plugin_File()
|
||||
{
|
||||
var types = new[] { typeof(PluginManager), typeof(PluginManagerTests), typeof(UmbracoContext) };
|
||||
var types = new[] { typeof (PluginManager), typeof (PluginManagerTests), typeof (UmbracoContext) };
|
||||
|
||||
//yes this is silly, none of these types inherit from string, but this is just to test the xml file format
|
||||
_manager.UpdateCachedPluginsFile<string>(types, PluginManager.TypeResolutionKind.FindAllTypes);
|
||||
var typeList1 = new PluginManager.TypeList(typeof (object), null);
|
||||
foreach (var type in types) typeList1.Add(type);
|
||||
_manager.AddTypeList(typeList1);
|
||||
_manager.WriteCache();
|
||||
|
||||
var plugins = _manager.TryGetCachedPluginsFromFile<string>(PluginManager.TypeResolutionKind.FindAllTypes);
|
||||
var diffType = _manager.TryGetCachedPluginsFromFile<string>(PluginManager.TypeResolutionKind.FindAttributedTypes);
|
||||
var plugins = _manager.TryGetCached(typeof (object), null);
|
||||
var diffType = _manager.TryGetCached(typeof (object), typeof (ObsoleteAttribute));
|
||||
|
||||
Assert.IsTrue(plugins.Success);
|
||||
//this will be false since there is no cache of that type resolution kind
|
||||
@@ -210,7 +223,7 @@ namespace Umbraco.Tests.Plugins
|
||||
public void PluginHash_From_String()
|
||||
{
|
||||
var s = "hello my name is someone".GetHashCode().ToString("x", CultureInfo.InvariantCulture);
|
||||
var output = PluginManager.ConvertPluginsHashFromHex(s);
|
||||
var output = PluginManager.ConvertHashToInt64(s);
|
||||
Assert.AreNotEqual(0, output);
|
||||
}
|
||||
|
||||
@@ -240,7 +253,7 @@ namespace Umbraco.Tests.Plugins
|
||||
var list1 = new[] { f1, f2, f3, f4, f5, f6 };
|
||||
var list2 = new[] { f1, f3, f5 };
|
||||
var list3 = new[] { f1, f3, f5, f7 };
|
||||
|
||||
|
||||
//Act
|
||||
var hash1 = PluginManager.GetFileHash(list1, new ProfilingLogger(Mock.Of<ILogger>(), Mock.Of<IProfiler>()));
|
||||
var hash2 = PluginManager.GetFileHash(list2, new ProfilingLogger(Mock.Of<ILogger>(), Mock.Of<IProfiler>()));
|
||||
@@ -259,9 +272,7 @@ namespace Umbraco.Tests.Plugins
|
||||
{
|
||||
var foundTypes1 = _manager.ResolveFindMeTypes();
|
||||
var foundTypes2 = _manager.ResolveFindMeTypes();
|
||||
Assert.AreEqual(1,
|
||||
_manager.GetTypeLists()
|
||||
.Count(x => x.IsTypeList<IFindMe>(PluginManager.TypeResolutionKind.FindAllTypes)));
|
||||
Assert.AreEqual(1, _manager.TypeLists.Count(x => x.BaseType == typeof(IFindMe) && x.AttributeType == null));
|
||||
}
|
||||
|
||||
[Test]
|
||||
@@ -344,20 +355,20 @@ namespace Umbraco.Tests.Plugins
|
||||
{
|
||||
var types = new HashSet<PluginManager.TypeList>();
|
||||
|
||||
var propEditors = new PluginManager.TypeList<PropertyEditor>(PluginManager.TypeResolutionKind.FindAllTypes);
|
||||
propEditors.AddType(typeof(LabelPropertyEditor));
|
||||
var propEditors = new PluginManager.TypeList(typeof (PropertyEditor), null);
|
||||
propEditors.Add(typeof(LabelPropertyEditor));
|
||||
types.Add(propEditors);
|
||||
|
||||
var found = types.SingleOrDefault(x => x.IsTypeList<PropertyEditor>(PluginManager.TypeResolutionKind.FindAllTypes));
|
||||
var found = types.SingleOrDefault(x => x.BaseType == typeof (PropertyEditor) && x.AttributeType == null);
|
||||
|
||||
Assert.IsNotNull(found);
|
||||
|
||||
//This should not find a type list of this type
|
||||
var shouldNotFind = types.SingleOrDefault(x => x.IsTypeList<IParameterEditor>(PluginManager.TypeResolutionKind.FindAllTypes));
|
||||
var shouldNotFind = types.SingleOrDefault(x => x.BaseType == typeof (IParameterEditor) && x.AttributeType == null);
|
||||
|
||||
Assert.IsNull(shouldNotFind);
|
||||
}
|
||||
|
||||
|
||||
[XsltExtension("Blah.Blah")]
|
||||
public class MyXsltExtension
|
||||
{
|
||||
@@ -371,7 +382,7 @@ namespace Umbraco.Tests.Plugins
|
||||
|
||||
}
|
||||
|
||||
public interface IFindMe
|
||||
public interface IFindMe : IDiscoverable
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
@@ -26,11 +26,11 @@ using Umbraco.Web.BaseRest;
|
||||
|
||||
namespace Umbraco.Tests.Plugins
|
||||
{
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Tests for typefinder
|
||||
/// </summary>
|
||||
[TestFixture]
|
||||
[TestFixture]
|
||||
public class TypeFinderTests
|
||||
{
|
||||
/// <summary>
|
||||
@@ -43,7 +43,7 @@ namespace Umbraco.Tests.Plugins
|
||||
{
|
||||
_assemblies = new[]
|
||||
{
|
||||
this.GetType().Assembly,
|
||||
this.GetType().Assembly,
|
||||
typeof(ApplicationStartupHandler).Assembly,
|
||||
typeof(SqlCEHelper).Assembly,
|
||||
typeof(CMSNode).Assembly,
|
||||
@@ -75,7 +75,7 @@ namespace Umbraco.Tests.Plugins
|
||||
[Test]
|
||||
public void Find_Classes_Of_Type()
|
||||
{
|
||||
var typesFound = TypeFinder.FindClassesOfType<IApplicationStartupHandler>(_assemblies);
|
||||
var typesFound = TypeFinder.FindClassesOfType<IApplicationStartupHandler>(_assemblies);
|
||||
var originalTypesFound = TypeFinderOriginal.FindClassesOfType<IApplicationStartupHandler>(_assemblies);
|
||||
|
||||
Assert.AreEqual(originalTypesFound.Count(), typesFound.Count());
|
||||
@@ -118,7 +118,7 @@ namespace Umbraco.Tests.Plugins
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
[Ignore]
|
||||
@@ -149,7 +149,7 @@ namespace Umbraco.Tests.Plugins
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
public class MyTag : ITag
|
||||
@@ -161,7 +161,7 @@ namespace Umbraco.Tests.Plugins
|
||||
|
||||
public class MySuperTag : MyTag
|
||||
{
|
||||
|
||||
|
||||
}
|
||||
|
||||
[AttributeUsage(AttributeTargets.Class, AllowMultiple = false)]
|
||||
@@ -203,7 +203,7 @@ namespace Umbraco.Tests.Plugins
|
||||
/// This is a modified version of: http://www.dominicpettifer.co.uk/Blog/44/how-to-get-a-reference-to-all-assemblies-in-the--bin-folder
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// We do this because we cannot use AppDomain.Current.GetAssemblies() as this will return only assemblies that have been
|
||||
/// We do this because we cannot use AppDomain.Current.GetAssemblies() as this will return only assemblies that have been
|
||||
/// loaded in the CLR, not all assemblies.
|
||||
/// See these threads:
|
||||
/// http://issues.umbraco.org/issue/U5-198
|
||||
@@ -329,8 +329,8 @@ namespace Umbraco.Tests.Plugins
|
||||
}
|
||||
catch (SecurityException)
|
||||
{
|
||||
//we will just ignore this because this will fail
|
||||
//in medium trust for system assemblies, we get an exception but we just want to continue until we get to
|
||||
//we will just ignore this because this will fail
|
||||
//in medium trust for system assemblies, we get an exception but we just want to continue until we get to
|
||||
//an assembly that is ok.
|
||||
}
|
||||
}
|
||||
@@ -347,9 +347,9 @@ namespace Umbraco.Tests.Plugins
|
||||
}
|
||||
catch (SecurityException)
|
||||
{
|
||||
//we will just ignore this because if we are trying to do a call to:
|
||||
//we will just ignore this because if we are trying to do a call to:
|
||||
// AssemblyName.ReferenceMatchesDefinition(a.GetName(), assemblyName)))
|
||||
//in medium trust for system assemblies, we get an exception but we just want to continue until we get to
|
||||
//in medium trust for system assemblies, we get an exception but we just want to continue until we get to
|
||||
//an assembly that is ok.
|
||||
}
|
||||
}
|
||||
@@ -361,7 +361,7 @@ namespace Umbraco.Tests.Plugins
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Return a list of found local Assemblies excluding the known assemblies we don't want to scan
|
||||
/// Return a list of found local Assemblies excluding the known assemblies we don't want to scan
|
||||
/// and exluding the ones passed in and excluding the exclusion list filter, the results of this are
|
||||
/// cached for perforance reasons.
|
||||
/// </summary>
|
||||
@@ -429,7 +429,7 @@ namespace Umbraco.Tests.Plugins
|
||||
"RouteDebugger,",
|
||||
"SqlCE4Umbraco,",
|
||||
"umbraco.datalayer,",
|
||||
"umbraco.interfaces,",
|
||||
"umbraco.interfaces,",
|
||||
"umbraco.providers,",
|
||||
"Umbraco.Web.UI,",
|
||||
"umbraco.webservices",
|
||||
@@ -631,5 +631,5 @@ namespace Umbraco.Tests.Plugins
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
@@ -376,7 +376,7 @@ namespace Umbraco.Tests.PropertyEditors
|
||||
{
|
||||
var cropperJson = "{\"focalPoint\": {\"left\": 0.5,\"top\": 0.5},\"src\": \"" + mediaPath + "\",\"crops\": [{\"alias\": \"home\",\"width\": 270,\"height\": 161}]}";
|
||||
|
||||
var urlString = mediaPath.GetCropUrl(400, 400, cropperJson, imageCropMode: ImageCropMode.Pad, backgroundColor: "fff");
|
||||
var urlString = mediaPath.GetCropUrl(400, 400, cropperJson, imageCropMode: ImageCropMode.Pad, furtherOptions: "&bgcolor=fff");
|
||||
Assert.AreEqual(mediaPath + "?mode=pad&width=400&height=400&bgcolor=fff", urlString);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -25,14 +25,14 @@ namespace Umbraco.Tests.Routing
|
||||
{
|
||||
SiteDomainHelper.AddSite("site1", "domain1.com", "domain1.net", "domain1.org");
|
||||
SiteDomainHelper.AddSite("site2", "domain2.com", "domain2.net", "domain2.org");
|
||||
|
||||
|
||||
var sites = SiteDomainHelper.Sites;
|
||||
|
||||
Assert.AreEqual(2, sites.Count);
|
||||
|
||||
Assert.Contains("site1", sites.Keys);
|
||||
Assert.Contains("site2", sites.Keys);
|
||||
|
||||
|
||||
var domains = sites["site1"];
|
||||
Assert.AreEqual(3, domains.Count());
|
||||
Assert.Contains("domain1.com", domains);
|
||||
@@ -84,7 +84,7 @@ namespace Umbraco.Tests.Routing
|
||||
|
||||
Assert.Contains("site2", sites.Keys);
|
||||
}
|
||||
|
||||
|
||||
[Test]
|
||||
public void AddSiteAgain()
|
||||
{
|
||||
@@ -175,15 +175,15 @@ namespace Umbraco.Tests.Routing
|
||||
|
||||
// map methods are not static because we can override them
|
||||
var helper = new SiteDomainHelper();
|
||||
|
||||
|
||||
// current is a site1 uri, domains contain current
|
||||
// so we'll get current
|
||||
//
|
||||
var current = new Uri("http://domain1.com/foo/bar");
|
||||
var output = helper.MapDomain(current, new[]
|
||||
{
|
||||
new DomainAndUri(new UmbracoDomain("domain1.com"), Uri.UriSchemeHttp),
|
||||
new DomainAndUri(new UmbracoDomain("domain2.com"), Uri.UriSchemeHttp),
|
||||
new DomainAndUri(new UmbracoDomain("domain1.com"), Uri.UriSchemeHttp),
|
||||
new DomainAndUri(new UmbracoDomain("domain2.com"), Uri.UriSchemeHttp),
|
||||
}).Uri.ToString();
|
||||
Assert.AreEqual("http://domain1.com/", output);
|
||||
|
||||
@@ -193,7 +193,7 @@ namespace Umbraco.Tests.Routing
|
||||
current = new Uri("http://domain1.com/foo/bar");
|
||||
output = helper.MapDomain(current, new[]
|
||||
{
|
||||
new DomainAndUri(new UmbracoDomain("domain1.net"), Uri.UriSchemeHttp),
|
||||
new DomainAndUri(new UmbracoDomain("domain1.net"), Uri.UriSchemeHttp),
|
||||
new DomainAndUri(new UmbracoDomain("domain2.net"), Uri.UriSchemeHttp)
|
||||
}).Uri.ToString();
|
||||
Assert.AreEqual("http://domain1.net/", output);
|
||||
@@ -205,12 +205,73 @@ namespace Umbraco.Tests.Routing
|
||||
current = new Uri("http://domain1.com/foo/bar");
|
||||
output = helper.MapDomain(current, new[]
|
||||
{
|
||||
new DomainAndUri(new UmbracoDomain("domain2.net"), Uri.UriSchemeHttp),
|
||||
new DomainAndUri(new UmbracoDomain("domain2.net"), Uri.UriSchemeHttp),
|
||||
new DomainAndUri(new UmbracoDomain("domain1.net"), Uri.UriSchemeHttp)
|
||||
}).Uri.ToString();
|
||||
Assert.AreEqual("http://domain1.net/", output);
|
||||
}
|
||||
|
||||
private DomainAndUri[] DomainAndUris(Uri current, IDomain[] domains)
|
||||
{
|
||||
var scheme = current == null ? Uri.UriSchemeHttp : current.Scheme;
|
||||
return domains
|
||||
.Where(d => d.IsWildcard == false)
|
||||
.Select(d => new DomainAndUri(d, scheme))
|
||||
.OrderByDescending(d => d.Uri.ToString())
|
||||
.ToArray();
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void MapDomainWithScheme()
|
||||
{
|
||||
SiteDomainHelper.AddSite("site1", "domain1.com", "domain1.net", "domain1.org");
|
||||
SiteDomainHelper.AddSite("site2", "domain2.com", "domain2.net", "domain2.org");
|
||||
SiteDomainHelper.AddSite("site3", "domain3.com", "domain3.net", "domain3.org");
|
||||
SiteDomainHelper.AddSite("site4", "https://domain4.com", "https://domain4.net", "https://domain4.org");
|
||||
|
||||
// map methods are not static because we can override them
|
||||
var helper = new SiteDomainHelper();
|
||||
|
||||
// this works, but it's purely by chance / arbitrary
|
||||
// don't use the www in tests here!
|
||||
var current = new Uri("https://www.domain1.com/foo/bar");
|
||||
var domainAndUris = DomainAndUris(current, new []
|
||||
{
|
||||
new UmbracoDomain("domain2.com"),
|
||||
new UmbracoDomain("domain1.com"),
|
||||
});
|
||||
var output = helper.MapDomain(current, domainAndUris).Uri.ToString();
|
||||
Assert.AreEqual("https://domain1.com/", output);
|
||||
|
||||
// will pick it all right
|
||||
current = new Uri("https://domain1.com/foo/bar");
|
||||
domainAndUris = DomainAndUris(current, new[]
|
||||
{
|
||||
new UmbracoDomain("https://domain1.com"),
|
||||
new UmbracoDomain("https://domain2.com")
|
||||
});
|
||||
output = helper.MapDomain(current, domainAndUris).Uri.ToString();
|
||||
Assert.AreEqual("https://domain1.com/", output);
|
||||
|
||||
current = new Uri("https://domain1.com/foo/bar");
|
||||
domainAndUris = DomainAndUris(current, new[]
|
||||
{
|
||||
new UmbracoDomain("https://domain1.com"),
|
||||
new UmbracoDomain("https://domain4.com")
|
||||
});
|
||||
output = helper.MapDomain(current, domainAndUris).Uri.ToString();
|
||||
Assert.AreEqual("https://domain1.com/", output);
|
||||
|
||||
current = new Uri("https://domain4.com/foo/bar");
|
||||
domainAndUris = DomainAndUris(current, new[]
|
||||
{
|
||||
new UmbracoDomain("https://domain1.com"),
|
||||
new UmbracoDomain("https://domain4.com")
|
||||
});
|
||||
output = helper.MapDomain(current, domainAndUris).Uri.ToString();
|
||||
Assert.AreEqual("https://domain4.com/", output);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void MapDomains()
|
||||
{
|
||||
|
||||
@@ -3,7 +3,7 @@ using System.Diagnostics;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using NUnit.Framework;
|
||||
using Umbraco.Tests.Logging;
|
||||
using Umbraco.Tests.TestHelpers;
|
||||
using Umbraco.Web.Scheduling;
|
||||
|
||||
namespace Umbraco.Tests.Scheduling
|
||||
|
||||
@@ -27,27 +27,27 @@ namespace Umbraco.Tests.Services
|
||||
{
|
||||
//NOTE Maybe not the best way to create/save test data as we are using the services, which are being tested.
|
||||
|
||||
//Create and Save ContentType "umbTextpage" -> 1045
|
||||
//Create and Save ContentType "umbTextpage" -> 1060
|
||||
ContentType contentType = MockedContentTypes.CreateSimpleContentType("umbTextpage", "Textpage");
|
||||
contentType.Key = new Guid("1D3A8E6E-2EA9-4CC1-B229-1AEE19821522");
|
||||
ServiceContext.ContentTypeService.Save(contentType);
|
||||
|
||||
//Create and Save Content "Homepage" based on "umbTextpage" -> 1046
|
||||
//Create and Save Content "Homepage" based on "umbTextpage" -> 1061
|
||||
Content textpage = MockedContent.CreateSimpleContent(contentType);
|
||||
textpage.Key = new Guid("B58B3AD4-62C2-4E27-B1BE-837BD7C533E0");
|
||||
ServiceContext.ContentService.Save(textpage, 0);
|
||||
|
||||
//Create and Save Content "Text Page 1" based on "umbTextpage" -> 1047
|
||||
//Create and Save Content "Text Page 1" based on "umbTextpage" -> 1062
|
||||
Content subpage = MockedContent.CreateSimpleContent(contentType, "Text Page 1", textpage.Id);
|
||||
subpage.ReleaseDate = DateTime.Now.AddMinutes(-5);
|
||||
subpage.ChangePublishedState(PublishedState.Saved);
|
||||
ServiceContext.ContentService.Save(subpage, 0);
|
||||
|
||||
//Create and Save Content "Text Page 1" based on "umbTextpage" -> 1048
|
||||
//Create and Save Content "Text Page 1" based on "umbTextpage" -> 1063
|
||||
Content subpage2 = MockedContent.CreateSimpleContent(contentType, "Text Page 2", textpage.Id);
|
||||
ServiceContext.ContentService.Save(subpage2, 0);
|
||||
|
||||
//Create and Save Content "Text Page Deleted" based on "umbTextpage" -> 1049
|
||||
//Create and Save Content "Text Page Deleted" based on "umbTextpage" -> 1064
|
||||
Content trashed = MockedContent.CreateSimpleContent(contentType, "Text Page Deleted", -20);
|
||||
trashed.Trashed = true;
|
||||
ServiceContext.ContentService.Save(trashed, 0);
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
using System.Runtime.Remoting;
|
||||
using NUnit.Framework;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
@@ -9,7 +8,6 @@ using Umbraco.Core.Exceptions;
|
||||
using Umbraco.Core.Models;
|
||||
using Umbraco.Core.Models.Rdbms;
|
||||
using Umbraco.Core.Services;
|
||||
using Umbraco.Tests.CodeFirst.TestModels.Composition;
|
||||
using Umbraco.Tests.TestHelpers;
|
||||
using Umbraco.Tests.TestHelpers.Entities;
|
||||
|
||||
@@ -1644,6 +1642,38 @@ namespace Umbraco.Tests.Services
|
||||
Assert.That(descriptionPropertyTypeReloaded.PropertyGroupId.IsValueCreated, Is.False);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Empty_Description_Is_Always_Null_After_Saving_Content_Type()
|
||||
{
|
||||
var service = ServiceContext.ContentTypeService;
|
||||
var contentType = MockedContentTypes.CreateBasicContentType();
|
||||
contentType.Description = null;
|
||||
service.Save(contentType);
|
||||
|
||||
var contentType2 = MockedContentTypes.CreateBasicContentType("basePage2", "Base Page 2");
|
||||
contentType2.Description = string.Empty;
|
||||
service.Save(contentType2);
|
||||
|
||||
Assert.IsNull(contentType.Description);
|
||||
Assert.IsNull(contentType2.Description);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Empty_Description_Is_Always_Null_After_Saving_Media_Type()
|
||||
{
|
||||
var service = ServiceContext.ContentTypeService;
|
||||
var mediaType = MockedContentTypes.CreateSimpleMediaType("mediaType", "Media Type");
|
||||
mediaType.Description = null;
|
||||
service.Save(mediaType);
|
||||
|
||||
var mediaType2 = MockedContentTypes.CreateSimpleMediaType("mediaType2", "Media Type 2");
|
||||
mediaType2.Description = string.Empty;
|
||||
service.Save(mediaType2);
|
||||
|
||||
Assert.IsNull(mediaType.Description);
|
||||
Assert.IsNull(mediaType2.Description);
|
||||
}
|
||||
|
||||
private ContentType CreateComponent()
|
||||
{
|
||||
var component = new ContentType(-1)
|
||||
|
||||
@@ -533,6 +533,44 @@ namespace Umbraco.Tests.Services
|
||||
Assert.AreEqual(mediaObjectType, UmbracoObjectTypes.MediaType);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void EntityService_Can_Get_Key_For_Id()
|
||||
{
|
||||
var service = ServiceContext.EntityService;
|
||||
var result = service.GetKeyForId(1060, UmbracoObjectTypes.DocumentType);
|
||||
|
||||
Assert.IsTrue(result.Success);
|
||||
Assert.AreEqual(Guid.Parse("1D3A8E6E-2EA9-4CC1-B229-1AEE19821522"), result.Result);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void EntityService_Cannot_Get_Key_For_Id_With_Incorrect_Object_Type()
|
||||
{
|
||||
var service = ServiceContext.EntityService;
|
||||
var result = service.GetKeyForId(1060, UmbracoObjectTypes.MediaType);
|
||||
|
||||
Assert.IsFalse(result.Success);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void EntityService_Can_Get_Id_For_Key()
|
||||
{
|
||||
var service = ServiceContext.EntityService;
|
||||
var result = service.GetIdForKey(Guid.Parse("1D3A8E6E-2EA9-4CC1-B229-1AEE19821522"), UmbracoObjectTypes.DocumentType);
|
||||
|
||||
Assert.IsTrue(result.Success);
|
||||
Assert.AreEqual(1060, result.Result);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void EntityService_Cannot_Get_Id_For_Key_With_Incorrect_Object_Type()
|
||||
{
|
||||
var service = ServiceContext.EntityService;
|
||||
var result = service.GetIdForKey(Guid.Parse("1D3A8E6E-2EA9-4CC1-B229-1AEE19821522"), UmbracoObjectTypes.MediaType);
|
||||
|
||||
Assert.IsFalse(result.Success);
|
||||
}
|
||||
|
||||
private static bool _isSetup = false;
|
||||
|
||||
private int folderId;
|
||||
|
||||
@@ -1,8 +1,6 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using NUnit.Framework;
|
||||
using umbraco.cms.presentation.create.controls;
|
||||
using Umbraco.Core;
|
||||
using Umbraco.Core.Models;
|
||||
using Umbraco.Core.Models.Rdbms;
|
||||
@@ -183,6 +181,22 @@ namespace Umbraco.Tests.Services
|
||||
Assert.Throws<ArgumentException>(() => ServiceContext.MemberTypeService.Save(memberType));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Empty_Description_Is_Always_Null_After_Saving_Member_Type()
|
||||
{
|
||||
var service = ServiceContext.MemberTypeService;
|
||||
var memberType = MockedContentTypes.CreateSimpleMemberType();
|
||||
memberType.Description = null;
|
||||
service.Save(memberType);
|
||||
|
||||
var memberType2 = MockedContentTypes.CreateSimpleMemberType("memberType2", "Member Type 2");
|
||||
memberType2.Description = string.Empty;
|
||||
service.Save(memberType2);
|
||||
|
||||
Assert.IsNull(memberType.Description);
|
||||
Assert.IsNull(memberType2.Description);
|
||||
}
|
||||
|
||||
//[Test]
|
||||
//public void Can_Save_MemberType_Structure_And_Create_A_Member_Based_On_It()
|
||||
//{
|
||||
|
||||
@@ -62,7 +62,7 @@ namespace Umbraco.Tests.TestHelpers
|
||||
public override void TearDown()
|
||||
{
|
||||
base.TearDown();
|
||||
|
||||
|
||||
// reset settings
|
||||
SettingsForTests.Reset();
|
||||
UmbracoContext.Current = null;
|
||||
@@ -119,7 +119,7 @@ namespace Umbraco.Tests.TestHelpers
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// By default this returns false which means the plugin manager will not be reset so it doesn't need to re-scan
|
||||
/// By default this returns false which means the plugin manager will not be reset so it doesn't need to re-scan
|
||||
/// all of the assemblies. Inheritors can override this if plugin manager resetting is required, generally needs
|
||||
/// to be set to true if the SetupPluginManager has been overridden.
|
||||
/// </summary>
|
||||
|
||||
+1
-1
@@ -2,7 +2,7 @@
|
||||
using System.Linq;
|
||||
using Umbraco.Core.Logging;
|
||||
|
||||
namespace Umbraco.Tests.Logging
|
||||
namespace Umbraco.Tests.TestHelpers
|
||||
{
|
||||
public class ConsoleLogger : ILogger
|
||||
{
|
||||
@@ -1,5 +1,4 @@
|
||||
using System;
|
||||
using System.Linq;
|
||||
using Umbraco.Core;
|
||||
using Umbraco.Core.Models;
|
||||
|
||||
|
||||
@@ -58,14 +58,20 @@
|
||||
<Reference Include="AutoMapper.Net4, Version=3.3.1.0, Culture=neutral, PublicKeyToken=be96cd2c38ef1005, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\AutoMapper.3.3.1\lib\net40\AutoMapper.Net4.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Castle.Core, Version=4.0.0.0, Culture=neutral, PublicKeyToken=407dd0808d44fbdc, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\Castle.Core.4.0.0\lib\net45\Castle.Core.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Examine, Version=0.1.82.0, Culture=neutral, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\Examine.0.1.82\lib\net45\Examine.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="ICSharpCode.SharpZipLib, Version=0.86.0.518, Culture=neutral, PublicKeyToken=1b03e6acf1164f73, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\SharpZipLib.0.86.0\lib\20\ICSharpCode.SharpZipLib.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="log4net, Version=1.2.15.0, Culture=neutral, PublicKeyToken=669e0ddf0bb1aa2a, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\log4net.2.0.5\lib\net45-full\log4net.dll</HintPath>
|
||||
<Reference Include="log4net, Version=2.0.8.0, Culture=neutral, PublicKeyToken=669e0ddf0bb1aa2a, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\log4net.2.0.8\lib\net45-full\log4net.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Log4Net.Async, Version=2.0.4.0, Culture=neutral, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\Log4Net.Async.2.0.4\lib\net40\Log4Net.Async.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Lucene.Net, Version=2.9.4.1, Culture=neutral, PublicKeyToken=85089178b9ac3181, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\Lucene.Net.2.9.4.1\lib\net40\Lucene.Net.dll</HintPath>
|
||||
@@ -82,8 +88,8 @@
|
||||
<Reference Include="Moq, Version=4.1.1309.919, Culture=neutral, PublicKeyToken=69f491c39445e920, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\Moq.4.1.1309.0919\lib\net40\Moq.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Newtonsoft.Json, Version=9.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\Newtonsoft.Json.9.0.1\lib\net45\Newtonsoft.Json.dll</HintPath>
|
||||
<Reference Include="Newtonsoft.Json, Version=10.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\Newtonsoft.Json.10.0.2\lib\net45\Newtonsoft.Json.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="nunit.framework, Version=2.6.2.12296, Culture=neutral, PublicKeyToken=96d09a1eb7f44a77, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\NUnit.2.6.2\lib\nunit.framework.dll</HintPath>
|
||||
@@ -162,7 +168,7 @@
|
||||
<Compile Include="Issues\U9560.cs" />
|
||||
<Compile Include="Collections\OrderedHashSetTests.cs" />
|
||||
<Compile Include="IO\ShadowFileSystemTests.cs" />
|
||||
<Compile Include="Logging\ConsoleLogger.cs" />
|
||||
<Compile Include="TestHelpers\ConsoleLogger.cs" />
|
||||
<Compile Include="Migrations\CreateTableMigrationTests.cs" />
|
||||
<Compile Include="Migrations\MigrationIssuesTests.cs" />
|
||||
<Compile Include="Persistence\LocksTests.cs" />
|
||||
@@ -204,9 +210,6 @@
|
||||
<Compile Include="Collections\DeepCloneableListTests.cs" />
|
||||
<Compile Include="Web\Controllers\BackOfficeControllerUnitTests.cs" />
|
||||
<Compile Include="DelegateExtensionsTests.cs" />
|
||||
<Compile Include="Logging\AsyncRollingFileAppenderTest.cs" />
|
||||
<Compile Include="Logging\DebugAppender.cs" />
|
||||
<Compile Include="Logging\ParallelForwarderTest.cs" />
|
||||
<Compile Include="Web\Mvc\RenderIndexActionSelectorAttributeTests.cs" />
|
||||
<Compile Include="Persistence\Repositories\AuditRepositoryTest.cs" />
|
||||
<Compile Include="Persistence\Repositories\DomainRepositoryTest.cs" />
|
||||
@@ -484,7 +487,6 @@
|
||||
<Compile Include="PublishedContent\PublishedContentMoreTests.cs" />
|
||||
<Compile Include="Publishing\PublishingStrategyTests.cs" />
|
||||
<Compile Include="Resolvers\ActionsResolverTests.cs" />
|
||||
<Compile Include="Logging\RingBufferTest.cs" />
|
||||
<Compile Include="TestHelpers\BaseUmbracoConfigurationTest.cs" />
|
||||
<Compile Include="TestHelpers\DatabaseTestBehaviorAttribute.cs" />
|
||||
<Compile Include="TestHelpers\Entities\MockedMember.cs" />
|
||||
|
||||
@@ -2,8 +2,10 @@
|
||||
<packages>
|
||||
<package id="AspNetWebApi.SelfHost" version="4.0.20710.0" targetFramework="net45" />
|
||||
<package id="AutoMapper" version="3.3.1" targetFramework="net45" />
|
||||
<package id="Castle.Core" version="4.0.0" targetFramework="net45" />
|
||||
<package id="Examine" version="0.1.82" targetFramework="net45" />
|
||||
<package id="log4net" version="2.0.5" targetFramework="net45" />
|
||||
<package id="log4net" version="2.0.8" targetFramework="net45" />
|
||||
<package id="Log4Net.Async" version="2.0.4" targetFramework="net45" />
|
||||
<package id="Lucene.Net" version="2.9.4.1" targetFramework="net45" />
|
||||
<package id="Microsoft.AspNet.Mvc" version="5.2.3" targetFramework="net45" />
|
||||
<package id="Microsoft.AspNet.Razor" version="3.2.3" targetFramework="net45" />
|
||||
@@ -17,15 +19,15 @@
|
||||
<package id="Microsoft.Web.Infrastructure" version="1.0.0.0" targetFramework="net45" />
|
||||
<package id="MiniProfiler" version="2.1.0" targetFramework="net45" />
|
||||
<package id="Moq" version="4.1.1309.0919" targetFramework="net45" />
|
||||
<package id="Newtonsoft.Json" version="9.0.1" targetFramework="net462" />
|
||||
<package id="Newtonsoft.Json" version="10.0.2" targetFramework="net45" />
|
||||
<package id="NUnit" version="2.6.2" targetFramework="net45" />
|
||||
<package id="Owin" version="1.0" targetFramework="net45" />
|
||||
<package id="Selenium.WebDriver" version="2.32.0" targetFramework="net45" />
|
||||
<package id="Semver" version="2.0.4" targetFramework="net45" />
|
||||
<package id="SharpZipLib" version="0.86.0" targetFramework="net45" />
|
||||
<package id="SqlServerCE" version="4.0.0.1" targetFramework="net45" />
|
||||
<package id="System.Runtime" version="4.1.0" targetFramework="net45" />
|
||||
<package id="System.Runtime.Extensions" version="4.1.0" targetFramework="net45" />
|
||||
<package id="System.Runtime.InteropServices" version="4.1.0" targetFramework="net45" />
|
||||
<package id="System.Text.RegularExpressions" version="4.1.0" targetFramework="net45" />
|
||||
<package id="System.Runtime" version="4.3.0" targetFramework="net45" />
|
||||
<package id="System.Runtime.Extensions" version="4.3.0" targetFramework="net45" />
|
||||
<package id="System.Runtime.InteropServices" version="4.3.0" targetFramework="net45" />
|
||||
<package id="System.Text.RegularExpressions" version="4.3.0" targetFramework="net45" />
|
||||
</packages>
|
||||
@@ -536,7 +536,23 @@ module.exports = function (grunt) {
|
||||
]
|
||||
},
|
||||
'ace-builds': {
|
||||
files: ['src-min-noconflict/**']
|
||||
files: [
|
||||
'src-min-noconflict/ace.js',
|
||||
|
||||
'src-min-noconflict/ext-language_tools.js',
|
||||
'src-min-noconflict/ext-searchbox.js',
|
||||
'src-min-noconflict/ext-settings_menu.js',
|
||||
|
||||
'src-min-noconflict/snippets/text.js',
|
||||
'src-min-noconflict/snippets/javascript.js',
|
||||
|
||||
'src-min-noconflict/theme-chrome.js',
|
||||
|
||||
'src-min-noconflict/mode-razor.js',
|
||||
'src-min-noconflict/mode-javascript.js',
|
||||
|
||||
'src-min-noconflict/worker-javascript.js',
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
body.mce-content-body {
|
||||
background-color: #fff;
|
||||
font-family: Verdana,Arial,Helvetica,sans-serif;
|
||||
font-size: 11px;
|
||||
font-size: 14px;
|
||||
line-height: 1.5em;
|
||||
scrollbar-3dlight-color: #f0f0ee;
|
||||
scrollbar-arrow-color: #676662;
|
||||
scrollbar-base-color: #f0f0ee;
|
||||
|
||||
@@ -92,6 +92,16 @@ function contentTypeResource($q, $http, umbRequestHelper, umbDataFormatter) {
|
||||
'Failed to retrieve property type aliases');
|
||||
},
|
||||
|
||||
getAllStandardFields: function () {
|
||||
|
||||
return umbRequestHelper.resourcePromise(
|
||||
$http.get(
|
||||
umbRequestHelper.getApiUrl(
|
||||
"contentTypeApiBaseUrl",
|
||||
"GetAllStandardFields")),
|
||||
'Failed to retrieve standard fields');
|
||||
},
|
||||
|
||||
getPropertyTypeScaffold : function (id) {
|
||||
return umbRequestHelper.resourcePromise(
|
||||
$http.get(
|
||||
|
||||
@@ -62,14 +62,14 @@ function macroResource($q, $http, umbRequestHelper) {
|
||||
* @param {} filename
|
||||
* @returns {}
|
||||
*/
|
||||
createPartialViewMacroWithFile: function(parent, filename) {
|
||||
createPartialViewMacroWithFile: function(virtualPath, filename) {
|
||||
|
||||
return umbRequestHelper.resourcePromise(
|
||||
$http.post(
|
||||
umbRequestHelper.getApiUrl(
|
||||
"macroApiBaseUrl",
|
||||
"CreatePartialViewMacroWithFile"), {
|
||||
parent: parent,
|
||||
virtualPath: virtualPath,
|
||||
filename: filename
|
||||
}
|
||||
),
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
margin-bottom: @baseLineHeight;
|
||||
background-color: @warningBackground;
|
||||
border: 1px solid @warningBorder;
|
||||
.border-radius(@baseBorderRadius);
|
||||
.border-radius(@alertBorderRadius);
|
||||
}
|
||||
.alert,
|
||||
.alert h4,
|
||||
|
||||
@@ -65,14 +65,11 @@
|
||||
-webkit-box-shadow:none;
|
||||
}
|
||||
|
||||
.btn-group > .btn:first-child,
|
||||
.btn-group > .btn:last-child,
|
||||
.btn-group > .dropdown-toggle {
|
||||
border-radius: 0;
|
||||
.btn-group .btn.dropdown-toggle {
|
||||
border-left-width: 1px;
|
||||
border-left-style: solid;
|
||||
}
|
||||
|
||||
|
||||
|
||||
// Button Sizes
|
||||
// --------------------------------------------------
|
||||
|
||||
|
||||
@@ -14,6 +14,7 @@ body {
|
||||
overflow: hidden;
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
width: ~"(calc(~'100%' - ~'80px'))"; // 80px is the fixed left menu for toggling the different browser sizes
|
||||
position: absolute;
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
.umb-button-group__toggle {
|
||||
padding-left: 8px;
|
||||
padding-right: 8px;
|
||||
margin-left: -1px;
|
||||
}
|
||||
|
||||
.umb-button-group__sub-buttons.-align-right {
|
||||
@@ -35,6 +34,9 @@
|
||||
padding-right: 10px;
|
||||
padding-left: 10px;
|
||||
border-radius: 0 3px 3px 0;
|
||||
border-left-style: solid;
|
||||
border-left-width: 1px;
|
||||
border-left-color: rgba(0,0,0,0.1);
|
||||
}
|
||||
|
||||
.umb-era-button.umb-button-group__toggle .caret {
|
||||
|
||||
@@ -47,8 +47,8 @@
|
||||
border-radius: 3px;
|
||||
padding: 10px;
|
||||
img {
|
||||
max-width: 50vw;
|
||||
max-height: 70vh;
|
||||
max-width: 80vw;
|
||||
max-height: 80vh;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
.umb-panel-header {
|
||||
padding: 20px;
|
||||
background: @gray-10;
|
||||
border-bottom: 1px solid @gray-8;
|
||||
border-bottom: 1px solid @purple-l3;
|
||||
height: 59px;
|
||||
|
||||
.umb-headline {
|
||||
@@ -25,9 +25,14 @@
|
||||
|
||||
.umb-panel-footer {
|
||||
background: @gray-10;
|
||||
border-top: 1px solid @gray-8;
|
||||
height: 51px;
|
||||
border-top: 1px solid @purple-l3;
|
||||
height: 52px;
|
||||
padding: 0 20px;
|
||||
}
|
||||
|
||||
// Hacks to fix editors inside the mini editors
|
||||
.umb-editor-sub-header {
|
||||
margin-top: 0;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -99,6 +99,12 @@
|
||||
}
|
||||
}
|
||||
|
||||
.forms-install-button {
|
||||
.btn {
|
||||
padding: 14px 40px;
|
||||
}
|
||||
}
|
||||
|
||||
.installer-top {
|
||||
overflow: hidden;
|
||||
margin: 0 auto 30px;
|
||||
|
||||
@@ -73,7 +73,7 @@ body {
|
||||
right: 0;
|
||||
left: 0;
|
||||
bottom: 0;
|
||||
background: @gray-1;
|
||||
background: @purple-d2;
|
||||
z-index: 666;
|
||||
}
|
||||
|
||||
|
||||
@@ -4,9 +4,6 @@
|
||||
.login-overlay {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background: @gray-1 url(../img/application/logo.png) no-repeat 25px 30px fixed !important;
|
||||
background-size: 30px 30px !important;
|
||||
color: @white;
|
||||
position: absolute;
|
||||
z-index: 10000;
|
||||
top: 0;
|
||||
@@ -16,34 +13,24 @@
|
||||
border: none;
|
||||
border-radius: 0;
|
||||
overflow-y: auto;
|
||||
background-color: @purple-d2;
|
||||
}
|
||||
|
||||
|
||||
@media only screen and (-webkit-min-device-pixel-ratio: 1.5),
|
||||
only screen and (min-resolution: 144dpi)
|
||||
{
|
||||
.login-overlay {
|
||||
background-image: url(../img/application/logo@2x.png) !important;
|
||||
}
|
||||
.login-overlay__background-image {
|
||||
background-position: center center;
|
||||
background-repeat: no-repeat;
|
||||
background-size: cover;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
position: absolute;
|
||||
opacity: 0.05;
|
||||
}
|
||||
|
||||
|
||||
@media only screen and (-webkit-min-device-pixel-ratio: 2),
|
||||
only screen and (min-resolution: 192dpi)
|
||||
{
|
||||
.login-overlay {
|
||||
background-image: url(../img/application/logo@2x.png) !important;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@media only screen and (-webkit-min-device-pixel-ratio: 3),
|
||||
only screen and (min-resolution: 3dppx),
|
||||
only screen and (min-resolution: 350dpi)
|
||||
{
|
||||
.login-overlay {
|
||||
background-image: url(../img/application/logo@3x.png) !important;
|
||||
}
|
||||
.login-overlay__logo {
|
||||
position: absolute;
|
||||
top: 22px;
|
||||
left: 25px;
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
.login-overlay .umb-modalcolumn {
|
||||
@@ -51,21 +38,57 @@
|
||||
border: none;
|
||||
}
|
||||
|
||||
.login-overlay .umb-login-container {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
position: relative;
|
||||
z-index: 3;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
@media (max-width: 565px) {
|
||||
// making sure we don't crash into the logo
|
||||
.login-overlay .umb-login-container {
|
||||
padding-top: 80px;
|
||||
}
|
||||
}
|
||||
|
||||
.login-overlay .form {
|
||||
position:relative;
|
||||
display: block;
|
||||
top: 100px;
|
||||
left: 165px;
|
||||
width: 370px;
|
||||
text-align: right;
|
||||
background: @white;
|
||||
padding: 25px;
|
||||
width: 500px;
|
||||
margin-left: 25px;
|
||||
margin-right: 25px;
|
||||
margin-top: auto;
|
||||
margin-bottom: auto;
|
||||
}
|
||||
|
||||
.login-overlay .form input[type="text"],
|
||||
.login-overlay .form input[type="password"],
|
||||
.login-overlay .form input[type="email"] {
|
||||
height: 36px;
|
||||
padding-left: 10px;
|
||||
padding-right: 10px;
|
||||
}
|
||||
|
||||
.login-overlay .btn-success {
|
||||
padding: 12px 24px;
|
||||
}
|
||||
|
||||
.login-overlay .form label {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.login-overlay h1 {
|
||||
display: block;
|
||||
text-align: right;
|
||||
color: @white;
|
||||
font-size: 18px;
|
||||
text-align: center;
|
||||
color: @black;
|
||||
font-size: 24px;
|
||||
font-weight: bold;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
.login-overlay .alert {
|
||||
@@ -76,62 +99,19 @@
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.login-overlay .switch-view {
|
||||
margin-top: 10px;
|
||||
.login-overlay .external-logins form {
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
@media (max-width: 767px) and (max-height: 420px) and (orientation: landscape) {
|
||||
// Move form closer to top on narrow screen sizes
|
||||
.login-overlay .form {
|
||||
top: 50px;
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 565px) {
|
||||
// Remove padding on login-form on smaller devices
|
||||
.login-overlay .form {
|
||||
top: 60px;
|
||||
right: 25px;
|
||||
left: inherit;
|
||||
padding-left: 25px;
|
||||
padding-right:25px;
|
||||
width: auto;
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 339px) {
|
||||
.login-overlay .form {
|
||||
input[type="text"], input[type="password"] {
|
||||
width: 250px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#hrOr {
|
||||
height: 30px;
|
||||
text-align: center;
|
||||
position: relative;
|
||||
padding-top: 20px;
|
||||
}
|
||||
|
||||
#hrOr hr {
|
||||
.login-overlay .btn-social {
|
||||
padding-top: 8px;
|
||||
padding-bottom: 8px;
|
||||
margin: 0;
|
||||
border: none;
|
||||
background-color: @gray-3;
|
||||
height: 1px;
|
||||
margin-bottom: 5px;
|
||||
}
|
||||
|
||||
#hrOr div {
|
||||
background-color: @black;
|
||||
position: relative;
|
||||
top: -16px;
|
||||
border: 1px solid @gray-3;
|
||||
padding: 4px;
|
||||
border-radius: 50%;
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
margin: auto;
|
||||
color: @gray-8;
|
||||
.login-overlay .btn-social>:first-child {
|
||||
line-height: 36px;
|
||||
}
|
||||
|
||||
.login-overlay .text-error,
|
||||
|
||||
@@ -42,6 +42,7 @@
|
||||
@turquoise-l3: #C0F0ED;
|
||||
@turquoise-washed: #F3FDFC;
|
||||
|
||||
@purple-d2: #1D1333;
|
||||
@purple-d1: #2E2246;
|
||||
@purple: #413659;
|
||||
@purple-l1: #675E7A;
|
||||
@@ -57,6 +58,7 @@
|
||||
@red-l3: #FFB2B0;
|
||||
@red-washed: #FFECEB;
|
||||
|
||||
@yellow-d2: #F0AC00;
|
||||
@yellow-d1: #FFC011;
|
||||
@yellow: #FFCE38;
|
||||
@yellow-l1: #FFD861;
|
||||
@@ -141,9 +143,9 @@
|
||||
|
||||
|
||||
// Disabled this to keep consistency throughout the backoffice UI. Untill a better solution is thought up, this will do.
|
||||
@baseBorderRadius: 0px; // 2px;
|
||||
@borderRadiusLarge: 0px; // 6px;
|
||||
@borderRadiusSmall: 0px; // 3px;
|
||||
@baseBorderRadius: 3px; // 2px;
|
||||
@borderRadiusLarge: 3px; // 6px;
|
||||
@borderRadiusSmall: 3px; // 3px;
|
||||
|
||||
|
||||
// Tables
|
||||
@@ -185,7 +187,7 @@
|
||||
// -------------------------
|
||||
@inputBackground: @white;
|
||||
@inputBorder: @gray-7;
|
||||
@inputBorderRadius: @baseBorderRadius;
|
||||
@inputBorderRadius: 0;
|
||||
@inputDisabledBackground: @gray-10;
|
||||
@formActionsBackground: @gray-9;
|
||||
@inputHeight: @baseLineHeight + 10px; // base line-height + 8px vertical padding + 2px top/bottom border
|
||||
@@ -195,7 +197,7 @@
|
||||
// Tabs
|
||||
// -------------------------
|
||||
|
||||
@tabsBorderRadius: 0px;
|
||||
@tabsBorderRadius: @baseBorderRadius;
|
||||
|
||||
// Dropdowns
|
||||
// -------------------------
|
||||
@@ -311,7 +313,7 @@
|
||||
// alerts
|
||||
// -------------------------
|
||||
@warningText: @white;
|
||||
@warningBackground: @orange;
|
||||
@warningBackground: @yellow-d2;
|
||||
@warningBorder: transparent;
|
||||
|
||||
@errorText: @white;
|
||||
@@ -326,6 +328,8 @@
|
||||
@infoBackground: @turquoise-d1;
|
||||
@infoBorder: transparent;
|
||||
|
||||
@alertBorderRadius: 0;
|
||||
|
||||
// SD: Had to duplicate the above but prefix with 'form' inversed colors
|
||||
// because we cannot share the above alert colors with forms otherwise we end up with white
|
||||
// text and giant red backgrounds.
|
||||
|
||||
@@ -81,6 +81,7 @@
|
||||
$scope.externalLoginProviders = externalLoginInfo.providers;
|
||||
$scope.externalLoginInfo = externalLoginInfo;
|
||||
$scope.resetPasswordCodeInfo = resetPasswordCodeInfo;
|
||||
$scope.backgroundImage = Umbraco.Sys.ServerVariables.umbracoSettings.loginBackgroundImage;
|
||||
|
||||
$scope.activateKonamiMode = function () {
|
||||
if ($cookies.konamiLogin == "1") {
|
||||
|
||||
@@ -1,133 +1,146 @@
|
||||
<div ng-controller="Umbraco.Dialogs.LoginController">
|
||||
|
||||
<div id="login" class="umb-modalcolumn umb-dialog" ng-class="{'show-validation': loginForm.$invalid}" ng-cloak konami-code="activateKonamiMode()">
|
||||
<div class="form">
|
||||
<h1>{{greeting}}</h1>
|
||||
|
||||
<div class="login-overlay__background-image" ng-if="backgroundImage" ng-style="{'background-image':'url(' + backgroundImage + ')'}"></div>
|
||||
|
||||
<div ng-show="view == 'login'">
|
||||
<div class="login-overlay__logo">
|
||||
<img ng-src="assets/img/application/logo.png" ng-srcset="assets/img/application/logo@2x.png 2x, assets/img/application/logo@3x.png 3x">
|
||||
</div>
|
||||
|
||||
<p>
|
||||
<span ng-show="dialogData.isTimedOut"><localize key="login_timeout">Log in below</localize>.</span>
|
||||
<localize key="login_instruction">Log in below</localize>
|
||||
</p>
|
||||
<div class="umb-login-container">
|
||||
|
||||
<div class="external-logins" ng-if="externalLoginProviders.length > 0">
|
||||
<div class="form">
|
||||
<h1>{{greeting}}</h1>
|
||||
|
||||
<div class="text-error" ng-repeat="error in externalLoginInfo.errors">
|
||||
<div ng-show="view == 'login'">
|
||||
|
||||
<p>
|
||||
<span ng-show="dialogData.isTimedOut"><localize key="login_timeout">Log in below</localize>.</span>
|
||||
</p>
|
||||
|
||||
<div class="external-logins" ng-if="externalLoginProviders.length > 0">
|
||||
|
||||
<div class="text-error" ng-repeat="error in externalLoginInfo.errors">
|
||||
<span>{{error}}</span>
|
||||
</div>
|
||||
|
||||
<form method="POST" name="externalLoginForm" action="{{externalLoginFormAction}}">
|
||||
|
||||
<div ng-repeat="login in externalLoginProviders">
|
||||
|
||||
<button type="submit" class="btn btn-block btn-social"
|
||||
ng-class="login.properties.SocialStyle"
|
||||
id="{{login.authType}}" name="provider" value="{{login.authType}}"
|
||||
title="Log in using your {{login.caption}} account">
|
||||
<i class="fa" ng-class="login.properties.SocialIcon"></i>
|
||||
<localize key="login_signInWith">Sign in with</localize> {{login.caption}}
|
||||
</button>
|
||||
|
||||
</div>
|
||||
</form>
|
||||
|
||||
</div>
|
||||
|
||||
<form method="POST" name="loginForm" ng-submit="loginSubmit(login, password)">
|
||||
|
||||
<div class="control-group" ng-show="loginForm.$invalid">
|
||||
<div class="text-error">{{errorMsg}}</div>
|
||||
</div>
|
||||
|
||||
<div class="control-group" ng-class="{error: loginForm.username.$invalid}">
|
||||
<label><localize key="general_username">Username</localize></label>
|
||||
<input type="text" ng-model="login" name="username" class="-full-width-input" localize="placeholder" placeholder="@placeholders_username" />
|
||||
</div>
|
||||
|
||||
<div class="control-group" ng-class="{error: loginForm.password.$invalid}">
|
||||
<label><localize key="general_password">Password</localize></label>
|
||||
<input type="password" ng-model="password" name="password" class="-full-width-input" localize="placeholder" placeholder="@placeholders_password" autocomplete="off" />
|
||||
</div>
|
||||
|
||||
<div class="flex justify-between items-center">
|
||||
<button type="submit" class="btn btn-success" val-trigger-change="#login .form input"><localize key="general_login">Login</localize></button>
|
||||
<div ng-show="allowPasswordReset">
|
||||
<a class="muted" style="text-decoration: underline;" href="#" prevent-default ng-click="showRequestPasswordReset()"><localize key="login_forgottenPassword">Forgotten password?</localize></a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<div ng-show="view == 'request-password-reset'">
|
||||
<p>
|
||||
<localize key="login_forgottenPasswordInstruction">An email will be sent to the address specified with a link to reset your password</localize>
|
||||
</p>
|
||||
|
||||
<form method="POST" name="requestPasswordResetForm" ng-submit="requestPasswordResetSubmit(email)">
|
||||
<div class="control-group" ng-class="{error: requestPasswordResetForm.email.$invalid}">
|
||||
<label><localize key="general_email">Email</localize></label>
|
||||
<input type="email" ng-model="email" name="email" class="-full-width-input" localize="placeholder" placeholder="@placeholders_email" />
|
||||
</div>
|
||||
|
||||
<div class="control-group" ng-show="requestPasswordResetForm.$invalid">
|
||||
<div class="text-error">{{errorMsg}}</div>
|
||||
</div>
|
||||
|
||||
<div class="control-group" ng-show="showEmailResetConfirmation">
|
||||
<div class="text-info">
|
||||
<localize key="login_requestPasswordResetConfirmation">An email with password reset instructions will be sent to the specified address if it matched our records</localize>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="flex justify-between items-center">
|
||||
<button type="submit" class="btn btn-success" val-trigger-change="#login .form input"><localize key="general_submit">Submit</localize></button>
|
||||
<a class="muted" href="#" prevent-default ng-click="showLogin()" style="text-decoration: underline;"><localize key="login_returnToLogin">Return to login form</localize></a>
|
||||
</div>
|
||||
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<div ng-show="view == 'set-password'">
|
||||
|
||||
<p ng-hide="resetComplete">
|
||||
<localize key="login_setPasswordInstruction">Please provide a new password.</localize>
|
||||
</p>
|
||||
|
||||
<form method="POST" name="setPasswordForm" ng-submit="setPasswordSubmit(password, confirmPassword)">
|
||||
|
||||
<div ng-hide="resetComplete" class="control-group" ng-class="{error: setPasswordForm.password.$invalid}">
|
||||
<label><localize key="user_newPassword">New password</localize></label>
|
||||
<input type="password" ng-model="password" name="password" class="-full-width-input" localize="placeholder" placeholder="@placeholders_password" />
|
||||
</div>
|
||||
|
||||
<div ng-hide="resetComplete" class="control-group" ng-class="{error: setPasswordForm.confirmPassword.$invalid}">
|
||||
<label><localize key="user_confirmNewPassword">Confirm new password</localize></label>
|
||||
<input type="password" ng-model="confirmPassword" name="confirmPassword" class="-full-width-input" localize="placeholder" placeholder="@placeholders_confirmPassword" />
|
||||
</div>
|
||||
|
||||
<div ng-hide="resetComplete" class="control-group" ng-show="setPasswordForm.$invalid">
|
||||
<div class="text-error">{{errorMsg}}</div>
|
||||
</div>
|
||||
|
||||
<div class="control-group" ng-show="showSetPasswordConfirmation">
|
||||
<div class="text-info">
|
||||
<localize key="login_setPasswordConfirmation">Your new password has been set and you may now use it to log in.</localize>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="flex justify-between items-center">
|
||||
<button ng-hide="resetComplete" type="submit" class="btn btn-success" val-trigger-change="#login .form input"><localize key="general_submit">Submit</localize></button>
|
||||
<a class="muted" href="#" prevent-default ng-click="showLogin()"><localize key="login_returnToLogin">Return to login form</localize></a>
|
||||
</div>
|
||||
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<div ng-show="view == 'password-reset-code-expired'">
|
||||
<div class="text-error" ng-repeat="error in resetPasswordCodeInfo.errors">
|
||||
<span>{{error}}</span>
|
||||
</div>
|
||||
|
||||
<form method="POST" name="externalLoginForm" action="{{externalLoginFormAction}}">
|
||||
|
||||
<div ng-repeat="login in externalLoginProviders">
|
||||
|
||||
<button type="submit" class="btn btn-block btn-social"
|
||||
ng-class="login.properties.SocialStyle"
|
||||
id="{{login.authType}}" name="provider" value="{{login.authType}}"
|
||||
title="Log in using your {{login.caption}} account">
|
||||
<i class="fa" ng-class="login.properties.SocialIcon"></i>
|
||||
<localize key="login_signInWith">Sign in with</localize> {{login.caption}}
|
||||
</button>
|
||||
|
||||
</div>
|
||||
</form>
|
||||
|
||||
<div id="hrOr">
|
||||
<hr />
|
||||
<div><localize key="general_or">or</localize></div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<form method="POST" name="loginForm" ng-submit="loginSubmit(login, password)">
|
||||
<div class="control-group" ng-class="{error: loginForm.username.$invalid}">
|
||||
<input type="text" ng-model="login" name="username" class="input-xlarge input--no-border" localize="placeholder" placeholder="@placeholders_username" />
|
||||
</div>
|
||||
|
||||
<div class="control-group" ng-class="{error: loginForm.password.$invalid}">
|
||||
<input type="password" ng-model="password" name="password" class="input-xlarge input--no-border" localize="placeholder" placeholder="@placeholders_password" autocomplete="off" />
|
||||
</div>
|
||||
|
||||
<div class="control-group" ng-show="loginForm.$invalid">
|
||||
<div class="text-error">{{errorMsg}}</div>
|
||||
</div>
|
||||
|
||||
<button type="submit" class="btn" val-trigger-change="#login .form input"><localize key="general_login">Login</localize></button>
|
||||
|
||||
<div class="switch-view" ng-show="allowPasswordReset">
|
||||
<a class="muted" href="#" prevent-default ng-click="showRequestPasswordReset()"><localize key="login_forgottenPassword">Forgotten password?</localize></a>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<div ng-show="view == 'request-password-reset'">
|
||||
<p>
|
||||
<localize key="login_forgottenPasswordInstruction">An email will be sent to the address specified with a link to reset your password</localize>
|
||||
</p>
|
||||
|
||||
<form method="POST" name="requestPasswordResetForm" ng-submit="requestPasswordResetSubmit(email)">
|
||||
<div class="control-group" ng-class="{error: requestPasswordResetForm.email.$invalid}">
|
||||
<input type="text" ng-model="email" name="email" class="input-xlarge input--no-border" localize="placeholder" placeholder="@placeholders_email" />
|
||||
</div>
|
||||
|
||||
<div class="control-group" ng-show="requestPasswordResetForm.$invalid">
|
||||
<div class="text-error">{{errorMsg}}</div>
|
||||
</div>
|
||||
|
||||
<div class="control-group" ng-show="showEmailResetConfirmation">
|
||||
<div class="text-info">
|
||||
<localize key="login_requestPasswordResetConfirmation">An email with password reset instructions will be sent to the specified address if it matched our records</localize>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<button type="submit" class="btn" val-trigger-change="#login .form input"><localize key="general_submit">Submit</localize></button>
|
||||
|
||||
<div class="switch-view">
|
||||
<a class="muted" href="#" prevent-default ng-click="showLogin()"><localize key="login_returnToLogin">Return to login form</localize></a>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<div ng-show="view == 'set-password'">
|
||||
|
||||
<p ng-hide="resetComplete">
|
||||
<localize key="login_setPasswordInstruction">Please provide a new password.</localize>
|
||||
</p>
|
||||
|
||||
<form method="POST" name="setPasswordForm" ng-submit="setPasswordSubmit(password, confirmPassword)">
|
||||
|
||||
<div ng-hide="resetComplete" class="control-group" ng-class="{error: setPasswordForm.password.$invalid}">
|
||||
<input type="password" ng-model="password" name="password" class="input-xlarge" localize="placeholder" placeholder="@placeholders_password" />
|
||||
</div>
|
||||
|
||||
<div ng-hide="resetComplete" class="control-group" ng-class="{error: setPasswordForm.confirmPassword.$invalid}">
|
||||
<input type="password" ng-model="confirmPassword" name="confirmPassword" class="input-xlarge" localize="placeholder" placeholder="@placeholders_confirmPassword" />
|
||||
</div>
|
||||
|
||||
<div ng-hide="resetComplete" class="control-group" ng-show="setPasswordForm.$invalid">
|
||||
<div class="text-error">{{errorMsg}}</div>
|
||||
</div>
|
||||
|
||||
<div class="control-group" ng-show="showSetPasswordConfirmation">
|
||||
<div class="text-info">
|
||||
<localize key="login_setPasswordConfirmation">Your new password has been set and you may now use it to log in.</localize>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<button ng-hide="resetComplete" type="submit" class="btn" val-trigger-change="#login .form input"><localize key="general_submit">Submit</localize></button>
|
||||
|
||||
<div class="switch-view">
|
||||
<a class="muted" href="#" prevent-default ng-click="showLogin()"><localize key="login_returnToLogin">Return to login form</localize></a>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<div ng-show="view == 'password-reset-code-expired'">
|
||||
<div class="text-error" ng-repeat="error in resetPasswordCodeInfo.errors">
|
||||
<span>{{error}}</span>
|
||||
</div>
|
||||
|
||||
<div class="switch-view">
|
||||
<a class="muted" href="#" prevent-default ng-click="showLogin()"><localize key="login_returnToLogin">Return to login form</localize></a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -158,4 +158,4 @@
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</form>
|
||||
|
||||
@@ -80,6 +80,7 @@
|
||||
multiPicker: false,
|
||||
title: localizationService.localize("template_insertDictionaryItem"),
|
||||
description: localizationService.localize("template_insertDictionaryItemDesc"),
|
||||
emptyStateMessage: localizationService.localize("emptyStates_emptyDictionaryTree"),
|
||||
show: true,
|
||||
select: function(node){
|
||||
|
||||
|
||||
+6
@@ -12,6 +12,7 @@
|
||||
vm.insertAfter;
|
||||
vm.recursive = false;
|
||||
vm.properties = [];
|
||||
vm.standardFields = [];
|
||||
vm.date = false;
|
||||
vm.dateTime = false;
|
||||
vm.dateTimeSeparator = "";
|
||||
@@ -41,6 +42,11 @@
|
||||
contentTypeResource.getAllPropertyTypeAliases().then(function (array) {
|
||||
vm.properties = array;
|
||||
});
|
||||
|
||||
// Load all standard fields
|
||||
contentTypeResource.getAllStandardFields().then(function (array) {
|
||||
vm.standardFields = array;
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -5,7 +5,14 @@
|
||||
<div class="umb-el-wrap">
|
||||
<label class="control-label" for="chooseField">Choose field</label>
|
||||
<div class="controls">
|
||||
<select name="chooseField" ng-model="vm.field" ng-options="property for property in vm.properties"></select>
|
||||
<select ng-model="vm.field">
|
||||
<optgroup localize="label" label="@templateEditor_customFields">
|
||||
<option ng-repeat="(key, value) in vm.properties" value="{{value}}">{{value}}</option>
|
||||
</optgroup>
|
||||
<optgroup localize="label" label="@templateEditor_standardFields">
|
||||
<option ng-repeat="(key, value) in vm.standardFields" value="{{value}}">{{value}}</option>
|
||||
</optgroup>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -24,7 +31,14 @@
|
||||
<div class="umb-el-wrap">
|
||||
<label class="control-label" for="altField">Fallback field</label>
|
||||
<div class="controls">
|
||||
<select name="altField" ng-model="vm.altField" ng-options="property for property in vm.properties"></select>
|
||||
<select ng-model="vm.altField" >
|
||||
<optgroup localize="label" label="@templateEditor_customFields">
|
||||
<option ng-repeat="(key, value) in vm.properties" value="{{value}}">{{value}}</option>
|
||||
</optgroup>
|
||||
<optgroup localize="label" label="@templateEditor_standardFields">
|
||||
<option ng-repeat="(key, value) in vm.standardFields" value="{{value}}">{{value}}</option>
|
||||
</optgroup>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
+2
-1
@@ -61,6 +61,7 @@ angular.module("umbraco")
|
||||
|
||||
$scope.submitFolder = function() {
|
||||
if ($scope.newFolderName) {
|
||||
$scope.creatingFolder = true;
|
||||
mediaResource
|
||||
.addFolder($scope.newFolderName, $scope.currentFolder.id)
|
||||
.then(function(data) {
|
||||
@@ -69,7 +70,7 @@ angular.module("umbraco")
|
||||
cacheKey: "__media", //this is the main media tree cache key
|
||||
childrenOf: data.parentId //clear the children of the parent
|
||||
});
|
||||
|
||||
$scope.creatingFolder = false;
|
||||
$scope.gotoFolder(data);
|
||||
$scope.showFolderInput = false;
|
||||
$scope.newFolderName = "";
|
||||
|
||||
@@ -37,7 +37,7 @@
|
||||
|
||||
</div>
|
||||
|
||||
<div class="row umb-control-group" ng-if="!searchOptions.filter">
|
||||
<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>
|
||||
@@ -64,7 +64,7 @@
|
||||
focus-when="{{showFolderInput}}" />
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<div class="umb-loader" ng-if="creatingFolder"></div>
|
||||
</div>
|
||||
|
||||
<umb-file-dropzone
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user