diff --git a/README.md b/README.md index 5fb4cb868b..53070b6917 100644 --- a/README.md +++ b/README.md @@ -13,11 +13,11 @@ If you're interested in making changes to Belle make sure to read the [Belle Rea ## Umbraco - the simple, flexible and friendly ASP.NET CMS ## -**More than 177,000 sites trust Umbraco** +**More than 350,000 sites trust Umbraco** For the first time on the Microsoft platform, there is a free user and developer friendly CMS that makes it quick and easy to create websites - or a breeze to build complex web applications. Umbraco has award-winning integration capabilities and supports ASP.NET MVC or Web Forms, including User and Custom Controls, out of the box. It's a developer's dream and your users will love it too. -Used by more than 177,000 active websites including [http://daviscup.com](http://daviscup.com), [http://heinz.com](http://heinz.com), [http://peugeot.com](http://peugeot.com), [http://www.hersheys.com/](http://www.hersheys.com/) and **The Official ASP.NET and IIS.NET website from Microsoft** ([http://asp.net](http://asp.net) / [http://iis.net](http://iis.net)), you can be sure that the technology is proven, stable and scales. +Used by more than 350,000 active websites including [http://daviscup.com](http://daviscup.com), [http://heinz.com](http://heinz.com), [http://peugeot.com](http://peugeot.com), [http://www.hersheys.com/](http://www.hersheys.com/) and **The Official ASP.NET and IIS.NET website from Microsoft** ([http://asp.net](http://asp.net) / [http://iis.net](http://iis.net)), you can be sure that the technology is proven, stable and scales. To view more examples, please visit [http://umbraco.com/why-umbraco/#caseStudies](http://umbraco.com/why-umbraco/#caseStudies) diff --git a/build/NuSpecs/tools/trees.config.install.xdt b/build/NuSpecs/tools/trees.config.install.xdt index 580c619547..1a56c81271 100644 --- a/build/NuSpecs/tools/trees.config.install.xdt +++ b/build/NuSpecs/tools/trees.config.install.xdt @@ -41,7 +41,7 @@ - /// The GlobalSettings Class contains general settings information for the entire Umbraco instance based on information from web.config appsettings /// - internal class GlobalSettings + [Obsolete("TODO: Need to move this configuration class into the proper configuration accesors for v8!")] + public class GlobalSettings { #region Private static fields diff --git a/src/Umbraco.Core/Configuration/UmbracoSettings/ISecuritySection.cs b/src/Umbraco.Core/Configuration/UmbracoSettings/ISecuritySection.cs index c3a1df301d..c44c0cf0df 100644 --- a/src/Umbraco.Core/Configuration/UmbracoSettings/ISecuritySection.cs +++ b/src/Umbraco.Core/Configuration/UmbracoSettings/ISecuritySection.cs @@ -6,6 +6,8 @@ bool HideDisabledUsersInBackoffice { get; } + bool AllowPasswordReset { get; } + string AuthCookieName { get; } string AuthCookieDomain { get; } diff --git a/src/Umbraco.Core/Configuration/UmbracoSettings/SecurityElement.cs b/src/Umbraco.Core/Configuration/UmbracoSettings/SecurityElement.cs index 34642c8c90..f280b3e20c 100644 --- a/src/Umbraco.Core/Configuration/UmbracoSettings/SecurityElement.cs +++ b/src/Umbraco.Core/Configuration/UmbracoSettings/SecurityElement.cs @@ -28,6 +28,18 @@ namespace Umbraco.Core.Configuration.UmbracoSettings } } + [ConfigurationProperty("allowPasswordReset")] + internal InnerTextConfigurationElement AllowPasswordReset + { + get + { + return new OptionalInnerTextConfigurationElement( + (InnerTextConfigurationElement)this["allowPasswordReset"], + //set the default + true); + } + } + [ConfigurationProperty("authCookieName")] internal InnerTextConfigurationElement AuthCookieName { @@ -62,6 +74,11 @@ namespace Umbraco.Core.Configuration.UmbracoSettings get { return HideDisabledUsersInBackoffice; } } + bool ISecuritySection.AllowPasswordReset + { + get { return AllowPasswordReset; } + } + string ISecuritySection.AuthCookieName { get { return AuthCookieName; } diff --git a/src/Umbraco.Core/Constants-Applications.cs b/src/Umbraco.Core/Constants-Applications.cs index 38dc22c473..2feae59bad 100644 --- a/src/Umbraco.Core/Constants-Applications.cs +++ b/src/Umbraco.Core/Constants-Applications.cs @@ -106,13 +106,26 @@ public const string Xslt = "xslt"; public const string Languages = "languages"; + + public const string Macros = "macros"; /// /// alias for the user types tree. /// public const string UserTypes = "userTypes"; - //TODO: Fill in the rest! + /// + /// alias for the users tree. + /// + public const string Users = "users"; + + public const string Scripts = "scripts"; + + public const string PartialViews = "partialViews"; + + public const string PartialViewMacros = "partialViewMacros"; + + //TODO: Fill in the rest! } } diff --git a/src/Umbraco.Core/CoreBootManager.cs b/src/Umbraco.Core/CoreBootManager.cs index ba60925b11..eb9cc6903e 100644 --- a/src/Umbraco.Core/CoreBootManager.cs +++ b/src/Umbraco.Core/CoreBootManager.cs @@ -6,6 +6,7 @@ using System.Threading.Tasks; using System.Threading; using AutoMapper; using LightInject; +using NPoco; using Umbraco.Core.Cache; using Umbraco.Core.Configuration; using Umbraco.Core.Configuration.UmbracoSettings; @@ -40,19 +41,19 @@ namespace Umbraco.Core { /// - /// A bootstrapper for the Umbraco application which initializes all objects for the Core of the application + /// A bootstrapper for the Umbraco application which initializes all objects for the Core of the application /// /// /// This does not provide any startup functionality relating to web objects /// public class CoreBootManager : IBootManager { - + private ServiceContainer _appStartupEvtContainer; protected ProfilingLogger ProfilingLogger { get; private set; } private DisposableTimer _timer; protected PluginManager PluginManager { get; private set; } - + private bool _isInitialized = false; private bool _isStarted = false; @@ -76,7 +77,7 @@ namespace Umbraco.Core public CoreBootManager(UmbracoApplicationBase umbracoApplication) { if (umbracoApplication == null) throw new ArgumentNullException("umbracoApplication"); - _umbracoApplication = umbracoApplication; + _umbracoApplication = umbracoApplication; } internal CoreBootManager(UmbracoApplicationBase umbracoApplication, ProfilingLogger logger) @@ -91,7 +92,7 @@ namespace Umbraco.Core { if (_isInitialized) throw new InvalidOperationException("The boot manager has already been initialized"); - + //Create logger/profiler, and their resolvers, these are special resolvers that can be resolved before frozen so we can start logging LoggerResolver.Current = new LoggerResolver(_umbracoApplication.Logger) { CanResolveBeforeFrozen = true }; var profiler = CreateProfiler(); @@ -99,7 +100,7 @@ namespace Umbraco.Core ProfilingLogger = new ProfilingLogger(_umbracoApplication.Logger, profiler); ProfilingLogger = ProfilingLogger?? new ProfilingLogger(LoggerResolver.Current.Logger, ProfilerResolver.Current.Profiler); - + ApplicationCache = CreateApplicationCache(); _timer = ProfilingLogger.TraceDuration( @@ -112,26 +113,24 @@ namespace Umbraco.Core //TODO: this is currently a singleton but it would be better if it weren't. Unfortunately the only way to get // rid of this singleton would be to put it into IoC and then use the ServiceLocator pattern. PluginManager.Current = PluginManager = new PluginManager(ServiceProvider, ApplicationCache.RuntimeCache, ProfilingLogger, true); - + //build up core IoC servoces ConfigureCoreServices(Container); //set the singleton resolved from the core container ApplicationContext.Current = ApplicationContext = Container.GetInstance(); - //TODO: Remove these for v8! + //TODO: Remove these for v8! LegacyPropertyEditorIdToAliasConverter.CreateMappingsForCoreEditors(); LegacyParameterEditorAliasConverter.CreateMappingsForCoreEditors(); - //TODO: Make this as part of the db ctor! - Database.Mapper = new PetaPocoMapper(); - + //Create a 'child'container which is a copy of all of the current registrations and begin a sub scope for it // this child container will be used to manage the application event handler instances and the scope will be // completed at the end of the boot process to allow garbage collection _appStartupEvtContainer = Container.CreateChildContainer(); _appStartupEvtContainer.BeginScope(); _appStartupEvtContainer.RegisterCollection(PluginManager.ResolveApplicationStartupHandlers()); - + //build up standard IoC services ConfigureApplicationServices(Container); @@ -143,11 +142,11 @@ namespace Umbraco.Core { try { - using (ProfilingLogger.DebugDuration(string.Format("Executing {0} in ApplicationInitialized", x.GetType()))) - { - x.OnApplicationInitialized(UmbracoApplication, ApplicationContext); + using (ProfilingLogger.DebugDuration(string.Format("Executing {0} in ApplicationInitialized", x.GetType()))) + { + x.OnApplicationInitialized(UmbracoApplication, ApplicationContext); + } } - } catch (Exception ex) { ProfilingLogger.Logger.Error("An error occurred running OnApplicationInitialized for handler " + x.GetType(), ex); @@ -166,12 +165,12 @@ namespace Umbraco.Core internal virtual void ConfigureCoreServices(ServiceContainer container) { container.Register(factory => container); - + //Logging container.RegisterSingleton(factory => _umbracoApplication.Logger); container.RegisterSingleton(factory => ProfilingLogger.Profiler); container.RegisterSingleton(factory => ProfilingLogger); - + //Config container.RegisterFrom(); @@ -193,7 +192,7 @@ namespace Umbraco.Core container.RegisterSingleton(); container.Register(factory => FileSystemProviderManager.Current.GetFileSystemProvider()); - + } /// @@ -202,9 +201,9 @@ namespace Umbraco.Core /// internal virtual void ConfigureApplicationServices(ServiceContainer container) { - + } - + /// /// Creates the ApplicationCache based on a new instance of System.Web.Caching.Cache /// @@ -260,7 +259,7 @@ namespace Umbraco.Core } /// - /// Fires after initialization and calls the callback to allow for customizations to occur & + /// Fires after initialization and calls the callback to allow for customizations to occur & /// Ensure that the OnApplicationStarting methods of the IApplicationEvents are called /// /// @@ -275,11 +274,11 @@ namespace Umbraco.Core { try { - using (ProfilingLogger.DebugDuration(string.Format("Executing {0} in ApplicationStarting", x.GetType()))) - { - x.OnApplicationStarting(UmbracoApplication, ApplicationContext); + using (ProfilingLogger.DebugDuration(string.Format("Executing {0} in ApplicationStarting", x.GetType()))) + { + x.OnApplicationStarting(UmbracoApplication, ApplicationContext); + } } - } catch (Exception ex) { ProfilingLogger.Logger.Error("An error occurred running OnApplicationStarting for handler " + x.GetType(), ex); @@ -306,7 +305,7 @@ namespace Umbraco.Core { if (_isComplete) throw new InvalidOperationException("The boot manager has already been completed"); - + FreezeResolution(); //Here we need to make sure the db can be connected to @@ -318,16 +317,16 @@ namespace Umbraco.Core ((UserService) ApplicationContext.Services.UserService).IsUpgrading = true; - + //call OnApplicationStarting of each application events handler Parallel.ForEach(_appStartupEvtContainer.GetAllInstances(), x => { try { - using (ProfilingLogger.DebugDuration(string.Format("Executing {0} in ApplicationStarted", x.GetType()))) - { - x.OnApplicationStarted(UmbracoApplication, ApplicationContext); - } + using (ProfilingLogger.DebugDuration(string.Format("Executing {0} in ApplicationStarted", x.GetType()))) + { + x.OnApplicationStarted(UmbracoApplication, ApplicationContext); + } } catch (Exception ex) { @@ -445,7 +444,7 @@ namespace Umbraco.Core Container, ProfilingLogger.Logger, () => PluginManager.ResolveAssignedMapperTypes()); - + //RepositoryResolver.Current = new RepositoryResolver( // new RepositoryFactory(ApplicationCache)); @@ -469,7 +468,7 @@ namespace Umbraco.Core PluginManager.ResolveTypes()); // use the new DefaultShortStringHelper - ShortStringHelperResolver.Current = new ShortStringHelperResolver(Container, + ShortStringHelperResolver.Current = new ShortStringHelperResolver(Container, factory => new DefaultShortStringHelper(factory.GetInstance()).WithDefaultConfig()); UrlSegmentProviderResolver.Current = new UrlSegmentProviderResolver( diff --git a/src/Umbraco.Core/DatabaseContext.cs b/src/Umbraco.Core/DatabaseContext.cs index 1f00fb0df9..8f94c993ba 100644 --- a/src/Umbraco.Core/DatabaseContext.cs +++ b/src/Umbraco.Core/DatabaseContext.cs @@ -6,6 +6,7 @@ using System.Linq; using System.Web; using System.Web.Configuration; using System.Xml.Linq; +using NPoco; using Semver; using Umbraco.Core.Configuration; using Umbraco.Core.IO; @@ -789,5 +790,10 @@ namespace Umbraco.Core return true; } + + public Sql Sql() + { + return NPoco.Sql.BuilderFor(new SqlContext(SqlSyntax, Database)); + } } } \ No newline at end of file diff --git a/src/Umbraco.Core/DependencyInjection/RepositoryCompositionRoot.cs b/src/Umbraco.Core/DependencyInjection/RepositoryCompositionRoot.cs index 2d8e0109ec..f6ff4f1914 100644 --- a/src/Umbraco.Core/DependencyInjection/RepositoryCompositionRoot.cs +++ b/src/Umbraco.Core/DependencyInjection/RepositoryCompositionRoot.cs @@ -23,16 +23,20 @@ namespace Umbraco.Core.DependencyInjection { container.RegisterSingleton(factory => new DefaultDatabaseFactory(GlobalSettings.UmbracoConnectionName, factory.GetInstance())); container.RegisterSingleton(factory => GetDbContext(factory)); + container.RegisterSingleton(factory => SqlSyntaxProviders.CreateDefault(factory.GetInstance())); + container.Register(factory => factory.GetInstance().SqlSyntax); + container.RegisterSingleton(); - container.RegisterSingleton(factory => new PetaPocoUnitOfWorkProvider(factory.GetInstance())); + container.RegisterSingleton(factory => new NPocoUnitOfWorkProvider(factory.GetInstance())); + container.RegisterSingleton(factory => new MappingResolver( factory.GetInstance(), factory.GetInstance(), () => factory.GetInstance().ResolveAssignedMapperTypes())); container.Register(); - container.Register(factory => factory.GetInstance().SqlSyntax); container.RegisterSingleton(factory => CacheHelper.CreateDisabledCacheHelper(), "DisabledCache"); + container.RegisterSingleton(factory => new PhysicalFileSystem(SystemDirectories.Scripts), "ScriptFileSystem"); container.RegisterSingleton(factory => new PhysicalFileSystem(SystemDirectories.MvcViews + "/Partials/"), "PartialViewFileSystem"); container.RegisterSingleton(factory => new PhysicalFileSystem(SystemDirectories.MvcViews + "/MacroPartials/"), "PartialViewMacroFileSystem"); diff --git a/src/Umbraco.Core/EnumerableExtensions.cs b/src/Umbraco.Core/EnumerableExtensions.cs index 58d4d453b7..156831670a 100644 --- a/src/Umbraco.Core/EnumerableExtensions.cs +++ b/src/Umbraco.Core/EnumerableExtensions.cs @@ -20,9 +20,33 @@ namespace Umbraco.Core if (groupSize <= 0) throw new ArgumentException("Must be greater than zero.", "groupSize"); - return source - .Select((x, i) => Tuple.Create(i / groupSize, x)) - .GroupBy(t => t.Item1, t => t.Item2); + + // following code derived from MoreLinq and does not allocate bazillions of tuples + + T[] temp = null; + var count = 0; + + foreach (var item in source) + { + if (temp == null) temp = new T[groupSize]; + temp[count++] = item; + if (count != groupSize) continue; + yield return temp/*.Select(x => x)*/; + temp = null; + count = 0; + } + + if (temp != null && count > 0) + yield return temp.Take(count); + } + + public static IEnumerable SelectByGroups(this IEnumerable source, Func, IEnumerable> selector, int groupSize) + { + // don't want to use a SelectMany(x => x) here - isn't this better? + // ReSharper disable once LoopCanBeConvertedToQuery + foreach (var resultGroup in source.InGroupsOf(groupSize).Select(selector)) + foreach (var result in resultGroup) + yield return result; } /// The distinct by. @@ -287,7 +311,7 @@ namespace Umbraco.Core /// /// The logic for this is taken from: /// http://stackoverflow.com/questions/4576723/test-whether-two-ienumerablet-have-the-same-values-with-the-same-frequencies - /// + /// /// There's a few answers, this one seems the best for it's simplicity and based on the comment of Eamon /// public static bool UnsortedSequenceEqual(this IEnumerable source, IEnumerable other) @@ -301,5 +325,27 @@ namespace Umbraco.Core && list1Groups.All(g => g.Count() == list2Groups[g.Key].Count()); } + /// + /// Transforms an enumerable. + /// + /// + /// + /// + /// + public static IEnumerable Transform(this IEnumerable source, Func, IEnumerable> transform) + { + return transform(source); + } + + /// + /// Gets a null IEnumerable as an empty IEnumerable. + /// + /// + /// + /// + public static IEnumerable EmptyNull(this IEnumerable items) + { + return items ?? Enumerable.Empty(); + } } } diff --git a/src/Umbraco.Core/ListExtensions.cs b/src/Umbraco.Core/ListExtensions.cs new file mode 100644 index 0000000000..e639cbd5c7 --- /dev/null +++ b/src/Umbraco.Core/ListExtensions.cs @@ -0,0 +1,50 @@ +using System; +using System.Collections.Generic; + +namespace Umbraco.Core +{ + /// + /// Provides extensions to the List type. + /// + internal static class ListExtensions + { + // based upon the original Zip method + public static IEnumerable Zip(this IEnumerable e1, IEnumerable e2, IEnumerable e3, + Func resultSelector) + { + if (e1 == null) throw new ArgumentNullException("e1"); + if (e2 == null) throw new ArgumentNullException("e2"); + if (e3 == null) throw new ArgumentNullException("e3"); + if (resultSelector == null) throw new ArgumentNullException("resultSelector"); + return ZipIterator(e1, e2, e3, resultSelector); + } + + private static IEnumerable ZipIterator(IEnumerable ie1, IEnumerable ie2, IEnumerable ie3, + Func resultSelector) + { + var e1 = ie1.GetEnumerator(); + try + { + var e2 = ie2.GetEnumerator(); + var e3 = ie3.GetEnumerator(); + try + { + while (e1.MoveNext() && e2.MoveNext() && e3.MoveNext()) + yield return resultSelector(e1.Current, e2.Current, e3.Current); + } + finally + { + if (e2 != null) + e2.Dispose(); + if (e3 != null) + e3.Dispose(); + } + } + finally + { + if (e1 != null) + e1.Dispose(); + } + } + } +} diff --git a/src/Umbraco.Core/Models/Rdbms/AccessDto.cs b/src/Umbraco.Core/Models/Rdbms/AccessDto.cs index 37b1dbddd8..b9a512e027 100644 --- a/src/Umbraco.Core/Models/Rdbms/AccessDto.cs +++ b/src/Umbraco.Core/Models/Rdbms/AccessDto.cs @@ -2,6 +2,7 @@ using System.Collections; using System.Collections.Generic; using System.Security.AccessControl; +using NPoco; using Umbraco.Core.Persistence; using Umbraco.Core.Persistence.DatabaseAnnotations; using Umbraco.Core.Persistence.DatabaseModelDefinitions; @@ -9,7 +10,7 @@ using Umbraco.Core.Persistence.DatabaseModelDefinitions; namespace Umbraco.Core.Models.Rdbms { [TableName("umbracoAccess")] - [PrimaryKey("id", autoIncrement = false)] + [PrimaryKey("id", AutoIncrement = false)] [ExplicitColumns] internal class AccessDto { @@ -39,6 +40,7 @@ namespace Umbraco.Core.Models.Rdbms public DateTime UpdateDate { get; set; } [ResultColumn] + [Reference(ReferenceType.Many, ReferenceMemberName = "AccessId")] public List Rules { get; set; } } } \ No newline at end of file diff --git a/src/Umbraco.Core/Models/Rdbms/AccessRuleDto.cs b/src/Umbraco.Core/Models/Rdbms/AccessRuleDto.cs index 78e3444e56..07f9d4f175 100644 --- a/src/Umbraco.Core/Models/Rdbms/AccessRuleDto.cs +++ b/src/Umbraco.Core/Models/Rdbms/AccessRuleDto.cs @@ -1,4 +1,5 @@ using System; +using NPoco; using Umbraco.Core.Persistence; using Umbraco.Core.Persistence.DatabaseAnnotations; using Umbraco.Core.Persistence.DatabaseModelDefinitions; @@ -6,7 +7,7 @@ using Umbraco.Core.Persistence.DatabaseModelDefinitions; namespace Umbraco.Core.Models.Rdbms { [TableName("umbracoAccessRule")] - [PrimaryKey("id", autoIncrement = false)] + [PrimaryKey("id", AutoIncrement = false)] [ExplicitColumns] internal class AccessRuleDto { diff --git a/src/Umbraco.Core/Models/Rdbms/CacheInstructionDto.cs b/src/Umbraco.Core/Models/Rdbms/CacheInstructionDto.cs index c24004b7dc..182b8c67b3 100644 --- a/src/Umbraco.Core/Models/Rdbms/CacheInstructionDto.cs +++ b/src/Umbraco.Core/Models/Rdbms/CacheInstructionDto.cs @@ -1,4 +1,5 @@ using System; +using NPoco; using Umbraco.Core.Persistence; using Umbraco.Core.Persistence.DatabaseAnnotations; diff --git a/src/Umbraco.Core/Models/Rdbms/ContentDto.cs b/src/Umbraco.Core/Models/Rdbms/ContentDto.cs index eb9a66a7f2..8cef85b998 100644 --- a/src/Umbraco.Core/Models/Rdbms/ContentDto.cs +++ b/src/Umbraco.Core/Models/Rdbms/ContentDto.cs @@ -1,4 +1,5 @@ -using Umbraco.Core.Persistence; +using NPoco; +using Umbraco.Core.Persistence; using Umbraco.Core.Persistence.DatabaseAnnotations; namespace Umbraco.Core.Models.Rdbms @@ -22,6 +23,7 @@ namespace Umbraco.Core.Models.Rdbms public int ContentTypeId { get; set; } [ResultColumn] + [Reference(ReferenceType.OneToOne, ColumnName = "NodeId")] public NodeDto NodeDto { get; set; } } } \ No newline at end of file diff --git a/src/Umbraco.Core/Models/Rdbms/ContentType2ContentTypeDto.cs b/src/Umbraco.Core/Models/Rdbms/ContentType2ContentTypeDto.cs index 89773ef1ee..a4e5b6b71b 100644 --- a/src/Umbraco.Core/Models/Rdbms/ContentType2ContentTypeDto.cs +++ b/src/Umbraco.Core/Models/Rdbms/ContentType2ContentTypeDto.cs @@ -1,4 +1,5 @@ -using Umbraco.Core.Persistence; +using NPoco; +using Umbraco.Core.Persistence; using Umbraco.Core.Persistence.DatabaseAnnotations; namespace Umbraco.Core.Models.Rdbms diff --git a/src/Umbraco.Core/Models/Rdbms/ContentTypeAllowedContentTypeDto.cs b/src/Umbraco.Core/Models/Rdbms/ContentTypeAllowedContentTypeDto.cs index 91904437f0..9c101ffda4 100644 --- a/src/Umbraco.Core/Models/Rdbms/ContentTypeAllowedContentTypeDto.cs +++ b/src/Umbraco.Core/Models/Rdbms/ContentTypeAllowedContentTypeDto.cs @@ -1,10 +1,11 @@ -using Umbraco.Core.Persistence; +using NPoco; +using Umbraco.Core.Persistence; using Umbraco.Core.Persistence.DatabaseAnnotations; namespace Umbraco.Core.Models.Rdbms { [TableName("cmsContentTypeAllowedContentType")] - [PrimaryKey("Id", autoIncrement = false)] + [PrimaryKey("Id", AutoIncrement = false)] [ExplicitColumns] internal class ContentTypeAllowedContentTypeDto { @@ -22,6 +23,7 @@ namespace Umbraco.Core.Models.Rdbms public int SortOrder { get; set; } [ResultColumn] + [Reference(ReferenceType.OneToOne)] public ContentTypeDto ContentTypeDto { get; set; } } } \ No newline at end of file diff --git a/src/Umbraco.Core/Models/Rdbms/ContentTypeDto.cs b/src/Umbraco.Core/Models/Rdbms/ContentTypeDto.cs index 8d163abf44..483587cffc 100644 --- a/src/Umbraco.Core/Models/Rdbms/ContentTypeDto.cs +++ b/src/Umbraco.Core/Models/Rdbms/ContentTypeDto.cs @@ -1,4 +1,5 @@ -using Umbraco.Core.Persistence; +using NPoco; +using Umbraco.Core.Persistence; using Umbraco.Core.Persistence.DatabaseAnnotations; namespace Umbraco.Core.Models.Rdbms diff --git a/src/Umbraco.Core/Models/Rdbms/ContentTypeTemplateDto.cs b/src/Umbraco.Core/Models/Rdbms/ContentTypeTemplateDto.cs index 88ef02ea90..5ebd97319a 100644 --- a/src/Umbraco.Core/Models/Rdbms/ContentTypeTemplateDto.cs +++ b/src/Umbraco.Core/Models/Rdbms/ContentTypeTemplateDto.cs @@ -1,10 +1,11 @@ -using Umbraco.Core.Persistence; +using NPoco; +using Umbraco.Core.Persistence; using Umbraco.Core.Persistence.DatabaseAnnotations; namespace Umbraco.Core.Models.Rdbms { [TableName("cmsDocumentType")] - [PrimaryKey("contentTypeNodeId", autoIncrement = false)] + [PrimaryKey("contentTypeNodeId", AutoIncrement = false)] [ExplicitColumns] internal class ContentTypeTemplateDto { @@ -23,6 +24,7 @@ namespace Umbraco.Core.Models.Rdbms public bool IsDefault { get; set; } [ResultColumn] + [Reference(ReferenceType.OneToOne)] public ContentTypeDto ContentTypeDto { get; set; } } } \ No newline at end of file diff --git a/src/Umbraco.Core/Models/Rdbms/ContentVersionDto.cs b/src/Umbraco.Core/Models/Rdbms/ContentVersionDto.cs index 3bd85cccf6..715f9908e4 100644 --- a/src/Umbraco.Core/Models/Rdbms/ContentVersionDto.cs +++ b/src/Umbraco.Core/Models/Rdbms/ContentVersionDto.cs @@ -1,4 +1,5 @@ using System; +using NPoco; using Umbraco.Core.Persistence; using Umbraco.Core.Persistence.DatabaseAnnotations; using Umbraco.Core.Persistence.DatabaseModelDefinitions; @@ -28,6 +29,7 @@ namespace Umbraco.Core.Models.Rdbms public DateTime VersionDate { get; set; } [ResultColumn] + [Reference(ReferenceType.OneToOne, ColumnName = "NodeId", ReferenceMemberName = "NodeId")] public ContentDto ContentDto { get; set; } } } \ No newline at end of file diff --git a/src/Umbraco.Core/Models/Rdbms/ContentXmlDto.cs b/src/Umbraco.Core/Models/Rdbms/ContentXmlDto.cs index ca48a4074c..c72af43901 100644 --- a/src/Umbraco.Core/Models/Rdbms/ContentXmlDto.cs +++ b/src/Umbraco.Core/Models/Rdbms/ContentXmlDto.cs @@ -1,11 +1,12 @@ using System.Data; +using NPoco; using Umbraco.Core.Persistence; using Umbraco.Core.Persistence.DatabaseAnnotations; namespace Umbraco.Core.Models.Rdbms { [TableName("cmsContentXml")] - [PrimaryKey("nodeId", autoIncrement = false)] + [PrimaryKey("nodeId", AutoIncrement = false)] [ExplicitColumns] internal class ContentXmlDto { diff --git a/src/Umbraco.Core/Models/Rdbms/DataTypeDto.cs b/src/Umbraco.Core/Models/Rdbms/DataTypeDto.cs index b0e63b0726..148116d70e 100644 --- a/src/Umbraco.Core/Models/Rdbms/DataTypeDto.cs +++ b/src/Umbraco.Core/Models/Rdbms/DataTypeDto.cs @@ -1,4 +1,5 @@ using System; +using NPoco; using Umbraco.Core.Persistence; using Umbraco.Core.Persistence.DatabaseAnnotations; @@ -26,6 +27,7 @@ namespace Umbraco.Core.Models.Rdbms public string DbType { get; set; }//NOTE Is set to [varchar] (50) in Sql Server script [ResultColumn] + [Reference(ReferenceType.OneToOne, ColumnName = "DataTypeId")] public NodeDto NodeDto { get; set; } } } \ No newline at end of file diff --git a/src/Umbraco.Core/Models/Rdbms/DataTypePreValueDto.cs b/src/Umbraco.Core/Models/Rdbms/DataTypePreValueDto.cs index 652e63df0b..69c9e17dbd 100644 --- a/src/Umbraco.Core/Models/Rdbms/DataTypePreValueDto.cs +++ b/src/Umbraco.Core/Models/Rdbms/DataTypePreValueDto.cs @@ -1,4 +1,5 @@ -using Umbraco.Core.Persistence; +using NPoco; +using Umbraco.Core.Persistence; using Umbraco.Core.Persistence.DatabaseAnnotations; namespace Umbraco.Core.Models.Rdbms diff --git a/src/Umbraco.Core/Models/Rdbms/DictionaryDto.cs b/src/Umbraco.Core/Models/Rdbms/DictionaryDto.cs index 712d1937a9..262c9f3c5b 100644 --- a/src/Umbraco.Core/Models/Rdbms/DictionaryDto.cs +++ b/src/Umbraco.Core/Models/Rdbms/DictionaryDto.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using NPoco; using Umbraco.Core.Persistence; using Umbraco.Core.Persistence.DatabaseAnnotations; @@ -28,6 +29,7 @@ namespace Umbraco.Core.Models.Rdbms public string Key { get; set; } [ResultColumn] + [Reference(ReferenceType.Many, ColumnName = "UniqueId", ReferenceMemberName = "UniqueId")] public List LanguageTextDtos { get; set; } } } \ No newline at end of file diff --git a/src/Umbraco.Core/Models/Rdbms/DocumentDto.cs b/src/Umbraco.Core/Models/Rdbms/DocumentDto.cs index 88e04087c9..2ad44fbe58 100644 --- a/src/Umbraco.Core/Models/Rdbms/DocumentDto.cs +++ b/src/Umbraco.Core/Models/Rdbms/DocumentDto.cs @@ -1,4 +1,5 @@ using System; +using NPoco; using Umbraco.Core.Persistence; using Umbraco.Core.Persistence.DatabaseAnnotations; using Umbraco.Core.Persistence.DatabaseModelDefinitions; @@ -6,7 +7,7 @@ using Umbraco.Core.Persistence.DatabaseModelDefinitions; namespace Umbraco.Core.Models.Rdbms { [TableName("cmsDocument")] - [PrimaryKey("versionId", autoIncrement = false)] + [PrimaryKey("versionId", AutoIncrement = false)] [ExplicitColumns] internal class DocumentDto { @@ -46,16 +47,18 @@ namespace Umbraco.Core.Models.Rdbms [NullSetting(NullSetting = NullSettings.Null)] [ForeignKey(typeof(TemplateDto), Column = "nodeId")] public int? TemplateId { get; set; } - + [Column("newest")] [Constraint(Default = "0")] [Index(IndexTypes.NonClustered, Name = "IX_cmsDocument_newest")] public bool Newest { get; set; } [ResultColumn] + [Reference(ReferenceType.OneToOne, ReferenceMemberName = "NodeId")] public ContentVersionDto ContentVersionDto { get; set; } [ResultColumn] + [Reference(ReferenceType.OneToOne, ReferenceMemberName = "NodeId")] public DocumentPublishedReadOnlyDto DocumentPublishedReadOnlyDto { get; set; } } } \ No newline at end of file diff --git a/src/Umbraco.Core/Models/Rdbms/DocumentPublishedReadOnlyDto.cs b/src/Umbraco.Core/Models/Rdbms/DocumentPublishedReadOnlyDto.cs index 4a7e359d91..788e321877 100644 --- a/src/Umbraco.Core/Models/Rdbms/DocumentPublishedReadOnlyDto.cs +++ b/src/Umbraco.Core/Models/Rdbms/DocumentPublishedReadOnlyDto.cs @@ -1,10 +1,11 @@ using System; +using NPoco; using Umbraco.Core.Persistence; namespace Umbraco.Core.Models.Rdbms { [TableName("cmsDocument")] - [PrimaryKey("versionId", autoIncrement = false)] + [PrimaryKey("versionId", AutoIncrement = false)] [ExplicitColumns] internal class DocumentPublishedReadOnlyDto { diff --git a/src/Umbraco.Core/Models/Rdbms/DomainDto.cs b/src/Umbraco.Core/Models/Rdbms/DomainDto.cs index e43c1bdeae..e78c442184 100644 --- a/src/Umbraco.Core/Models/Rdbms/DomainDto.cs +++ b/src/Umbraco.Core/Models/Rdbms/DomainDto.cs @@ -1,4 +1,5 @@ -using Umbraco.Core.Persistence; +using NPoco; +using Umbraco.Core.Persistence; using Umbraco.Core.Persistence.DatabaseAnnotations; namespace Umbraco.Core.Models.Rdbms diff --git a/src/Umbraco.Core/Models/Rdbms/ExternalLoginDto.cs b/src/Umbraco.Core/Models/Rdbms/ExternalLoginDto.cs index 803c25fdfc..1f335ec6ce 100644 --- a/src/Umbraco.Core/Models/Rdbms/ExternalLoginDto.cs +++ b/src/Umbraco.Core/Models/Rdbms/ExternalLoginDto.cs @@ -1,4 +1,5 @@ using System; +using NPoco; using Umbraco.Core.Persistence; using Umbraco.Core.Persistence.DatabaseAnnotations; using Umbraco.Core.Persistence.DatabaseModelDefinitions; diff --git a/src/Umbraco.Core/Models/Rdbms/LanguageDto.cs b/src/Umbraco.Core/Models/Rdbms/LanguageDto.cs index a634dca0a4..2e6a4fdae2 100644 --- a/src/Umbraco.Core/Models/Rdbms/LanguageDto.cs +++ b/src/Umbraco.Core/Models/Rdbms/LanguageDto.cs @@ -1,4 +1,5 @@ -using Umbraco.Core.Persistence; +using NPoco; +using Umbraco.Core.Persistence; using Umbraco.Core.Persistence.DatabaseAnnotations; namespace Umbraco.Core.Models.Rdbms diff --git a/src/Umbraco.Core/Models/Rdbms/LanguageTextDto.cs b/src/Umbraco.Core/Models/Rdbms/LanguageTextDto.cs index 87329fbd4c..e14ffdb8a8 100644 --- a/src/Umbraco.Core/Models/Rdbms/LanguageTextDto.cs +++ b/src/Umbraco.Core/Models/Rdbms/LanguageTextDto.cs @@ -1,4 +1,5 @@ using System; +using NPoco; using Umbraco.Core.Persistence; using Umbraco.Core.Persistence.DatabaseAnnotations; diff --git a/src/Umbraco.Core/Models/Rdbms/LogDto.cs b/src/Umbraco.Core/Models/Rdbms/LogDto.cs index be67b5873a..277720d29b 100644 --- a/src/Umbraco.Core/Models/Rdbms/LogDto.cs +++ b/src/Umbraco.Core/Models/Rdbms/LogDto.cs @@ -1,4 +1,5 @@ using System; +using NPoco; using Umbraco.Core.Persistence; using Umbraco.Core.Persistence.DatabaseAnnotations; using Umbraco.Core.Persistence.DatabaseModelDefinitions; diff --git a/src/Umbraco.Core/Models/Rdbms/MacroDto.cs b/src/Umbraco.Core/Models/Rdbms/MacroDto.cs index 15422f7a08..1affe3a04e 100644 --- a/src/Umbraco.Core/Models/Rdbms/MacroDto.cs +++ b/src/Umbraco.Core/Models/Rdbms/MacroDto.cs @@ -1,4 +1,5 @@ using System.Collections.Generic; +using NPoco; using Umbraco.Core.Persistence; using Umbraco.Core.Persistence.DatabaseAnnotations; @@ -59,6 +60,7 @@ namespace Umbraco.Core.Models.Rdbms public string MacroFilePath { get; set; } [ResultColumn] + [Reference(ReferenceType.Many, ReferenceMemberName = "Macro")] public List MacroPropertyDtos { get; set; } } } \ No newline at end of file diff --git a/src/Umbraco.Core/Models/Rdbms/MacroPropertyDto.cs b/src/Umbraco.Core/Models/Rdbms/MacroPropertyDto.cs index e2efddc829..6d10315ec1 100644 --- a/src/Umbraco.Core/Models/Rdbms/MacroPropertyDto.cs +++ b/src/Umbraco.Core/Models/Rdbms/MacroPropertyDto.cs @@ -1,4 +1,5 @@ -using Umbraco.Core.Persistence; +using NPoco; +using Umbraco.Core.Persistence; using Umbraco.Core.Persistence.DatabaseAnnotations; namespace Umbraco.Core.Models.Rdbms @@ -11,8 +12,8 @@ namespace Umbraco.Core.Models.Rdbms [Column("id")] [PrimaryKeyColumn] public int Id { get; set; } - - [Column("editorAlias")] + + [Column("editorAlias")] public string EditorAlias { get; set; } [Column("macro")] diff --git a/src/Umbraco.Core/Models/Rdbms/Member2MemberGroupDto.cs b/src/Umbraco.Core/Models/Rdbms/Member2MemberGroupDto.cs index 888f331364..653f4d3c87 100644 --- a/src/Umbraco.Core/Models/Rdbms/Member2MemberGroupDto.cs +++ b/src/Umbraco.Core/Models/Rdbms/Member2MemberGroupDto.cs @@ -1,10 +1,11 @@ -using Umbraco.Core.Persistence; +using NPoco; +using Umbraco.Core.Persistence; using Umbraco.Core.Persistence.DatabaseAnnotations; namespace Umbraco.Core.Models.Rdbms { [TableName("cmsMember2MemberGroup")] - [PrimaryKey("Member", autoIncrement = false)] + [PrimaryKey("Member", AutoIncrement = false)] [ExplicitColumns] internal class Member2MemberGroupDto { diff --git a/src/Umbraco.Core/Models/Rdbms/MemberDto.cs b/src/Umbraco.Core/Models/Rdbms/MemberDto.cs index e5f7b3f17c..35d5db1042 100644 --- a/src/Umbraco.Core/Models/Rdbms/MemberDto.cs +++ b/src/Umbraco.Core/Models/Rdbms/MemberDto.cs @@ -1,10 +1,11 @@ -using Umbraco.Core.Persistence; +using NPoco; +using Umbraco.Core.Persistence; using Umbraco.Core.Persistence.DatabaseAnnotations; namespace Umbraco.Core.Models.Rdbms { [TableName("cmsMember")] - [PrimaryKey("nodeId", autoIncrement = false)] + [PrimaryKey("nodeId", AutoIncrement = false)] [ExplicitColumns] internal class MemberDto { @@ -30,6 +31,7 @@ namespace Umbraco.Core.Models.Rdbms public string Password { get; set; } [ResultColumn] + [Reference(ReferenceType.OneToOne, ReferenceMemberName = "NodeId")] public ContentVersionDto ContentVersionDto { get; set; } } } \ No newline at end of file diff --git a/src/Umbraco.Core/Models/Rdbms/MemberTypeDto.cs b/src/Umbraco.Core/Models/Rdbms/MemberTypeDto.cs index c9432652af..7d637e74c6 100644 --- a/src/Umbraco.Core/Models/Rdbms/MemberTypeDto.cs +++ b/src/Umbraco.Core/Models/Rdbms/MemberTypeDto.cs @@ -1,4 +1,5 @@ -using Umbraco.Core.Persistence; +using NPoco; +using Umbraco.Core.Persistence; using Umbraco.Core.Persistence.DatabaseAnnotations; namespace Umbraco.Core.Models.Rdbms diff --git a/src/Umbraco.Core/Models/Rdbms/MemberTypeReadOnlyDto.cs b/src/Umbraco.Core/Models/Rdbms/MemberTypeReadOnlyDto.cs index 4833cb33f0..4997134ccf 100644 --- a/src/Umbraco.Core/Models/Rdbms/MemberTypeReadOnlyDto.cs +++ b/src/Umbraco.Core/Models/Rdbms/MemberTypeReadOnlyDto.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using NPoco; using Umbraco.Core.Persistence; namespace Umbraco.Core.Models.Rdbms @@ -68,11 +69,13 @@ namespace Umbraco.Core.Models.Rdbms /* PropertyTypes */ //TODO Add PropertyTypeDto (+MemberTypeDto and DataTypeDto as one) ReadOnly list [ResultColumn] + [Reference(ReferenceType.Many, ReferenceMemberName = "ContentTypeId")] public List PropertyTypes { get; set; } /* PropertyTypeGroups */ //TODO Add PropertyTypeGroupDto ReadOnly list [ResultColumn] + [Reference(ReferenceType.Many, ReferenceMemberName = "ContentTypeNodeId")] public List PropertyTypeGroups { get; set; } } } \ No newline at end of file diff --git a/src/Umbraco.Core/Models/Rdbms/MigrationDto.cs b/src/Umbraco.Core/Models/Rdbms/MigrationDto.cs index 1a76895e90..2cff4f1c5a 100644 --- a/src/Umbraco.Core/Models/Rdbms/MigrationDto.cs +++ b/src/Umbraco.Core/Models/Rdbms/MigrationDto.cs @@ -1,4 +1,5 @@ using System; +using NPoco; using Umbraco.Core.Persistence; using Umbraco.Core.Persistence.DatabaseAnnotations; using Umbraco.Core.Persistence.DatabaseModelDefinitions; diff --git a/src/Umbraco.Core/Models/Rdbms/NodeDto.cs b/src/Umbraco.Core/Models/Rdbms/NodeDto.cs index c5fac092df..b0860ea34a 100644 --- a/src/Umbraco.Core/Models/Rdbms/NodeDto.cs +++ b/src/Umbraco.Core/Models/Rdbms/NodeDto.cs @@ -1,4 +1,5 @@ using System; +using NPoco; using Umbraco.Core.Persistence; using Umbraco.Core.Persistence.DatabaseAnnotations; using Umbraco.Core.Persistence.DatabaseModelDefinitions; diff --git a/src/Umbraco.Core/Models/Rdbms/PreviewXmlDto.cs b/src/Umbraco.Core/Models/Rdbms/PreviewXmlDto.cs index d981855f24..e3adb3c915 100644 --- a/src/Umbraco.Core/Models/Rdbms/PreviewXmlDto.cs +++ b/src/Umbraco.Core/Models/Rdbms/PreviewXmlDto.cs @@ -1,11 +1,12 @@ using System; +using NPoco; using Umbraco.Core.Persistence; using Umbraco.Core.Persistence.DatabaseAnnotations; namespace Umbraco.Core.Models.Rdbms { [TableName("cmsPreviewXml")] - [PrimaryKey("nodeId", autoIncrement = false)] + [PrimaryKey("nodeId", AutoIncrement = false)] [ExplicitColumns] internal class PreviewXmlDto { diff --git a/src/Umbraco.Core/Models/Rdbms/PropertyDataDto.cs b/src/Umbraco.Core/Models/Rdbms/PropertyDataDto.cs index 63e3104d12..8840cb771d 100644 --- a/src/Umbraco.Core/Models/Rdbms/PropertyDataDto.cs +++ b/src/Umbraco.Core/Models/Rdbms/PropertyDataDto.cs @@ -1,4 +1,5 @@ using System; +using NPoco; using Umbraco.Core.Persistence; using Umbraco.Core.Persistence.DatabaseAnnotations; @@ -52,6 +53,7 @@ namespace Umbraco.Core.Models.Rdbms public string Text { get; set; } [ResultColumn] + [Reference(ReferenceType.OneToOne, ColumnName = "PropertyTypeId")] public PropertyTypeDto PropertyTypeDto { get; set; } [Ignore] @@ -68,12 +70,12 @@ namespace Umbraco.Core.Models.Rdbms { return Decimal.Value; } - + if (Date.HasValue) { return Date.Value; } - + if (string.IsNullOrEmpty(VarChar) == false) { return VarChar; diff --git a/src/Umbraco.Core/Models/Rdbms/PropertyTypeDto.cs b/src/Umbraco.Core/Models/Rdbms/PropertyTypeDto.cs index 2be4b24157..cc74268c8a 100644 --- a/src/Umbraco.Core/Models/Rdbms/PropertyTypeDto.cs +++ b/src/Umbraco.Core/Models/Rdbms/PropertyTypeDto.cs @@ -1,4 +1,5 @@ using System; +using NPoco; using Umbraco.Core.Persistence; using Umbraco.Core.Persistence.DatabaseAnnotations; using Umbraco.Core.Persistence.DatabaseModelDefinitions; @@ -52,6 +53,7 @@ namespace Umbraco.Core.Models.Rdbms public string Description { get; set; } [ResultColumn] + [Reference(ReferenceType.OneToOne, ColumnName = "DataTypeId")] public DataTypeDto DataTypeDto { get; set; } [Column("UniqueID")] diff --git a/src/Umbraco.Core/Models/Rdbms/PropertyTypeGroupDto.cs b/src/Umbraco.Core/Models/Rdbms/PropertyTypeGroupDto.cs index 68de420a97..c560780dcf 100644 --- a/src/Umbraco.Core/Models/Rdbms/PropertyTypeGroupDto.cs +++ b/src/Umbraco.Core/Models/Rdbms/PropertyTypeGroupDto.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using NPoco; using Umbraco.Core.Persistence; using Umbraco.Core.Persistence.DatabaseAnnotations; using Umbraco.Core.Persistence.DatabaseModelDefinitions; @@ -7,7 +8,7 @@ using Umbraco.Core.Persistence.DatabaseModelDefinitions; namespace Umbraco.Core.Models.Rdbms { [TableName("cmsPropertyTypeGroup")] - [PrimaryKey("id", autoIncrement = true)] + [PrimaryKey("id", AutoIncrement = true)] [ExplicitColumns] internal class PropertyTypeGroupDto { @@ -26,6 +27,7 @@ namespace Umbraco.Core.Models.Rdbms public int SortOrder { get; set; } [ResultColumn] + [Reference(ReferenceType.Many, ReferenceMemberName = "PropertyTypeGroupId")] public List PropertyTypeDtos { get; set; } [Column("uniqueID")] diff --git a/src/Umbraco.Core/Models/Rdbms/PropertyTypeGroupReadOnlyDto.cs b/src/Umbraco.Core/Models/Rdbms/PropertyTypeGroupReadOnlyDto.cs index beebef9eeb..ac38b7b642 100644 --- a/src/Umbraco.Core/Models/Rdbms/PropertyTypeGroupReadOnlyDto.cs +++ b/src/Umbraco.Core/Models/Rdbms/PropertyTypeGroupReadOnlyDto.cs @@ -1,9 +1,10 @@ -using Umbraco.Core.Persistence; +using NPoco; +using Umbraco.Core.Persistence; namespace Umbraco.Core.Models.Rdbms { [TableName("cmsPropertyTypeGroup")] - [PrimaryKey("id", autoIncrement = true)] + [PrimaryKey("id", AutoIncrement = true)] [ExplicitColumns] internal class PropertyTypeGroupReadOnlyDto { diff --git a/src/Umbraco.Core/Models/Rdbms/PropertyTypeReadOnlyDto.cs b/src/Umbraco.Core/Models/Rdbms/PropertyTypeReadOnlyDto.cs index 2f448860b0..bba1546a93 100644 --- a/src/Umbraco.Core/Models/Rdbms/PropertyTypeReadOnlyDto.cs +++ b/src/Umbraco.Core/Models/Rdbms/PropertyTypeReadOnlyDto.cs @@ -1,4 +1,5 @@ using System; +using NPoco; using Umbraco.Core.Persistence; namespace Umbraco.Core.Models.Rdbms diff --git a/src/Umbraco.Core/Models/Rdbms/RelationDto.cs b/src/Umbraco.Core/Models/Rdbms/RelationDto.cs index 368904a5cb..44f0199b17 100644 --- a/src/Umbraco.Core/Models/Rdbms/RelationDto.cs +++ b/src/Umbraco.Core/Models/Rdbms/RelationDto.cs @@ -1,4 +1,5 @@ using System; +using NPoco; using Umbraco.Core.Persistence; using Umbraco.Core.Persistence.DatabaseAnnotations; using Umbraco.Core.Persistence.DatabaseModelDefinitions; diff --git a/src/Umbraco.Core/Models/Rdbms/RelationTypeDto.cs b/src/Umbraco.Core/Models/Rdbms/RelationTypeDto.cs index 8a6eb5c02a..c927fcf455 100644 --- a/src/Umbraco.Core/Models/Rdbms/RelationTypeDto.cs +++ b/src/Umbraco.Core/Models/Rdbms/RelationTypeDto.cs @@ -1,4 +1,5 @@ using System; +using NPoco; using Umbraco.Core.Persistence; using Umbraco.Core.Persistence.DatabaseAnnotations; diff --git a/src/Umbraco.Core/Models/Rdbms/ServerRegistrationDto.cs b/src/Umbraco.Core/Models/Rdbms/ServerRegistrationDto.cs index 2a3751c083..55b6145a3a 100644 --- a/src/Umbraco.Core/Models/Rdbms/ServerRegistrationDto.cs +++ b/src/Umbraco.Core/Models/Rdbms/ServerRegistrationDto.cs @@ -1,4 +1,5 @@ using System; +using NPoco; using Umbraco.Core.Persistence; using Umbraco.Core.Persistence.DatabaseAnnotations; using Umbraco.Core.Persistence.DatabaseModelDefinitions; diff --git a/src/Umbraco.Core/Models/Rdbms/StylesheetDto.cs b/src/Umbraco.Core/Models/Rdbms/StylesheetDto.cs index 3580fcf918..91132d3a7e 100644 --- a/src/Umbraco.Core/Models/Rdbms/StylesheetDto.cs +++ b/src/Umbraco.Core/Models/Rdbms/StylesheetDto.cs @@ -1,10 +1,11 @@ -using Umbraco.Core.Persistence; +using NPoco; +using Umbraco.Core.Persistence; using Umbraco.Core.Persistence.DatabaseAnnotations; namespace Umbraco.Core.Models.Rdbms { [TableName("cmsStylesheet")] - [PrimaryKey("nodeId", autoIncrement = false)] + [PrimaryKey("nodeId", AutoIncrement = false)] [ExplicitColumns] internal class StylesheetDto { diff --git a/src/Umbraco.Core/Models/Rdbms/StylesheetPropertyDto.cs b/src/Umbraco.Core/Models/Rdbms/StylesheetPropertyDto.cs index cfe3148764..8e249a8da2 100644 --- a/src/Umbraco.Core/Models/Rdbms/StylesheetPropertyDto.cs +++ b/src/Umbraco.Core/Models/Rdbms/StylesheetPropertyDto.cs @@ -1,10 +1,11 @@ -using Umbraco.Core.Persistence; +using NPoco; +using Umbraco.Core.Persistence; using Umbraco.Core.Persistence.DatabaseAnnotations; namespace Umbraco.Core.Models.Rdbms { [TableName("cmsStylesheetProperty")] - [PrimaryKey("nodeId", autoIncrement = false)] + [PrimaryKey("nodeId", AutoIncrement = false)] [ExplicitColumns] internal class StylesheetPropertyDto { diff --git a/src/Umbraco.Core/Models/Rdbms/TagDto.cs b/src/Umbraco.Core/Models/Rdbms/TagDto.cs index d612f656bb..cb37f2c723 100644 --- a/src/Umbraco.Core/Models/Rdbms/TagDto.cs +++ b/src/Umbraco.Core/Models/Rdbms/TagDto.cs @@ -1,4 +1,5 @@ -using Umbraco.Core.Persistence; +using NPoco; +using Umbraco.Core.Persistence; using Umbraco.Core.Persistence.DatabaseAnnotations; namespace Umbraco.Core.Models.Rdbms diff --git a/src/Umbraco.Core/Models/Rdbms/TagRelationshipDto.cs b/src/Umbraco.Core/Models/Rdbms/TagRelationshipDto.cs index 4fc936713a..d605530839 100644 --- a/src/Umbraco.Core/Models/Rdbms/TagRelationshipDto.cs +++ b/src/Umbraco.Core/Models/Rdbms/TagRelationshipDto.cs @@ -1,10 +1,11 @@ -using Umbraco.Core.Persistence; +using NPoco; +using Umbraco.Core.Persistence; using Umbraco.Core.Persistence.DatabaseAnnotations; namespace Umbraco.Core.Models.Rdbms { [TableName("cmsTagRelationship")] - [PrimaryKey("nodeId", autoIncrement = false)] + [PrimaryKey("nodeId", AutoIncrement = false)] [ExplicitColumns] internal class TagRelationshipDto { diff --git a/src/Umbraco.Core/Models/Rdbms/TaskDto.cs b/src/Umbraco.Core/Models/Rdbms/TaskDto.cs index e27f7c0a93..7ce24aa21e 100644 --- a/src/Umbraco.Core/Models/Rdbms/TaskDto.cs +++ b/src/Umbraco.Core/Models/Rdbms/TaskDto.cs @@ -1,4 +1,5 @@ using System; +using NPoco; using Umbraco.Core.Persistence; using Umbraco.Core.Persistence.DatabaseAnnotations; using Umbraco.Core.Persistence.DatabaseModelDefinitions; @@ -44,6 +45,7 @@ namespace Umbraco.Core.Models.Rdbms public string Comment { get; set; } [ResultColumn] + [Reference(ReferenceType.OneToOne, ColumnName = "TaskTypeId")] public TaskTypeDto TaskTypeDto { get; set; } } } \ No newline at end of file diff --git a/src/Umbraco.Core/Models/Rdbms/TaskTypeDto.cs b/src/Umbraco.Core/Models/Rdbms/TaskTypeDto.cs index 2ff61953ce..113908a47c 100644 --- a/src/Umbraco.Core/Models/Rdbms/TaskTypeDto.cs +++ b/src/Umbraco.Core/Models/Rdbms/TaskTypeDto.cs @@ -1,4 +1,5 @@ -using Umbraco.Core.Persistence; +using NPoco; +using Umbraco.Core.Persistence; using Umbraco.Core.Persistence.DatabaseAnnotations; namespace Umbraco.Core.Models.Rdbms diff --git a/src/Umbraco.Core/Models/Rdbms/TemplateDto.cs b/src/Umbraco.Core/Models/Rdbms/TemplateDto.cs index 8e2fe0b9f5..b0bdb17bba 100644 --- a/src/Umbraco.Core/Models/Rdbms/TemplateDto.cs +++ b/src/Umbraco.Core/Models/Rdbms/TemplateDto.cs @@ -1,4 +1,5 @@ -using Umbraco.Core.Persistence; +using NPoco; +using Umbraco.Core.Persistence; using Umbraco.Core.Persistence.DatabaseAnnotations; namespace Umbraco.Core.Models.Rdbms @@ -27,6 +28,7 @@ namespace Umbraco.Core.Models.Rdbms public string Design { get; set; } [ResultColumn] + [Reference(ReferenceType.OneToOne, ColumnName = "NodeId")] public NodeDto NodeDto { get; set; } } } \ No newline at end of file diff --git a/src/Umbraco.Core/Models/Rdbms/UmbracoDeployChecksumDto.cs b/src/Umbraco.Core/Models/Rdbms/UmbracoDeployChecksumDto.cs index 06d904ee88..a012d85563 100644 --- a/src/Umbraco.Core/Models/Rdbms/UmbracoDeployChecksumDto.cs +++ b/src/Umbraco.Core/Models/Rdbms/UmbracoDeployChecksumDto.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using NPoco; using Umbraco.Core.Persistence; using Umbraco.Core.Persistence.DatabaseAnnotations; using Umbraco.Core.Persistence.DatabaseModelDefinitions; diff --git a/src/Umbraco.Core/Models/Rdbms/UmbracoDeployDependencyDto.cs b/src/Umbraco.Core/Models/Rdbms/UmbracoDeployDependencyDto.cs index 765a32c929..6ec19a513d 100644 --- a/src/Umbraco.Core/Models/Rdbms/UmbracoDeployDependencyDto.cs +++ b/src/Umbraco.Core/Models/Rdbms/UmbracoDeployDependencyDto.cs @@ -1,3 +1,4 @@ +using NPoco; using Umbraco.Core.Persistence; using Umbraco.Core.Persistence.DatabaseAnnotations; diff --git a/src/Umbraco.Core/Models/Rdbms/User2AppDto.cs b/src/Umbraco.Core/Models/Rdbms/User2AppDto.cs index eafc6be230..5c80c6e117 100644 --- a/src/Umbraco.Core/Models/Rdbms/User2AppDto.cs +++ b/src/Umbraco.Core/Models/Rdbms/User2AppDto.cs @@ -1,10 +1,11 @@ -using Umbraco.Core.Persistence; +using NPoco; +using Umbraco.Core.Persistence; using Umbraco.Core.Persistence.DatabaseAnnotations; namespace Umbraco.Core.Models.Rdbms { [TableName("umbracoUser2app")] - [PrimaryKey("user", autoIncrement = false)] + [PrimaryKey("user", AutoIncrement = false)] [ExplicitColumns] internal class User2AppDto { diff --git a/src/Umbraco.Core/Models/Rdbms/User2NodeNotifyDto.cs b/src/Umbraco.Core/Models/Rdbms/User2NodeNotifyDto.cs index 298ad920d9..e45c0a6ad8 100644 --- a/src/Umbraco.Core/Models/Rdbms/User2NodeNotifyDto.cs +++ b/src/Umbraco.Core/Models/Rdbms/User2NodeNotifyDto.cs @@ -1,10 +1,11 @@ -using Umbraco.Core.Persistence; +using NPoco; +using Umbraco.Core.Persistence; using Umbraco.Core.Persistence.DatabaseAnnotations; namespace Umbraco.Core.Models.Rdbms { [TableName("umbracoUser2NodeNotify")] - [PrimaryKey("userId", autoIncrement = false)] + [PrimaryKey("userId", AutoIncrement = false)] [ExplicitColumns] internal class User2NodeNotifyDto { diff --git a/src/Umbraco.Core/Models/Rdbms/User2NodePermissionDto.cs b/src/Umbraco.Core/Models/Rdbms/User2NodePermissionDto.cs index 1e6662735f..117f88fe66 100644 --- a/src/Umbraco.Core/Models/Rdbms/User2NodePermissionDto.cs +++ b/src/Umbraco.Core/Models/Rdbms/User2NodePermissionDto.cs @@ -1,10 +1,11 @@ -using Umbraco.Core.Persistence; +using NPoco; +using Umbraco.Core.Persistence; using Umbraco.Core.Persistence.DatabaseAnnotations; namespace Umbraco.Core.Models.Rdbms { [TableName("umbracoUser2NodePermission")] - [PrimaryKey("userId", autoIncrement = false)] + [PrimaryKey("userId", AutoIncrement = false)] [ExplicitColumns] internal class User2NodePermissionDto { diff --git a/src/Umbraco.Core/Models/Rdbms/UserDto.cs b/src/Umbraco.Core/Models/Rdbms/UserDto.cs index 05a93c86bf..350f4b4a79 100644 --- a/src/Umbraco.Core/Models/Rdbms/UserDto.cs +++ b/src/Umbraco.Core/Models/Rdbms/UserDto.cs @@ -1,12 +1,13 @@ using System; using System.Collections.Generic; +using NPoco; using Umbraco.Core.Persistence; using Umbraco.Core.Persistence.DatabaseAnnotations; namespace Umbraco.Core.Models.Rdbms { [TableName("umbracoUser")] - [PrimaryKey("id", autoIncrement = true)] + [PrimaryKey("id", AutoIncrement = true)] [ExplicitColumns] internal class UserDto { @@ -75,6 +76,7 @@ namespace Umbraco.Core.Models.Rdbms public DateTime? LastLoginDate { get; set; } [ResultColumn] + [Reference(ReferenceType.Many, ReferenceMemberName = "UserId")] public List User2AppDtos { get; set; } } } \ No newline at end of file diff --git a/src/Umbraco.Core/Models/Rdbms/UserTypeDto.cs b/src/Umbraco.Core/Models/Rdbms/UserTypeDto.cs index d3268a14fb..8b6d286073 100644 --- a/src/Umbraco.Core/Models/Rdbms/UserTypeDto.cs +++ b/src/Umbraco.Core/Models/Rdbms/UserTypeDto.cs @@ -1,4 +1,5 @@ -using Umbraco.Core.Persistence; +using NPoco; +using Umbraco.Core.Persistence; using Umbraco.Core.Persistence.DatabaseAnnotations; namespace Umbraco.Core.Models.Rdbms diff --git a/src/Umbraco.Core/Persistence/DatabaseModelDefinitions/DefinitionFactory.cs b/src/Umbraco.Core/Persistence/DatabaseModelDefinitions/DefinitionFactory.cs index eefacbcbc1..7936ac0fa8 100644 --- a/src/Umbraco.Core/Persistence/DatabaseModelDefinitions/DefinitionFactory.cs +++ b/src/Umbraco.Core/Persistence/DatabaseModelDefinitions/DefinitionFactory.cs @@ -2,6 +2,7 @@ using System.Data; using System.Linq; using System.Reflection; +using NPoco; using Umbraco.Core.Persistence.DatabaseAnnotations; using Umbraco.Core.Persistence.SqlSyntax; @@ -11,7 +12,7 @@ namespace Umbraco.Core.Persistence.DatabaseModelDefinitions { public static TableDefinition GetTableDefinition(Type modelType, ISqlSyntaxProvider sqlSyntax) { - //Looks for PetaPoco's TableNameAtribute for the name of the table + //Looks for NPoco's TableNameAtribute for the name of the table //If no attribute is set we use the name of the Type as the default convention var tableNameAttribute = modelType.FirstAttribute(); string tableName = tableNameAttribute == null ? modelType.Name : tableNameAttribute.Value; @@ -108,7 +109,7 @@ namespace Umbraco.Core.Persistence.DatabaseModelDefinitions var constraintAttribute = propertyInfo.FirstAttribute(); if (constraintAttribute != null) { - //Special case for MySQL as it can't have multiple default DateTime values, which + //Special case for MySQL as it can't have multiple default DateTime values, which //is what the umbracoServer table definition is trying to create if (sqlSyntax is MySqlSyntaxProvider && definition.TableName == "umbracoServer" && definition.TableName.ToLowerInvariant() == "lastNotifiedDate".ToLowerInvariant()) diff --git a/src/Umbraco.Core/Persistence/DatabaseSchemaHelper.cs b/src/Umbraco.Core/Persistence/DatabaseSchemaHelper.cs index 418e5b953d..ad6af9dd0a 100644 --- a/src/Umbraco.Core/Persistence/DatabaseSchemaHelper.cs +++ b/src/Umbraco.Core/Persistence/DatabaseSchemaHelper.cs @@ -1,5 +1,6 @@ using System; using System.Linq; +using NPoco; using Umbraco.Core.Configuration; using Umbraco.Core.Logging; using Umbraco.Core.Models.Rdbms; diff --git a/src/Umbraco.Core/Persistence/DatabasenodeLockExtensions.cs b/src/Umbraco.Core/Persistence/DatabasenodeLockExtensions.cs index 3e6d245416..d6ad4f1f3c 100644 --- a/src/Umbraco.Core/Persistence/DatabasenodeLockExtensions.cs +++ b/src/Umbraco.Core/Persistence/DatabasenodeLockExtensions.cs @@ -12,7 +12,7 @@ namespace Umbraco.Core.Persistence { if (database == null) throw new ArgumentNullException("database"); - if (database.CurrentTransactionIsolationLevel < IsolationLevel.RepeatableRead) + if (database.GetCurrentTransactionIsolationLevel() < IsolationLevel.RepeatableRead) throw new InvalidOperationException("A transaction with minimum RepeatableRead isolation level is required."); } diff --git a/src/Umbraco.Core/Persistence/DefaultDatabaseFactory.cs b/src/Umbraco.Core/Persistence/DefaultDatabaseFactory.cs index 72c4275541..f5c2ab9c4f 100644 --- a/src/Umbraco.Core/Persistence/DefaultDatabaseFactory.cs +++ b/src/Umbraco.Core/Persistence/DefaultDatabaseFactory.cs @@ -1,7 +1,12 @@ using System; +using System.Configuration; using System.Web; +using NPoco; +using NPoco.FluentMappings; using Umbraco.Core.Configuration; using Umbraco.Core.Logging; +using Umbraco.Core.Persistence.FaultHandling; +using Umbraco.Core.Persistence.Mappers; namespace Umbraco.Core.Persistence { @@ -17,82 +22,100 @@ namespace Umbraco.Core.Persistence { private readonly string _connectionStringName; private readonly ILogger _logger; - public string ConnectionString { get; private set; } + private readonly DatabaseFactory _databaseFactory; + private readonly RetryPolicy _connectionRetryPolicy; + private readonly RetryPolicy _commandRetryPolicy; + + public string ConnectionString { get; private set; } public string ProviderName { get; private set; } - + //very important to have ThreadStatic: // see: http://issues.umbraco.org/issue/U4-2172 [ThreadStatic] - private static volatile UmbracoDatabase _nonHttpInstance; - - private static readonly object Locker = new object(); - + private static Lazy _nonHttpInstance; + /// /// Constructor accepting custom connection string /// /// Name of the connection string in web.config /// public DefaultDatabaseFactory(string connectionStringName, ILogger logger) + : this(logger) { - if (logger == null) throw new ArgumentNullException("logger"); Mandate.ParameterNotNullOrEmpty(connectionStringName, "connectionStringName"); _connectionStringName = connectionStringName; - _logger = logger; - } - /// - /// Constructor accepting custom connectino string and provider name - /// - /// Connection String to use with Database - /// Database Provider for the Connection String - /// - public DefaultDatabaseFactory(string connectionString, string providerName, ILogger logger) + if (ConfigurationManager.ConnectionStrings[connectionStringName] == null) + throw new InvalidOperationException("Can't find a connection string with the name '" + connectionStringName + "'"); + var connectionString = ConfigurationManager.ConnectionStrings[connectionStringName].ConnectionString; + + _connectionRetryPolicy = RetryPolicyFactory.GetDefaultSqlConnectionRetryPolicyByConnectionString(connectionString); + _commandRetryPolicy = RetryPolicyFactory.GetDefaultSqlCommandRetryPolicyByConnectionString(connectionString); + } + + /// + /// Constructor accepting custom connectino string and provider name + /// + /// Connection String to use with Database + /// Database Provider for the Connection String + /// + public DefaultDatabaseFactory(string connectionString, string providerName, ILogger logger) + : this(logger) { - if (logger == null) throw new ArgumentNullException("logger"); Mandate.ParameterNotNullOrEmpty(connectionString, "connectionString"); Mandate.ParameterNotNullOrEmpty(providerName, "providerName"); ConnectionString = connectionString; ProviderName = providerName; + + _connectionRetryPolicy = RetryPolicyFactory.GetDefaultSqlConnectionRetryPolicyByConnectionString(connectionString); + _commandRetryPolicy = RetryPolicyFactory.GetDefaultSqlCommandRetryPolicyByConnectionString(connectionString); + } + + private DefaultDatabaseFactory(ILogger logger) + { + if (logger == null) throw new ArgumentNullException("logger"); _logger = logger; - } + + // ensure we have only 1 set of mappers, and 1 PocoDataFactory, for all database + // so that everything NPoco is properly cached for the lifetime of the application + var mappers = new MapperCollection { new PocoMapper() }; + var pocoDataFactory = new FluentPocoDataFactory((type, iPocoDataFactory) => new PocoDataBuilder(type, mappers).Init()); + var config = new FluentConfig(xmappers => pocoDataFactory); + + // create the database factory + _databaseFactory = DatabaseFactory.Config(x => x + .UsingDatabase(CreateDatabaseInstance) // creating UmbracoDatabase instances + .WithFluentConfig(config)); // with proper configuration + + _nonHttpInstance = new Lazy(() => (UmbracoDatabase)_databaseFactory.GetDatabase()); + } + + private UmbracoDatabase CreateDatabaseInstance() + { + return string.IsNullOrEmpty(ConnectionString) == false && string.IsNullOrEmpty(ProviderName) == false + ? new UmbracoDatabase(ConnectionString, ProviderName, _logger, _connectionRetryPolicy, _commandRetryPolicy) + : new UmbracoDatabase(_connectionStringName, _logger, _connectionRetryPolicy, _commandRetryPolicy); + } public UmbracoDatabase CreateDatabase() { - //no http context, create the singleton global object + // no http context, create the singleton global object if (HttpContext.Current == null) { - if (_nonHttpInstance == null) - { - lock (Locker) - { - //double check - if (_nonHttpInstance == null) - { - _nonHttpInstance = string.IsNullOrEmpty(ConnectionString) == false && string.IsNullOrEmpty(ProviderName) == false - ? new UmbracoDatabase(ConnectionString, ProviderName, _logger) - : new UmbracoDatabase(_connectionStringName, _logger); - } - } - } - return _nonHttpInstance; + return _nonHttpInstance.Value; } - //we have an http context, so only create one per request - if (HttpContext.Current.Items.Contains(typeof(DefaultDatabaseFactory)) == false) - { - HttpContext.Current.Items.Add(typeof (DefaultDatabaseFactory), - string.IsNullOrEmpty(ConnectionString) == false && string.IsNullOrEmpty(ProviderName) == false - ? new UmbracoDatabase(ConnectionString, ProviderName, _logger) - : new UmbracoDatabase(_connectionStringName, _logger)); - } - return (UmbracoDatabase)HttpContext.Current.Items[typeof(DefaultDatabaseFactory)]; + // we have an http context, so only create one per request + var db = HttpContext.Current.Items[typeof (DefaultDatabaseFactory)] as UmbracoDatabase; + if (db == null) HttpContext.Current.Items[typeof (DefaultDatabaseFactory)] = db = (UmbracoDatabase) _databaseFactory.GetDatabase(); + return db; } protected override void DisposeResources() { - if (HttpContext.Current == null) + if (HttpContext.Current == null && _nonHttpInstance.IsValueCreated) { - _nonHttpInstance.Dispose(); + _nonHttpInstance.Value.Dispose(); } else { diff --git a/src/Umbraco.Core/Persistence/Factories/MacroFactory.cs b/src/Umbraco.Core/Persistence/Factories/MacroFactory.cs index d6b54e4797..6327a2ac62 100644 --- a/src/Umbraco.Core/Persistence/Factories/MacroFactory.cs +++ b/src/Umbraco.Core/Persistence/Factories/MacroFactory.cs @@ -12,7 +12,7 @@ namespace Umbraco.Core.Persistence.Factories public IMacro BuildEntity(MacroDto dto) { var model = new Macro(dto.Id, dto.UseInEditor, dto.RefreshRate, dto.Alias, dto.Name, dto.ScriptType, dto.ScriptAssembly, dto.Xslt, dto.CacheByPage, dto.CachePersonalized, dto.DontRender, dto.MacroFilePath); - foreach (var p in dto.MacroPropertyDtos) + foreach (var p in dto.MacroPropertyDtos.EmptyNull()) { model.Properties.Add(new MacroProperty(p.Id, p.Alias, p.Name, p.SortOrder, p.EditorAlias)); } diff --git a/src/Umbraco.Core/Persistence/Factories/UmbracoEntityFactory.cs b/src/Umbraco.Core/Persistence/Factories/UmbracoEntityFactory.cs index 658ddad2d4..0685432398 100644 --- a/src/Umbraco.Core/Persistence/Factories/UmbracoEntityFactory.cs +++ b/src/Umbraco.Core/Persistence/Factories/UmbracoEntityFactory.cs @@ -93,18 +93,15 @@ namespace Umbraco.Core.Persistence.Factories entity.IsDraft = dto.NewestVersion != default(Guid) && (dto.PublishedVersion == default(Guid) || dto.PublishedVersion != dto.NewestVersion); entity.HasPendingChanges = (dto.PublishedVersion != default(Guid) && dto.NewestVersion != default(Guid)) && dto.PublishedVersion != dto.NewestVersion; - if (dto.UmbracoPropertyDtos != null) + foreach (var propertyDto in dto.UmbracoPropertyDtos.EmptyNull()) { - foreach (var propertyDto in dto.UmbracoPropertyDtos) + entity.AdditionalData[propertyDto.PropertyAlias] = new UmbracoEntity.EntityProperty { - entity.AdditionalData[propertyDto.PropertyAlias] = new UmbracoEntity.EntityProperty - { - PropertyEditorAlias = propertyDto.PropertyEditorAlias, - Value = propertyDto.NTextValue.IsNullOrWhiteSpace() - ? propertyDto.NVarcharValue - : propertyDto.NTextValue.ConvertToJsonIfPossible() - }; - } + PropertyEditorAlias = propertyDto.PropertyEditorAlias, + Value = propertyDto.NTextValue.IsNullOrWhiteSpace() + ? propertyDto.NVarcharValue + : propertyDto.NTextValue.ConvertToJsonIfPossible() + }; } return entity; diff --git a/src/Umbraco.Core/Persistence/Factories/UserFactory.cs b/src/Umbraco.Core/Persistence/Factories/UserFactory.cs index bf6ff7d09e..bbc193d461 100644 --- a/src/Umbraco.Core/Persistence/Factories/UserFactory.cs +++ b/src/Umbraco.Core/Persistence/Factories/UserFactory.cs @@ -41,7 +41,7 @@ namespace Umbraco.Core.Persistence.Factories LastPasswordChangeDate = dto.LastPasswordChangeDate ?? DateTime.MinValue }; - foreach (var app in dto.User2AppDtos) + foreach (var app in dto.User2AppDtos.EmptyNull()) { user.AddAllowedSection(app.AppAlias); } diff --git a/src/Umbraco.Core/Persistence/FaultHandling/RetryDbConnection.cs b/src/Umbraco.Core/Persistence/FaultHandling/RetryDbConnection.cs new file mode 100644 index 0000000000..ee67774dc1 --- /dev/null +++ b/src/Umbraco.Core/Persistence/FaultHandling/RetryDbConnection.cs @@ -0,0 +1,222 @@ +using System; +using System.Data; +using System.Data.Common; +using NPoco; +using Transaction = System.Transactions.Transaction; + +namespace Umbraco.Core.Persistence.FaultHandling +{ + class RetryDbConnection : DbConnection + { + private DbConnection _inner; + private readonly RetryPolicy _conRetryPolicy; + private readonly RetryPolicy _cmdRetryPolicy; + + public RetryDbConnection(DbConnection connection, RetryPolicy conRetryPolicy, RetryPolicy cmdRetryPolicy) + { + _inner = connection; + _inner.StateChange += StateChangeHandler; + + _conRetryPolicy = conRetryPolicy ?? RetryPolicy.NoRetry; + _cmdRetryPolicy = cmdRetryPolicy; + } + + public DbConnection Inner { get { return _inner; } } + + public override string ConnectionString { get { return _inner.ConnectionString; } set { _inner.ConnectionString = value; } } + + protected override DbTransaction BeginDbTransaction(IsolationLevel isolationLevel) + { + return _inner.BeginTransaction(isolationLevel); + } + + protected override bool CanRaiseEvents + { + get { return true; } + } + + public override void ChangeDatabase(string databaseName) + { + _inner.ChangeDatabase(databaseName); + } + + public override void Close() + { + _inner.Close(); + } + + public override int ConnectionTimeout + { + get { return _inner.ConnectionTimeout; } + } + + protected override DbCommand CreateDbCommand() + { + return new FaultHandlingDbCommand(this, _inner.CreateCommand(), _cmdRetryPolicy); + } + + public override string DataSource + { + get { return _inner.DataSource; } + } + + public override string Database + { + get { return _inner.Database; } + } + + protected override void Dispose(bool disposing) + { + if (disposing && _inner != null) + { + _inner.StateChange -= StateChangeHandler; + _inner.Dispose(); + } + _inner = null; + base.Dispose(disposing); + } + + public override void EnlistTransaction(Transaction transaction) + { + _inner.EnlistTransaction(transaction); + } + + public override DataTable GetSchema() + { + return _inner.GetSchema(); + } + + public override DataTable GetSchema(string collectionName) + { + return _inner.GetSchema(collectionName); + } + + public override DataTable GetSchema(string collectionName, string[] restrictionValues) + { + return _inner.GetSchema(collectionName, restrictionValues); + } + + public override void Open() + { + _conRetryPolicy.ExecuteAction(_inner.Open); + } + + public override string ServerVersion + { + get { return _inner.ServerVersion; } + } + + public override ConnectionState State + { + get { return _inner.State; } + } + + private void StateChangeHandler(object sender, StateChangeEventArgs stateChangeEventArguments) + { + OnStateChange(stateChangeEventArguments); + } + + public void Ensure() + { + // verify whether or not the connection is valid and is open. This code may be retried therefore + // it is important to ensure that a connection is re-established should it have previously failed + if (State != ConnectionState.Open) + Open(); + } + } + + class FaultHandlingDbCommand : DbCommand + { + private RetryDbConnection _connection; + private DbCommand _inner; + private readonly RetryPolicy _cmdRetryPolicy; + + public FaultHandlingDbCommand(RetryDbConnection connection, DbCommand command, RetryPolicy cmdRetryPolicy) + { + _connection = connection; + _inner = command; + _cmdRetryPolicy = cmdRetryPolicy ?? RetryPolicy.NoRetry; + } + + protected override void Dispose(bool disposing) + { + if (disposing && _inner != null) + _inner.Dispose(); + _inner = null; + base.Dispose(disposing); + } + + public override void Cancel() + { + _inner.Cancel(); + } + + public override string CommandText { get { return _inner.CommandText; } set { _inner.CommandText = value; } } + + public override int CommandTimeout { get { return _inner.CommandTimeout; } set { _inner.CommandTimeout = value; } } + + public override CommandType CommandType { get { return _inner.CommandType; } set { _inner.CommandType = value; } } + + protected override DbConnection DbConnection + { + get + { + return _connection; + } + set + { + if (value == null) throw new ArgumentNullException("value"); + var connection = value as RetryDbConnection; + if (connection == null) throw new ArgumentException("Value is not a FaultHandlingDbConnection instance."); + if (_connection != null && _connection != connection) throw new Exception("Value is another FaultHandlingDbConnection instance."); + _connection = connection; + _inner.Connection = connection.Inner; + } + } + + protected override DbParameter CreateDbParameter() + { + return _inner.CreateParameter(); + } + + protected override DbParameterCollection DbParameterCollection + { + get { return _inner.Parameters; } + } + + protected override DbTransaction DbTransaction { get { return _inner.Transaction; } set { _inner.Transaction = value; } } + + public override bool DesignTimeVisible { get; set; } + + protected override DbDataReader ExecuteDbDataReader(CommandBehavior behavior) + { + return Execute(() => _inner.ExecuteReader(behavior)); + } + + public override int ExecuteNonQuery() + { + return Execute(() => _inner.ExecuteNonQuery()); + } + + public override object ExecuteScalar() + { + return Execute(() => _inner.ExecuteScalar()); + } + + private T Execute(Func f) + { + return _cmdRetryPolicy.ExecuteAction(() => + { + _connection.Ensure(); + return f(); + }); + } + + public override void Prepare() + { + _inner.Prepare(); + } + + public override UpdateRowSource UpdatedRowSource { get { return _inner.UpdatedRowSource; } set { _inner.UpdatedRowSource = value; } } + } +} diff --git a/src/Umbraco.Core/Persistence/LockedRepository.cs b/src/Umbraco.Core/Persistence/LockedRepository.cs index b5d2d672f2..c067e84288 100644 --- a/src/Umbraco.Core/Persistence/LockedRepository.cs +++ b/src/Umbraco.Core/Persistence/LockedRepository.cs @@ -1,4 +1,5 @@ using System; +using NPoco; using Umbraco.Core.Persistence.Repositories; using Umbraco.Core.Persistence.UnitOfWork; @@ -7,14 +8,14 @@ namespace Umbraco.Core.Persistence internal class LockedRepository where TRepository : IDisposable, IRepository { - public LockedRepository(Transaction transaction, IDatabaseUnitOfWork unitOfWork, TRepository repository) + public LockedRepository(ITransaction transaction, IDatabaseUnitOfWork unitOfWork, TRepository repository) { Transaction = transaction; UnitOfWork = unitOfWork; Repository = repository; } - public Transaction Transaction { get; private set; } + public ITransaction Transaction { get; private set; } public IDatabaseUnitOfWork UnitOfWork { get; private set; } public TRepository Repository { get; private set; } diff --git a/src/Umbraco.Core/Persistence/Mappers/BaseMapper.cs b/src/Umbraco.Core/Persistence/Mappers/BaseMapper.cs index ff373df2bf..7f64daa899 100644 --- a/src/Umbraco.Core/Persistence/Mappers/BaseMapper.cs +++ b/src/Umbraco.Core/Persistence/Mappers/BaseMapper.cs @@ -2,6 +2,7 @@ using System.Collections.Concurrent; using System.Linq.Expressions; using System.Reflection; +using NPoco; using Umbraco.Core.Persistence.SqlSyntax; namespace Umbraco.Core.Persistence.Mappers diff --git a/src/Umbraco.Core/Persistence/Mappers/MappingResolver.cs b/src/Umbraco.Core/Persistence/Mappers/MappingResolver.cs index a622bcda8c..808a932670 100644 --- a/src/Umbraco.Core/Persistence/Mappers/MappingResolver.cs +++ b/src/Umbraco.Core/Persistence/Mappers/MappingResolver.cs @@ -19,7 +19,7 @@ namespace Umbraco.Core.Persistence.Mappers public MappingResolver(IServiceContainer container, ILogger logger, Func> assignedMapperTypes) : base(container, logger, assignedMapperTypes) { - + } /// @@ -36,7 +36,7 @@ namespace Umbraco.Core.Persistence.Mappers { return _mapperCache.GetOrAdd(type, type1 => { - + //first check if we can resolve it by attribute var byAttribute = TryGetMapperByAttribute(type); @@ -54,7 +54,7 @@ namespace Umbraco.Core.Persistence.Mappers /// /// private Attempt TryGetMapperByAttribute(Type entityType) - { + { //check if any of the mappers are assigned to this type var mapper = Values.FirstOrDefault( x => x.GetType().GetCustomAttributes(false) @@ -66,7 +66,7 @@ namespace Umbraco.Core.Persistence.Mappers } return Attempt.Succeed(mapper); - } + } internal string GetMapping(Type type, string propertyName) { diff --git a/src/Umbraco.Core/Persistence/Mappers/PetaPocoMapper.cs b/src/Umbraco.Core/Persistence/Mappers/PetaPocoMapper.cs deleted file mode 100644 index fd516073ce..0000000000 --- a/src/Umbraco.Core/Persistence/Mappers/PetaPocoMapper.cs +++ /dev/null @@ -1,45 +0,0 @@ -using System; -using System.Reflection; - -namespace Umbraco.Core.Persistence.Mappers -{ - /// - /// Represents the PetaPocoMapper, which is the implementation of the IMapper interface. - /// This is currently only used to ensure that nullable dates are not saved to the database. - /// - public class PetaPocoMapper : IMapper - { - public void GetTableInfo(Type t, TableInfo ti) - { - } - - public bool MapPropertyToColumn(Type t, PropertyInfo pi, ref string columnName, ref bool resultColumn) - { - return true; - } - - public Func GetFromDbConverter(PropertyInfo pi, Type sourceType) - { - return null; - } - - public Func GetToDbConverter(Type sourceType) - { - //We need this check to ensure that PetaPoco doesn't try to insert an invalid - //date from a nullable DateTime property. - if (sourceType == typeof(DateTime)) - { - return datetimeVal => - { - var datetime = datetimeVal as DateTime?; - if (datetime.HasValue && datetime.Value > DateTime.MinValue) - return datetime.Value; - - return null; - }; - } - - return null; - } - } -} \ No newline at end of file diff --git a/src/Umbraco.Core/Persistence/Mappers/PocoMapper.cs b/src/Umbraco.Core/Persistence/Mappers/PocoMapper.cs new file mode 100644 index 0000000000..281e05499c --- /dev/null +++ b/src/Umbraco.Core/Persistence/Mappers/PocoMapper.cs @@ -0,0 +1,31 @@ +using System; +using System.Reflection; +using NPoco; + +namespace Umbraco.Core.Persistence.Mappers +{ + /// + /// Extends NPoco default mapper and ensures that nullable dates are not saved to the database. + /// + public class PocoMapper : DefaultMapper + { + public override Func GetToDbConverter(Type destType, MemberInfo sourceMemberInfo) + { + // ensures that NPoco does not try to insert an invalid date + // from a nullable DateTime property + if (sourceMemberInfo.GetMemberInfoType() == typeof(DateTime)) + { + return datetimeVal => + { + var datetime = datetimeVal as DateTime?; + if (datetime.HasValue && datetime.Value > DateTime.MinValue) + return datetime.Value; + + return null; + }; + } + + return null; + } + } +} \ No newline at end of file diff --git a/src/Umbraco.Core/Persistence/Migrations/IMigrationContext.cs b/src/Umbraco.Core/Persistence/Migrations/IMigrationContext.cs index b162eba305..4440e7d2e3 100644 --- a/src/Umbraco.Core/Persistence/Migrations/IMigrationContext.cs +++ b/src/Umbraco.Core/Persistence/Migrations/IMigrationContext.cs @@ -1,4 +1,5 @@ using System.Collections.Generic; +using NPoco; using Umbraco.Core.Persistence.SqlSyntax; namespace Umbraco.Core.Persistence.Migrations diff --git a/src/Umbraco.Core/Persistence/Migrations/IMigrationExpression.cs b/src/Umbraco.Core/Persistence/Migrations/IMigrationExpression.cs index c8d36de915..4ea66b869f 100644 --- a/src/Umbraco.Core/Persistence/Migrations/IMigrationExpression.cs +++ b/src/Umbraco.Core/Persistence/Migrations/IMigrationExpression.cs @@ -1,4 +1,6 @@ -namespace Umbraco.Core.Persistence.Migrations +using NPoco; + +namespace Umbraco.Core.Persistence.Migrations { /// /// Marker interface for migration expressions diff --git a/src/Umbraco.Core/Persistence/Migrations/Initial/BaseDataCreation.cs b/src/Umbraco.Core/Persistence/Migrations/Initial/BaseDataCreation.cs index 7e70adb10f..66d9c8be0c 100644 --- a/src/Umbraco.Core/Persistence/Migrations/Initial/BaseDataCreation.cs +++ b/src/Umbraco.Core/Persistence/Migrations/Initial/BaseDataCreation.cs @@ -1,4 +1,5 @@ using System; +using NPoco; using Umbraco.Core.Configuration; using Umbraco.Core.Logging; using Umbraco.Core.Models.Rdbms; diff --git a/src/Umbraco.Core/Persistence/Migrations/Initial/DatabaseSchemaCreation.cs b/src/Umbraco.Core/Persistence/Migrations/Initial/DatabaseSchemaCreation.cs index f789c18aa1..e89d7367ec 100644 --- a/src/Umbraco.Core/Persistence/Migrations/Initial/DatabaseSchemaCreation.cs +++ b/src/Umbraco.Core/Persistence/Migrations/Initial/DatabaseSchemaCreation.cs @@ -1,6 +1,7 @@ using System; using System.Collections.Generic; using System.Linq; +using NPoco; using Umbraco.Core.Events; using Umbraco.Core.Logging; using Umbraco.Core.Models.Rdbms; diff --git a/src/Umbraco.Core/Persistence/Migrations/MigrationBase.cs b/src/Umbraco.Core/Persistence/Migrations/MigrationBase.cs index 70821d301f..966a0715c7 100644 --- a/src/Umbraco.Core/Persistence/Migrations/MigrationBase.cs +++ b/src/Umbraco.Core/Persistence/Migrations/MigrationBase.cs @@ -1,4 +1,5 @@ using System; +using NPoco; using Umbraco.Core.Logging; using Umbraco.Core.Persistence.Migrations.Syntax.Alter; using Umbraco.Core.Persistence.Migrations.Syntax.Create; @@ -79,5 +80,10 @@ namespace Umbraco.Core.Persistence.Migrations { return new IfDatabaseBuilder(Context, SqlSyntax, databaseProviders); } + + protected Sql Sql() + { + return NPoco.Sql.BuilderFor(new SqlContext(SqlSyntax, Context.Database)); + } } } \ No newline at end of file diff --git a/src/Umbraco.Core/Persistence/Migrations/MigrationContext.cs b/src/Umbraco.Core/Persistence/Migrations/MigrationContext.cs index c2f0b6051d..8126a402f2 100644 --- a/src/Umbraco.Core/Persistence/Migrations/MigrationContext.cs +++ b/src/Umbraco.Core/Persistence/Migrations/MigrationContext.cs @@ -1,6 +1,7 @@ using System; using System.Collections.Generic; using System.Collections.ObjectModel; +using NPoco; using Umbraco.Core.Logging; using Umbraco.Core.Persistence.SqlSyntax; diff --git a/src/Umbraco.Core/Persistence/Migrations/MigrationExpressionBase.cs b/src/Umbraco.Core/Persistence/Migrations/MigrationExpressionBase.cs index 6c3ef66735..8a0e0d7063 100644 --- a/src/Umbraco.Core/Persistence/Migrations/MigrationExpressionBase.cs +++ b/src/Umbraco.Core/Persistence/Migrations/MigrationExpressionBase.cs @@ -1,5 +1,6 @@ using System; using System.Linq; +using NPoco; using Umbraco.Core.Logging; using Umbraco.Core.Persistence.SqlSyntax; diff --git a/src/Umbraco.Core/Persistence/Migrations/MigrationRunner.cs b/src/Umbraco.Core/Persistence/Migrations/MigrationRunner.cs index 3c70cf6bcb..dbb98c877f 100644 --- a/src/Umbraco.Core/Persistence/Migrations/MigrationRunner.cs +++ b/src/Umbraco.Core/Persistence/Migrations/MigrationRunner.cs @@ -5,6 +5,7 @@ using System.IO; using System.Linq; using System.Text; using log4net; +using NPoco; using Semver; using Umbraco.Core.Configuration; using Umbraco.Core.Events; @@ -51,7 +52,7 @@ namespace Umbraco.Core.Persistence.Migrations /// /// Executes the migrations against the database. /// - /// The PetaPoco Database, which the migrations will be run against + /// The NPoco Database, which the migrations will be run against /// /// /// Boolean indicating whether this is an upgrade or downgrade @@ -67,7 +68,7 @@ namespace Umbraco.Core.Persistence.Migrations ? OrderedUpgradeMigrations(foundMigrations).ToList() : OrderedDowngradeMigrations(foundMigrations).ToList(); - + if (Migrating.IsRaisedEventCancelled(new MigrationEventArgs(migrations, _currentVersion, _targetVersion, _productName, true), this)) { _logger.Warn("Migration was cancelled by an event"); @@ -164,9 +165,9 @@ namespace Umbraco.Core.Persistence.Migrations } internal MigrationContext InitializeMigrations( - List migrations, - Database database, - DatabaseProviders databaseProvider, + List migrations, + Database database, + DatabaseProviders databaseProvider, ISqlSyntaxProvider sqlSyntax, bool isUpgrade = true) { @@ -242,7 +243,7 @@ namespace Umbraco.Core.Persistence.Migrations var exeSql = sb.ToString(); _logger.Info("Executing sql statement " + i + ": " + exeSql); database.Execute(exeSql); - + //restart the string builder sb.Remove(0, sb.Length); } @@ -259,7 +260,7 @@ namespace Umbraco.Core.Persistence.Migrations database.Execute(exeSql); } } - + i++; } @@ -273,9 +274,9 @@ namespace Umbraco.Core.Persistence.Migrations var exists = _migrationEntryService.FindEntry(_productName, _targetVersion); if (exists == null) { - _migrationEntryService.CreateEntry(_productName, _targetVersion); + _migrationEntryService.CreateEntry(_productName, _targetVersion); } - + } } diff --git a/src/Umbraco.Core/Persistence/Migrations/Syntax/Execute/ExecuteBuilder.cs b/src/Umbraco.Core/Persistence/Migrations/Syntax/Execute/ExecuteBuilder.cs index 549a4a0c66..5d8bc6b965 100644 --- a/src/Umbraco.Core/Persistence/Migrations/Syntax/Execute/ExecuteBuilder.cs +++ b/src/Umbraco.Core/Persistence/Migrations/Syntax/Execute/ExecuteBuilder.cs @@ -1,4 +1,5 @@ using System; +using NPoco; using Umbraco.Core.Persistence.Migrations.Syntax.Execute.Expressions; using Umbraco.Core.Persistence.SqlSyntax; diff --git a/src/Umbraco.Core/Persistence/Migrations/Syntax/Execute/Expressions/ExecuteCodeStatementExpression.cs b/src/Umbraco.Core/Persistence/Migrations/Syntax/Execute/Expressions/ExecuteCodeStatementExpression.cs index c5ab17db44..87ff16f31f 100644 --- a/src/Umbraco.Core/Persistence/Migrations/Syntax/Execute/Expressions/ExecuteCodeStatementExpression.cs +++ b/src/Umbraco.Core/Persistence/Migrations/Syntax/Execute/Expressions/ExecuteCodeStatementExpression.cs @@ -1,4 +1,5 @@ using System; +using NPoco; using Umbraco.Core.Persistence.SqlSyntax; namespace Umbraco.Core.Persistence.Migrations.Syntax.Execute.Expressions diff --git a/src/Umbraco.Core/Persistence/Migrations/Syntax/Execute/IExecuteBuilder.cs b/src/Umbraco.Core/Persistence/Migrations/Syntax/Execute/IExecuteBuilder.cs index 46717e0a3f..1d4c8e3f55 100644 --- a/src/Umbraco.Core/Persistence/Migrations/Syntax/Execute/IExecuteBuilder.cs +++ b/src/Umbraco.Core/Persistence/Migrations/Syntax/Execute/IExecuteBuilder.cs @@ -1,4 +1,5 @@ using System; +using NPoco; namespace Umbraco.Core.Persistence.Migrations.Syntax.Execute { diff --git a/src/Umbraco.Core/Persistence/Migrations/Syntax/Rename/Expressions/RenameColumnExpression.cs b/src/Umbraco.Core/Persistence/Migrations/Syntax/Rename/Expressions/RenameColumnExpression.cs index c99a1f95f8..db1ebde5d9 100644 --- a/src/Umbraco.Core/Persistence/Migrations/Syntax/Rename/Expressions/RenameColumnExpression.cs +++ b/src/Umbraco.Core/Persistence/Migrations/Syntax/Rename/Expressions/RenameColumnExpression.cs @@ -1,4 +1,5 @@ -using Umbraco.Core.Persistence.SqlSyntax; +using NPoco; +using Umbraco.Core.Persistence.SqlSyntax; namespace Umbraco.Core.Persistence.Migrations.Syntax.Rename.Expressions { diff --git a/src/Umbraco.Core/Persistence/Migrations/Upgrades/TargetVersionSeven/UpdateRelatedLinksData.cs b/src/Umbraco.Core/Persistence/Migrations/Upgrades/TargetVersionSeven/UpdateRelatedLinksData.cs index d65fc90bcc..121d6d7ff3 100644 --- a/src/Umbraco.Core/Persistence/Migrations/Upgrades/TargetVersionSeven/UpdateRelatedLinksData.cs +++ b/src/Umbraco.Core/Persistence/Migrations/Upgrades/TargetVersionSeven/UpdateRelatedLinksData.cs @@ -9,6 +9,7 @@ using System.Web.Script.Serialization; using System.Xml; using System.Xml.Linq; using Newtonsoft.Json; +using NPoco; using Umbraco.Core.Configuration; using Umbraco.Core.Logging; using Umbraco.Core.Models.Rdbms; @@ -33,8 +34,8 @@ namespace Umbraco.Core.Persistence.Migrations.Upgrades.TargetVersionSeven { if (database != null) { - var dtSql = new Sql().Select("nodeId").From(SqlSyntax) - .Where(SqlSyntax, dto => dto.PropertyEditorAlias == Constants.PropertyEditors.RelatedLinksAlias); + var dtSql = Sql().Select("nodeId").From() + .Where(dto => dto.PropertyEditorAlias == Constants.PropertyEditors.RelatedLinksAlias); var dataTypeIds = database.Fetch(dtSql); if (!dataTypeIds.Any()) return string.Empty; diff --git a/src/Umbraco.Core/Persistence/Migrations/Upgrades/TargetVersionSevenFourZero/AddUniqueIdPropertyTypeGroupColumn.cs b/src/Umbraco.Core/Persistence/Migrations/Upgrades/TargetVersionSevenFourZero/AddUniqueIdPropertyTypeGroupColumn.cs index fe600f6b69..c8ba7325a6 100644 --- a/src/Umbraco.Core/Persistence/Migrations/Upgrades/TargetVersionSevenFourZero/AddUniqueIdPropertyTypeGroupColumn.cs +++ b/src/Umbraco.Core/Persistence/Migrations/Upgrades/TargetVersionSevenFourZero/AddUniqueIdPropertyTypeGroupColumn.cs @@ -2,6 +2,7 @@ using System; using System.Collections; using System.Collections.Generic; using System.Linq; +using NPoco; using Umbraco.Core.Configuration; using Umbraco.Core.Logging; using Umbraco.Core.Persistence.DatabaseModelDefinitions; diff --git a/src/Umbraco.Core/Persistence/Migrations/Upgrades/TargetVersionSevenFourZero/EnsureContentTypeUniqueIdsAreConsistent.cs b/src/Umbraco.Core/Persistence/Migrations/Upgrades/TargetVersionSevenFourZero/EnsureContentTypeUniqueIdsAreConsistent.cs index 4d017dd230..c040fd7349 100644 --- a/src/Umbraco.Core/Persistence/Migrations/Upgrades/TargetVersionSevenFourZero/EnsureContentTypeUniqueIdsAreConsistent.cs +++ b/src/Umbraco.Core/Persistence/Migrations/Upgrades/TargetVersionSevenFourZero/EnsureContentTypeUniqueIdsAreConsistent.cs @@ -1,5 +1,6 @@ using System; using System.Linq; +using NPoco; using Umbraco.Core.Configuration; using Umbraco.Core.Logging; using Umbraco.Core.Models.Rdbms; @@ -28,12 +29,12 @@ namespace Umbraco.Core.Persistence.Migrations.Upgrades.TargetVersionSevenFourZer Constants.ObjectTypes.MemberTypeGuid, }; - var sql = new Sql() + var sql = NPoco.Sql.BuilderFor(new SqlContext(SqlSyntax, Context.Database)) .Select("umbracoNode.id,cmsContentType.alias,umbracoNode.nodeObjectType") - .From(SqlSyntax) - .InnerJoin(SqlSyntax) - .On(SqlSyntax, dto => dto.NodeId, dto => dto.NodeId) - .WhereIn(SqlSyntax, x => x.NodeObjectType, objectTypes); + .From() + .InnerJoin() + .On(dto => dto.NodeId, dto => dto.NodeId) + .WhereIn(x => x.NodeObjectType, objectTypes); var rows = Context.Database.Fetch(sql); diff --git a/src/Umbraco.Core/Persistence/Migrations/Upgrades/TargetVersionSevenFourZero/FixListViewMediaSortOrder.cs b/src/Umbraco.Core/Persistence/Migrations/Upgrades/TargetVersionSevenFourZero/FixListViewMediaSortOrder.cs index 00915e1947..323248d5d5 100644 --- a/src/Umbraco.Core/Persistence/Migrations/Upgrades/TargetVersionSevenFourZero/FixListViewMediaSortOrder.cs +++ b/src/Umbraco.Core/Persistence/Migrations/Upgrades/TargetVersionSevenFourZero/FixListViewMediaSortOrder.cs @@ -1,4 +1,5 @@ using System.Linq; +using NPoco; using Umbraco.Core.Configuration; using Umbraco.Core.Logging; using Umbraco.Core.Models.Rdbms; @@ -17,7 +18,7 @@ namespace Umbraco.Core.Persistence.Migrations.Upgrades.TargetVersionSevenFourZer public override void Up() { var mediaListviewIncludeProperties = Context.Database.Fetch( - new Sql().Select("*").From(SqlSyntax).Where(SqlSyntax, x => x.Id == -9)).FirstOrDefault(); + Sql().SelectAll().From().Where(x => x.Id == -9)).FirstOrDefault(); if (mediaListviewIncludeProperties != null) { if (mediaListviewIncludeProperties.Value.Contains("\"alias\":\"sort\"")) diff --git a/src/Umbraco.Core/Persistence/Migrations/Upgrades/TargetVersionSevenThreeOne/UpdateUserLanguagesToIsoCode.cs b/src/Umbraco.Core/Persistence/Migrations/Upgrades/TargetVersionSevenThreeOne/UpdateUserLanguagesToIsoCode.cs index 50f78ca66d..5c61c03723 100644 --- a/src/Umbraco.Core/Persistence/Migrations/Upgrades/TargetVersionSevenThreeOne/UpdateUserLanguagesToIsoCode.cs +++ b/src/Umbraco.Core/Persistence/Migrations/Upgrades/TargetVersionSevenThreeOne/UpdateUserLanguagesToIsoCode.cs @@ -1,4 +1,5 @@ using System.Linq; +using NPoco; using Umbraco.Core.Configuration; using Umbraco.Core.Logging; using Umbraco.Core.Models.Rdbms; @@ -18,7 +19,7 @@ namespace Umbraco.Core.Persistence.Migrations.Upgrades.TargetVersionSevenThreeOn public override void Up() { - var userData = Context.Database.Fetch(new Sql().Select("*").From(SqlSyntax)); + var userData = Context.Database.Fetch(Sql().SelectAll().From()); foreach (var user in userData.Where(x => x.UserLanguage.Contains("_"))) { var languageParts = user.UserLanguage.Split('_'); diff --git a/src/Umbraco.Core/Persistence/Migrations/Upgrades/TargetVersionSevenThreeTwo/EnsureMigrationsTableIdentityIsCorrect.cs b/src/Umbraco.Core/Persistence/Migrations/Upgrades/TargetVersionSevenThreeTwo/EnsureMigrationsTableIdentityIsCorrect.cs index 91b4bd6438..06a3995c36 100644 --- a/src/Umbraco.Core/Persistence/Migrations/Upgrades/TargetVersionSevenThreeTwo/EnsureMigrationsTableIdentityIsCorrect.cs +++ b/src/Umbraco.Core/Persistence/Migrations/Upgrades/TargetVersionSevenThreeTwo/EnsureMigrationsTableIdentityIsCorrect.cs @@ -1,4 +1,5 @@ using System.Collections.Generic; +using NPoco; using Umbraco.Core.Configuration; using Umbraco.Core.Logging; using Umbraco.Core.Models.Rdbms; @@ -25,7 +26,7 @@ namespace Umbraco.Core.Persistence.Migrations.Upgrades.TargetVersionSevenThreeTw List migrations = null; Execute.Code(db => { - migrations = Context.Database.Fetch(new Sql().Select("*").From(SqlSyntax)); + migrations = Context.Database.Fetch(Sql().SelectAll().From()); return string.Empty; }); Delete.FromTable("umbracoMigration").AllRows(); diff --git a/src/Umbraco.Core/Persistence/Migrations/Upgrades/TargetVersionSevenThreeZero/AddForeignKeysForLanguageAndDictionaryTables.cs b/src/Umbraco.Core/Persistence/Migrations/Upgrades/TargetVersionSevenThreeZero/AddForeignKeysForLanguageAndDictionaryTables.cs index eea56031d4..7bc94cdaba 100644 --- a/src/Umbraco.Core/Persistence/Migrations/Upgrades/TargetVersionSevenThreeZero/AddForeignKeysForLanguageAndDictionaryTables.cs +++ b/src/Umbraco.Core/Persistence/Migrations/Upgrades/TargetVersionSevenThreeZero/AddForeignKeysForLanguageAndDictionaryTables.cs @@ -1,6 +1,7 @@ using System; using System.Data; using System.Linq; +using NPoco; using Umbraco.Core.Configuration; using Umbraco.Core.Logging; using Umbraco.Core.Models.Rdbms; @@ -45,7 +46,7 @@ namespace Umbraco.Core.Persistence.Migrations.Upgrades.TargetVersionSevenThreeZe .WithColumn("languageISOCode").AsString(10).Nullable() .WithColumn("languageCultureName").AsString(50).Nullable(); - var currentData = this.Context.Database.Fetch(new Sql().Select("*").From(SqlSyntax)); + var currentData = Context.Database.Fetch(Sql().SelectAll().From()); foreach (var languageDto in currentData) { Insert.IntoTable("umbracoLanguage_TEMP") diff --git a/src/Umbraco.Core/Persistence/Migrations/Upgrades/TargetVersionSevenThreeZero/MigrateAndRemoveTemplateMasterColumn.cs b/src/Umbraco.Core/Persistence/Migrations/Upgrades/TargetVersionSevenThreeZero/MigrateAndRemoveTemplateMasterColumn.cs index 8ef10b178f..c5ca312123 100644 --- a/src/Umbraco.Core/Persistence/Migrations/Upgrades/TargetVersionSevenThreeZero/MigrateAndRemoveTemplateMasterColumn.cs +++ b/src/Umbraco.Core/Persistence/Migrations/Upgrades/TargetVersionSevenThreeZero/MigrateAndRemoveTemplateMasterColumn.cs @@ -1,5 +1,6 @@ using System.Collections.Generic; using System.Linq; +using NPoco; using Umbraco.Core.Configuration; using Umbraco.Core.Logging; using Umbraco.Core.Models.Rdbms; @@ -74,7 +75,7 @@ namespace Umbraco.Core.Persistence.Migrations.Upgrades.TargetVersionSevenThreeZe Execute.Code(database => { //NOTE: we are using dynamic because we need to get the data in a column that no longer exists in the schema - var templates = database.Fetch(new Sql().Select("*").From(SqlSyntax)); + var templates = database.Fetch(Sql().SelectAll().From()); foreach (var template in templates) { var sql = string.Format(SqlSyntax.UpdateData, diff --git a/src/Umbraco.Core/Persistence/Migrations/Upgrades/TargetVersionSevenThreeZero/MovePublicAccessXmlDataToDb.cs b/src/Umbraco.Core/Persistence/Migrations/Upgrades/TargetVersionSevenThreeZero/MovePublicAccessXmlDataToDb.cs index de7c4e09aa..19d44ba3f9 100644 --- a/src/Umbraco.Core/Persistence/Migrations/Upgrades/TargetVersionSevenThreeZero/MovePublicAccessXmlDataToDb.cs +++ b/src/Umbraco.Core/Persistence/Migrations/Upgrades/TargetVersionSevenThreeZero/MovePublicAccessXmlDataToDb.cs @@ -2,6 +2,7 @@ using System; using System.IO; using System.Linq; using System.Xml.Linq; +using NPoco; using Umbraco.Core.Configuration; using Umbraco.Core.IO; using Umbraco.Core.Logging; @@ -25,7 +26,7 @@ namespace Umbraco.Core.Persistence.Migrations.Upgrades.TargetVersionSevenThreeZe if (tables.InvariantContains("umbracoAccess")) { //don't run if data is already there. - var dataExists = Context.Database.Fetch(new Sql().Select("*").From(SqlSyntax)); + var dataExists = Context.Database.Fetch(Sql().SelectAll().From()); if (dataExists.Any()) return; } diff --git a/src/Umbraco.Core/Persistence/Migrations/Upgrades/TargetVersionSixTwoZero/AddChangeDocumentTypePermission.cs b/src/Umbraco.Core/Persistence/Migrations/Upgrades/TargetVersionSixTwoZero/AddChangeDocumentTypePermission.cs index 6c4f6ea97b..3b82a02c47 100644 --- a/src/Umbraco.Core/Persistence/Migrations/Upgrades/TargetVersionSixTwoZero/AddChangeDocumentTypePermission.cs +++ b/src/Umbraco.Core/Persistence/Migrations/Upgrades/TargetVersionSixTwoZero/AddChangeDocumentTypePermission.cs @@ -1,4 +1,5 @@ using System.Linq; +using NPoco; using Umbraco.Core.Configuration; using Umbraco.Core.Logging; using Umbraco.Core.Models.Rdbms; @@ -34,7 +35,7 @@ namespace Umbraco.Core.Persistence.Migrations.Upgrades.TargetVersionSixTwoZero if (adminUserType.DefaultPermissions.Contains("7") == false) { adminUserType.DefaultPermissions = adminUserType.DefaultPermissions + "7"; - database.Save(adminUserType); + database.Save(adminUserType); } } @@ -50,7 +51,7 @@ namespace Umbraco.Core.Persistence.Migrations.Upgrades.TargetVersionSixTwoZero if (adminUserType.DefaultPermissions.Contains("7")) { adminUserType.DefaultPermissions = adminUserType.DefaultPermissions.Replace("7", ""); - database.Save(adminUserType); + database.Save(adminUserType); } } diff --git a/src/Umbraco.Core/Persistence/Migrations/Upgrades/TargetVersionSixTwoZero/UpdateToNewMemberPropertyAliases.cs b/src/Umbraco.Core/Persistence/Migrations/Upgrades/TargetVersionSixTwoZero/UpdateToNewMemberPropertyAliases.cs index a0b64a9830..311672f237 100644 --- a/src/Umbraco.Core/Persistence/Migrations/Upgrades/TargetVersionSixTwoZero/UpdateToNewMemberPropertyAliases.cs +++ b/src/Umbraco.Core/Persistence/Migrations/Upgrades/TargetVersionSixTwoZero/UpdateToNewMemberPropertyAliases.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using NPoco; using Umbraco.Core.Configuration; using Umbraco.Core.Logging; using Umbraco.Core.Models.Rdbms; diff --git a/src/Umbraco.Core/Persistence/Migrations/Upgrades/TargetVersionSixZeroOne/UpdatePropertyTypesAndGroups.cs b/src/Umbraco.Core/Persistence/Migrations/Upgrades/TargetVersionSixZeroOne/UpdatePropertyTypesAndGroups.cs index 9a2b47d79d..b96aedaca2 100644 --- a/src/Umbraco.Core/Persistence/Migrations/Upgrades/TargetVersionSixZeroOne/UpdatePropertyTypesAndGroups.cs +++ b/src/Umbraco.Core/Persistence/Migrations/Upgrades/TargetVersionSixZeroOne/UpdatePropertyTypesAndGroups.cs @@ -1,5 +1,6 @@ using System; using System.Linq; +using NPoco; using Umbraco.Core.Configuration; using Umbraco.Core.Logging; using Umbraco.Core.Models.Rdbms; diff --git a/src/Umbraco.Core/Persistence/PetaPocoExtensions.cs b/src/Umbraco.Core/Persistence/NPocoDatabaseExtensions.cs similarity index 87% rename from src/Umbraco.Core/Persistence/PetaPocoExtensions.cs rename to src/Umbraco.Core/Persistence/NPocoDatabaseExtensions.cs index 4c8d72ceec..b7e3407176 100644 --- a/src/Umbraco.Core/Persistence/PetaPocoExtensions.cs +++ b/src/Umbraco.Core/Persistence/NPocoDatabaseExtensions.cs @@ -1,331 +1,337 @@ -using System; -using System.Collections.Generic; -using System.Data; -using System.Data.Common; -using System.Data.SqlClient; -using System.Linq; -using System.Text.RegularExpressions; -using Umbraco.Core.Logging; -using Umbraco.Core.Persistence.Querying; -using Umbraco.Core.Persistence.SqlSyntax; - -namespace Umbraco.Core.Persistence -{ - public static class PetaPocoExtensions - { - // NOTE - // - // proper way to do it with TSQL and SQLCE - // IF EXISTS (SELECT ... FROM table WITH (UPDLOCK,HOLDLOCK)) WHERE ...) - // BEGIN - // UPDATE table SET ... WHERE ... - // END - // ELSE - // BEGIN - // INSERT INTO table (...) VALUES (...) - // END - // - // works in READ COMMITED, TSQL & SQLCE lock the constraint even if it does not exist, so INSERT is OK - // - // proper way to do it with MySQL - // IF EXISTS (SELECT ... FROM table WHERE ... FOR UPDATE) - // BEGIN - // UPDATE table SET ... WHERE ... - // END - // ELSE - // BEGIN - // INSERT INTO table (...) VALUES (...) - // END - // - // MySQL locks the constraint ONLY if it exists, so INSERT may fail... - // in theory, happens in READ COMMITTED but not REPEATABLE READ - // http://www.percona.com/blog/2012/08/28/differences-between-read-committed-and-repeatable-read-transaction-isolation-levels/ - // but according to - // http://dev.mysql.com/doc/refman/5.0/en/set-transaction.html - // it won't work for exact index value (only ranges) so really... - // - // MySQL should do - // INSERT INTO table (...) VALUES (...) ON DUPLICATE KEY UPDATE ... - // - // also the lock is released when the transaction is committed - // not sure if that can have unexpected consequences on our code? - // - // so... for the time being, let's do with that somewhat crazy solution below... - - /// - /// Safely inserts a record, or updates if it exists, based on a unique constraint. - /// - /// - /// - /// The action that executed, either an insert or an update. If an insert occurred and a PK value got generated, the poco object - /// passed in will contain the updated value. - /// - /// We cannot rely on database-specific options such as MySql ON DUPLICATE KEY UPDATE or MSSQL MERGE WHEN MATCHED because SQLCE - /// does not support any of them. Ideally this should be achieved with proper transaction isolation levels but that would mean revisiting - /// isolation levels globally. We want to keep it simple for the time being and manage it manually. - /// We handle it by trying to update, then insert, etc. until something works, or we get bored. - /// Note that with proper transactions, if T2 begins after T1 then we are sure that the database will contain T2's value - /// once T1 and T2 have completed. Whereas here, it could contain T1's value. - /// - internal static RecordPersistenceType InsertOrUpdate(this Database db, T poco) - where T : class - { - return db.InsertOrUpdate(poco, null, null); - } - - /// - /// Safely inserts a record, or updates if it exists, based on a unique constraint. - /// - /// - /// - /// - /// If the entity has a composite key they you need to specify the update command explicitly - /// The action that executed, either an insert or an update. If an insert occurred and a PK value got generated, the poco object - /// passed in will contain the updated value. - /// - /// We cannot rely on database-specific options such as MySql ON DUPLICATE KEY UPDATE or MSSQL MERGE WHEN MATCHED because SQLCE - /// does not support any of them. Ideally this should be achieved with proper transaction isolation levels but that would mean revisiting - /// isolation levels globally. We want to keep it simple for the time being and manage it manually. - /// We handle it by trying to update, then insert, etc. until something works, or we get bored. - /// Note that with proper transactions, if T2 begins after T1 then we are sure that the database will contain T2's value - /// once T1 and T2 have completed. Whereas here, it could contain T1's value. - /// - internal static RecordPersistenceType InsertOrUpdate(this Database db, - T poco, - string updateCommand, - object updateArgs) - where T : class - { - if (poco == null) - throw new ArgumentNullException("poco"); - - // try to update - var rowCount = updateCommand.IsNullOrWhiteSpace() - ? db.Update(poco) - : db.Update(updateCommand, updateArgs); - if (rowCount > 0) - return RecordPersistenceType.Update; - - // failed: does not exist, need to insert - // RC1 race cond here: another thread may insert a record with the same constraint - - var i = 0; - while (i++ < 4) - { - try - { - // try to insert - db.Insert(poco); - return RecordPersistenceType.Insert; - } - catch (SqlException) // TODO: need to find out if all db will throw that exception - probably OK - { - // failed: exists (due to race cond RC1) - // RC2 race cond here: another thread may remove the record - - // try to update - rowCount = updateCommand.IsNullOrWhiteSpace() - ? db.Update(poco) - : db.Update(updateCommand, updateArgs); - if (rowCount > 0) - return RecordPersistenceType.Update; - - // failed: does not exist (due to race cond RC2), need to insert - // loop - } - } - - // this can go on forever... have to break at some point and report an error. - throw new DataException("Record could not be inserted or updated."); - } - - /// - /// This will escape single @ symbols for peta poco values so it doesn't think it's a parameter - /// - /// - /// - public static string EscapeAtSymbols(string value) - { - if (value.Contains("@")) - { - //this fancy regex will only match a single @ not a double, etc... - var regex = new Regex("(?(this Database db, ISqlSyntaxProvider sqlSyntax, IEnumerable collection) - { - //don't do anything if there are no records. - if (collection.Any() == false) - return; - - using (var tr = db.GetTransaction()) - { - db.BulkInsertRecords(sqlSyntax, collection, tr, true); - } - } - - /// - /// Performs the bulk insertion in the context of a current transaction with an optional parameter to complete the transaction - /// when finished - /// - /// - /// - /// - /// - /// - /// - public static void BulkInsertRecords(this Database db, ISqlSyntaxProvider sqlSyntax, IEnumerable collection, Transaction tr, bool commitTrans = false) - { - //don't do anything if there are no records. - if (collection.Any() == false) - return; - - try - { - //if it is sql ce or it is a sql server version less than 2008, we need to do individual inserts. - var sqlServerSyntax = sqlSyntax as SqlServerSyntaxProvider; - if ((sqlServerSyntax != null && (int)sqlServerSyntax.VersionName.Value < (int)SqlServerVersionName.V2008) - || sqlSyntax is SqlCeSyntaxProvider) - { - //SqlCe doesn't support bulk insert statements! - - foreach (var poco in collection) - { - db.Insert(poco); - } - } - else - { - string[] sqlStatements; - var cmds = db.GenerateBulkInsertCommand(collection, db.Connection, out sqlStatements); - for (var i = 0; i < sqlStatements.Length; i++) - { - using (var cmd = cmds[i]) - { - cmd.CommandText = sqlStatements[i]; - cmd.ExecuteNonQuery(); - } - } - } - - if (commitTrans) - { - tr.Complete(); - } - } - catch - { - if (commitTrans) - { - tr.Dispose(); - } - throw; - } - } - - /// - /// Creates a bulk insert command - /// - /// - /// - /// - /// - /// - /// Sql commands with populated command parameters required to execute the sql statement - /// - /// The limits for number of parameters are 2100 (in sql server, I think there's many more allowed in mysql). So - /// we need to detect that many params and split somehow. - /// For some reason the 2100 limit is not actually allowed even though the exception from sql server mentions 2100 as a max, perhaps it is 2099 - /// that is max. I've reduced it to 2000 anyways. - /// - internal static IDbCommand[] GenerateBulkInsertCommand( - this Database db, - IEnumerable collection, - IDbConnection connection, - out string[] sql) - { - //A filter used below a few times to get all columns except result cols and not the primary key if it is auto-incremental - Func, bool> includeColumn = (data, column) => - { - if (column.Value.ResultColumn) return false; - if (data.TableInfo.AutoIncrement && column.Key == data.TableInfo.PrimaryKey) return false; - return true; - }; - - var pd = Database.PocoData.ForType(typeof(T)); - var tableName = db.EscapeTableName(pd.TableInfo.TableName); - - //get all columns to include and format for sql - var cols = string.Join(", ", - pd.Columns - .Where(c => includeColumn(pd, c)) - .Select(c => tableName + "." + db.EscapeSqlIdentifier(c.Key)).ToArray()); - - var itemArray = collection.ToArray(); - - //calculate number of parameters per item - var paramsPerItem = pd.Columns.Count(i => includeColumn(pd, i)); - - //Example calc: - // Given: we have 4168 items in the itemArray, each item contains 8 command parameters (values to be inserterted) - // 2100 / 8 = 262.5 - // Math.Floor(2100 / 8) = 262 items per trans - // 4168 / 262 = 15.908... = there will be 16 trans in total - - //all items will be included if we have disabled db parameters - var itemsPerTrans = Math.Floor(2000.00 / paramsPerItem); - //there will only be one transaction if we have disabled db parameters - var numTrans = Math.Ceiling(itemArray.Length / itemsPerTrans); - - var sqlQueries = new List(); - var commands = new List(); - - for (var tIndex = 0; tIndex < numTrans; tIndex++) - { - var itemsForTrans = itemArray - .Skip(tIndex * (int)itemsPerTrans) - .Take((int)itemsPerTrans); - - var cmd = db.CreateCommand(connection, ""); - var pocoValues = new List(); - var index = 0; - foreach (var poco in itemsForTrans) - { - var values = new List(); - //get all columns except result cols and not the primary key if it is auto-incremental - foreach (var i in pd.Columns.Where(x => includeColumn(pd, x))) - { - db.AddParam(cmd, i.Value.GetValue(poco), "@"); - values.Add(string.Format("{0}{1}", "@", index++)); - } - pocoValues.Add("(" + string.Join(",", values.ToArray()) + ")"); - } - - var sqlResult = string.Format("INSERT INTO {0} ({1}) VALUES {2}", tableName, cols, string.Join(", ", pocoValues)); - sqlQueries.Add(sqlResult); - commands.Add(cmd); - } - - sql = sqlQueries.ToArray(); - - return commands.ToArray(); - } - - public static void TruncateTable(this Database db, ISqlSyntaxProvider sqlSyntax, string tableName) - { - var sql = new Sql(string.Format( - sqlSyntax.TruncateTable, - sqlSyntax.GetQuotedTableName(tableName))); - db.Execute(sql); - } - - - } - - +using System; +using System.Collections.Generic; +using System.Data; +using System.Data.Common; +using System.Data.SqlClient; +using System.Linq; +using System.Text.RegularExpressions; +using NPoco; +using Umbraco.Core.Persistence.SqlSyntax; + +namespace Umbraco.Core.Persistence +{ + /// + /// Provides extension methods to NPoco Database class. + /// + public static class NPocoDatabaseExtensions + { + // NOTE + // + // proper way to do it with TSQL and SQLCE + // IF EXISTS (SELECT ... FROM table WITH (UPDLOCK,HOLDLOCK)) WHERE ...) + // BEGIN + // UPDATE table SET ... WHERE ... + // END + // ELSE + // BEGIN + // INSERT INTO table (...) VALUES (...) + // END + // + // works in READ COMMITED, TSQL & SQLCE lock the constraint even if it does not exist, so INSERT is OK + // + // proper way to do it with MySQL + // IF EXISTS (SELECT ... FROM table WHERE ... FOR UPDATE) + // BEGIN + // UPDATE table SET ... WHERE ... + // END + // ELSE + // BEGIN + // INSERT INTO table (...) VALUES (...) + // END + // + // MySQL locks the constraint ONLY if it exists, so INSERT may fail... + // in theory, happens in READ COMMITTED but not REPEATABLE READ + // http://www.percona.com/blog/2012/08/28/differences-between-read-committed-and-repeatable-read-transaction-isolation-levels/ + // but according to + // http://dev.mysql.com/doc/refman/5.0/en/set-transaction.html + // it won't work for exact index value (only ranges) so really... + // + // MySQL should do + // INSERT INTO table (...) VALUES (...) ON DUPLICATE KEY UPDATE ... + // + // also the lock is released when the transaction is committed + // not sure if that can have unexpected consequences on our code? + // + // so... for the time being, let's do with that somewhat crazy solution below... + + /// + /// Safely inserts a record, or updates if it exists, based on a unique constraint. + /// + /// + /// + /// The action that executed, either an insert or an update. If an insert occurred and a PK value got generated, the poco object + /// passed in will contain the updated value. + /// + /// We cannot rely on database-specific options such as MySql ON DUPLICATE KEY UPDATE or MSSQL MERGE WHEN MATCHED because SQLCE + /// does not support any of them. Ideally this should be achieved with proper transaction isolation levels but that would mean revisiting + /// isolation levels globally. We want to keep it simple for the time being and manage it manually. + /// We handle it by trying to update, then insert, etc. until something works, or we get bored. + /// Note that with proper transactions, if T2 begins after T1 then we are sure that the database will contain T2's value + /// once T1 and T2 have completed. Whereas here, it could contain T1's value. + /// + internal static RecordPersistenceType InsertOrUpdate(this Database db, T poco) + where T : class + { + return db.InsertOrUpdate(poco, null, null); + } + + /// + /// Safely inserts a record, or updates if it exists, based on a unique constraint. + /// + /// + /// + /// + /// If the entity has a composite key they you need to specify the update command explicitly + /// The action that executed, either an insert or an update. If an insert occurred and a PK value got generated, the poco object + /// passed in will contain the updated value. + /// + /// We cannot rely on database-specific options such as MySql ON DUPLICATE KEY UPDATE or MSSQL MERGE WHEN MATCHED because SQLCE + /// does not support any of them. Ideally this should be achieved with proper transaction isolation levels but that would mean revisiting + /// isolation levels globally. We want to keep it simple for the time being and manage it manually. + /// We handle it by trying to update, then insert, etc. until something works, or we get bored. + /// Note that with proper transactions, if T2 begins after T1 then we are sure that the database will contain T2's value + /// once T1 and T2 have completed. Whereas here, it could contain T1's value. + /// + internal static RecordPersistenceType InsertOrUpdate(this Database db, + T poco, + string updateCommand, + object updateArgs) + where T : class + { + if (poco == null) + throw new ArgumentNullException("poco"); + + // try to update + var rowCount = updateCommand.IsNullOrWhiteSpace() + ? db.Update(poco) + : db.Update(updateCommand, updateArgs); + if (rowCount > 0) + return RecordPersistenceType.Update; + + // failed: does not exist, need to insert + // RC1 race cond here: another thread may insert a record with the same constraint + + var i = 0; + while (i++ < 4) + { + try + { + // try to insert + db.Insert(poco); + return RecordPersistenceType.Insert; + } + catch (SqlException) // TODO: need to find out if all db will throw that exception - probably OK + { + // failed: exists (due to race cond RC1) + // RC2 race cond here: another thread may remove the record + + // try to update + rowCount = updateCommand.IsNullOrWhiteSpace() + ? db.Update(poco) + : db.Update(updateCommand, updateArgs); + if (rowCount > 0) + return RecordPersistenceType.Update; + + // failed: does not exist (due to race cond RC2), need to insert + // loop + } + } + + // this can go on forever... have to break at some point and report an error. + throw new DataException("Record could not be inserted or updated."); + } + + /// + /// This will escape single @ symbols for npoco values so it doesn't think it's a parameter + /// + /// + /// + public static string EscapeAtSymbols(string value) + { + if (value.Contains("@")) + { + //this fancy regex will only match a single @ not a double, etc... + var regex = new Regex("(?(this Database db, ISqlSyntaxProvider sqlSyntax, IEnumerable collection) + { + //don't do anything if there are no records. + if (collection.Any() == false) + return; + + using (var tr = db.GetTransaction()) + { + db.BulkInsertRecords(sqlSyntax, collection, tr, true); + } + } + + /// + /// Performs the bulk insertion in the context of a current transaction with an optional parameter to complete the transaction + /// when finished + /// + /// + /// + /// + /// + /// + /// + public static void BulkInsertRecords(this Database db, ISqlSyntaxProvider sqlSyntax, IEnumerable collection, ITransaction tr, bool commitTrans = false) + { + //don't do anything if there are no records. + if (collection.Any() == false) + return; + + try + { + //if it is sql ce or it is a sql server version less than 2008, we need to do individual inserts. + var sqlServerSyntax = sqlSyntax as SqlServerSyntaxProvider; + if ((sqlServerSyntax != null && (int)sqlServerSyntax.VersionName.Value < (int)SqlServerVersionName.V2008) + || sqlSyntax is SqlCeSyntaxProvider) + { + //SqlCe doesn't support bulk insert statements! + + foreach (var poco in collection) + { + db.Insert(poco); + } + } + else + { + string[] sqlStatements; + var cmds = db.GenerateBulkInsertCommand(collection, db.Connection, out sqlStatements); + for (var i = 0; i < sqlStatements.Length; i++) + { + using (var cmd = cmds[i]) + { + cmd.CommandText = sqlStatements[i]; + cmd.ExecuteNonQuery(); + } + } + } + + if (commitTrans) + { + tr.Complete(); + } + } + catch + { + if (commitTrans) + { + tr.Dispose(); + } + throw; + } + } + + /// + /// Creates a bulk insert command + /// + /// + /// + /// + /// + /// + /// Sql commands with populated command parameters required to execute the sql statement + /// + /// The limits for number of parameters are 2100 (in sql server, I think there's many more allowed in mysql). So + /// we need to detect that many params and split somehow. + /// For some reason the 2100 limit is not actually allowed even though the exception from sql server mentions 2100 as a max, perhaps it is 2099 + /// that is max. I've reduced it to 2000 anyways. + /// + internal static IDbCommand[] GenerateBulkInsertCommand( + this Database db, + IEnumerable collection, + DbConnection connection, + out string[] sql) + { + //A filter used below a few times to get all columns except result cols and not the primary key if it is auto-incremental + Func, bool> includeColumn = (data, column) => + { + if (column.Value.ResultColumn) return false; + if (data.TableInfo.AutoIncrement && column.Key == data.TableInfo.PrimaryKey) return false; + return true; + }; + + var pd = db.PocoDataFactory.ForType(typeof(T)); + var tableName = db.DatabaseType.EscapeTableName(pd.TableInfo.TableName); + + //get all columns to include and format for sql + var cols = string.Join(", ", + pd.Columns + .Where(c => includeColumn(pd, c)) + .Select(c => tableName + "." + db.DatabaseType.EscapeSqlIdentifier(c.Key)).ToArray()); + + var itemArray = collection.ToArray(); + + //calculate number of parameters per item + var paramsPerItem = pd.Columns.Count(i => includeColumn(pd, i)); + + //Example calc: + // Given: we have 4168 items in the itemArray, each item contains 8 command parameters (values to be inserterted) + // 2100 / 8 = 262.5 + // Math.Floor(2100 / 8) = 262 items per trans + // 4168 / 262 = 15.908... = there will be 16 trans in total + + //all items will be included if we have disabled db parameters + var itemsPerTrans = Math.Floor(2000.00 / paramsPerItem); + //there will only be one transaction if we have disabled db parameters + var numTrans = Math.Ceiling(itemArray.Length / itemsPerTrans); + + var sqlQueries = new List(); + var commands = new List(); + + for (var tIndex = 0; tIndex < numTrans; tIndex++) + { + var itemsForTrans = itemArray + .Skip(tIndex * (int)itemsPerTrans) + .Take((int)itemsPerTrans); + + var cmd = db.CreateCommand(connection, ""); + var pocoValues = new List(); + var index = 0; + foreach (var poco in itemsForTrans) + { + var values = new List(); + //get all columns except result cols and not the primary key if it is auto-incremental + var prefix = db.DatabaseType.GetParameterPrefix(cmd.Connection.ConnectionString); + foreach (var i in pd.Columns.Where(x => includeColumn(pd, x))) + { + db.AddParameter(cmd, i.Value.GetValue(poco)); + values.Add(prefix + index++); + } + pocoValues.Add("(" + string.Join(",", values.ToArray()) + ")"); + } + + var sqlResult = string.Format("INSERT INTO {0} ({1}) VALUES {2}", tableName, cols, string.Join(", ", pocoValues)); + sqlQueries.Add(sqlResult); + commands.Add(cmd); + } + + sql = sqlQueries.ToArray(); + + return commands.ToArray(); + } + + public static void TruncateTable(this Database db, ISqlSyntaxProvider sqlSyntax, string tableName) + { + var sql = new Sql(string.Format( + sqlSyntax.TruncateTable, + sqlSyntax.GetQuotedTableName(tableName))); + db.Execute(sql); + } + + public static IsolationLevel GetCurrentTransactionIsolationLevel(this Database database) + { + var transaction = database.Transaction; + return transaction == null ? IsolationLevel.Unspecified : transaction.IsolationLevel; + } + } } \ No newline at end of file diff --git a/src/Umbraco.Core/Persistence/PetaPoco.cs b/src/Umbraco.Core/Persistence/PetaPoco.cs deleted file mode 100644 index a174255746..0000000000 --- a/src/Umbraco.Core/Persistence/PetaPoco.cs +++ /dev/null @@ -1,2504 +0,0 @@ -/* PetaPoco v4.0.3 - A Tiny ORMish thing for your POCO's. - * Copyright © 2011 Topten Software. All Rights Reserved. - * - * Apache License 2.0 - http://www.toptensoftware.com/petapoco/license - * - * Special thanks to Rob Conery (@robconery) for original inspiration (ie:Massive) and for - * use of Subsonic's T4 templates, Rob Sullivan (@DataChomp) for hard core DBA advice - * and Adam Schroder (@schotime) for lots of suggestions, improvements and Oracle support - */ - -// Define PETAPOCO_NO_DYNAMIC in your project settings on .NET 3.5 - -using System; -using System.Collections.Generic; -using System.Linq; -using System.Runtime.Caching; -using System.Security; -using System.Security.Permissions; -using System.Text; -using System.Configuration; -using System.Data.Common; -using System.Data; -using System.Text.RegularExpressions; -using System.Reflection; -using System.Reflection.Emit; -using System.Linq.Expressions; - -namespace Umbraco.Core.Persistence -{ - // Poco's marked [Explicit] require all column properties to be marked - [AttributeUsage(AttributeTargets.Class)] - public class ExplicitColumnsAttribute : Attribute - { - } - // For non-explicit pocos, causes a property to be ignored - [AttributeUsage(AttributeTargets.Property)] - public class IgnoreAttribute : Attribute - { - } - - // For explicit pocos, marks property as a column and optionally supplies column name - [AttributeUsage(AttributeTargets.Property)] - public class ColumnAttribute : Attribute - { - public ColumnAttribute() { } - public ColumnAttribute(string name) { Name = name; } - public string Name { get; set; } - } - - // For explicit pocos, marks property as a result column and optionally supplies column name - [AttributeUsage(AttributeTargets.Property)] - public class ResultColumnAttribute : ColumnAttribute - { - public ResultColumnAttribute() { } - public ResultColumnAttribute(string name) : base(name) { } - } - - // Specify the table name of a poco - [AttributeUsage(AttributeTargets.Class)] - public class TableNameAttribute : Attribute - { - public TableNameAttribute(string tableName) - { - Value = tableName; - } - public string Value { get; private set; } - } - - // Specific the primary key of a poco class (and optional sequence name for Oracle) - [AttributeUsage(AttributeTargets.Class)] - public class PrimaryKeyAttribute : Attribute - { - public PrimaryKeyAttribute(string primaryKey) - { - Value = primaryKey; - autoIncrement = true; - } - - public string Value { get; private set; } - public string sequenceName { get; set; } - public bool autoIncrement { get; set; } - } - - [AttributeUsage(AttributeTargets.Property)] - public class AutoJoinAttribute : Attribute - { - public AutoJoinAttribute() { } - } - - // Results from paged request - public class Page - { - public long CurrentPage { get; set; } - public long TotalPages { get; set; } - public long TotalItems { get; set; } - public long ItemsPerPage { get; set; } - public List Items { get; set; } - public object Context { get; set; } - } - - // Pass as parameter value to force to DBType.AnsiString - public class AnsiString - { - public AnsiString(string str) - { - Value = str; - } - public string Value { get; private set; } - } - - // Used by IMapper to override table bindings for an object - public class TableInfo - { - public string TableName { get; set; } - public string PrimaryKey { get; set; } - public bool AutoIncrement { get; set; } - public string SequenceName { get; set; } - } - - // Optionally provide an implementation of this to Database.Mapper - public interface IMapper - { - void GetTableInfo(Type t, TableInfo ti); - bool MapPropertyToColumn(Type t, PropertyInfo pi, ref string columnName, ref bool resultColumn); - Func GetFromDbConverter(PropertyInfo pi, Type SourceType); - Func GetToDbConverter(Type SourceType); - } - - // This will be merged with IMapper in the next major version - public interface IMapper2 : IMapper - { - Func GetFromDbConverter(Type DestType, Type SourceType); - } - - // Database class ... this is where most of the action happens - public class Database : IDisposable - { - public Database(IDbConnection connection) - { - _sharedConnection = connection; - _connectionString = connection.ConnectionString; - _sharedConnectionDepth = 2; // Prevent closing external connection - CommonConstruct(); - } - - public Database(string connectionString, string providerName) - { - _connectionString = connectionString; - _providerName = providerName; - CommonConstruct(); - } - - public Database(string connectionString, DbProviderFactory provider) - { - _connectionString = connectionString; - _factory = provider; - CommonConstruct(); - } - - public Database(string connectionStringName) - { - // Use first? - if (connectionStringName == "") - connectionStringName = ConfigurationManager.ConnectionStrings[0].Name; - - // Work out connection string and provider name - var providerName = "System.Data.SqlClient"; - if (ConfigurationManager.ConnectionStrings[connectionStringName] != null) - { - if (!string.IsNullOrEmpty(ConfigurationManager.ConnectionStrings[connectionStringName].ProviderName)) - providerName = ConfigurationManager.ConnectionStrings[connectionStringName].ProviderName; - } - else - { - throw new InvalidOperationException("Can't find a connection string with the name '" + connectionStringName + "'"); - } - - // Store factory and connection string - _connectionString = ConfigurationManager.ConnectionStrings[connectionStringName].ConnectionString; - _providerName = providerName; - CommonConstruct(); - } - - enum DBType - { - SqlServer, - SqlServerCE, - MySql, - PostgreSQL, - Oracle, - SQLite - } - DBType _dbType = DBType.SqlServer; - - // Common initialization - private void CommonConstruct() - { - _transactionDepth = 0; - EnableAutoSelect = true; - EnableNamedParams = true; - ForceDateTimesToUtc = true; - - if (_providerName != null) - _factory = DbProviderFactories.GetFactory(_providerName); - - string dbtype = (_factory == null ? _sharedConnection.GetType() : _factory.GetType()).Name; - - if (dbtype.StartsWith("MySql")) _dbType = DBType.MySql; - else if (dbtype.StartsWith("SqlCe")) _dbType = DBType.SqlServerCE; - else if (dbtype.StartsWith("Npgsql")) _dbType = DBType.PostgreSQL; - else if (dbtype.StartsWith("Oracle")) _dbType = DBType.Oracle; - else if (dbtype.StartsWith("SQLite")) _dbType = DBType.SQLite; - - if (_dbType == DBType.MySql && _connectionString != null && _connectionString.IndexOf("Allow User Variables=true") >= 0) - _paramPrefix = "?"; - if (_dbType == DBType.Oracle) - _paramPrefix = ":"; - - // by default use MSSQL default ReadCommitted level - //TODO change to RepeatableRead - but that is breaking - _isolationLevel = IsolationLevel.ReadCommitted; - } - - // Automatically close one open shared connection - public void Dispose() - { - // Automatically close one open connection reference - // (Works with KeepConnectionAlive and manually opening a shared connection) - CloseSharedConnection(); - } - - // Set to true to keep the first opened connection alive until this object is disposed - public bool KeepConnectionAlive { get; set; } - - // Open a connection (can be nested) - public void OpenSharedConnection() - { - if (_sharedConnectionDepth == 0) - { - _sharedConnection = _factory.CreateConnection(); - _sharedConnection.ConnectionString = _connectionString; - _sharedConnection.OpenWithRetry();//Changed .Open() => .OpenWithRetry() extension method - - // ensure we have the proper isolation level, as levels can leak in pools - // read http://stackoverflow.com/questions/9851415/sql-server-isolation-level-leaks-across-pooled-connections - // and http://stackoverflow.com/questions/641120/what-exec-sp-reset-connection-shown-in-sql-profiler-means - // - // NPoco has that code in OpenSharedConnectionImp (commented out?) - //using (var cmd = _sharedConnection.CreateCommand()) - //{ - // cmd.CommandText = GetSqlForTransactionLevel(_isolationLevel); - // cmd.CommandTimeout = CommandTimeout; - // cmd.ExecuteNonQuery(); - //} - // - // although MSDN documentation for SQL CE clearly states that the above method - // should work, it fails & reports an error parsing the query on 'TRANSACTION', - // and Google is no help (others have faced the same issue... no solution). So, - // switching to another method that does work on all databases. - var tr = _sharedConnection.BeginTransaction(_isolationLevel); - tr.Commit(); - tr.Dispose(); - - _sharedConnection = OnConnectionOpened(_sharedConnection); - - if (KeepConnectionAlive) - _sharedConnectionDepth++; // Make sure you call Dispose - } - _sharedConnectionDepth++; - } - - // Close a previously opened connection - public void CloseSharedConnection() - { - if (_sharedConnectionDepth > 0) - { - _sharedConnectionDepth--; - if (_sharedConnectionDepth == 0) - { - OnConnectionClosing(_sharedConnection); - _sharedConnection.Dispose(); - _sharedConnection = null; - } - } - } - - // Access to our shared connection - public IDbConnection Connection - { - get { return _sharedConnection; } - } - - // Helper to create a transaction scope - public Transaction GetTransaction() - { - return GetTransaction(_isolationLevel); - } - - public Transaction GetTransaction(IsolationLevel isolationLevel) - { - return new Transaction(this, isolationLevel); - } - - public IsolationLevel CurrentTransactionIsolationLevel - { - get { return _transaction == null ? IsolationLevel.Unspecified : _transaction.IsolationLevel; } - } - - // Use by derived repo generated by T4 templates - public virtual void OnBeginTransaction() { } - public virtual void OnEndTransaction() { } - - // Start a new transaction, can be nested, every call must be - // matched by a call to AbortTransaction or CompleteTransaction - // Use `using (var scope=db.Transaction) { scope.Complete(); }` to ensure correct semantics - public void BeginTransaction() - { - BeginTransaction(_isolationLevel); - } - - public void BeginTransaction(IsolationLevel isolationLevel) - { - _transactionDepth++; - - if (_transactionDepth == 1) - { - OpenSharedConnection(); - _transaction = _sharedConnection.BeginTransaction(isolationLevel); - _transactionCancelled = false; - OnBeginTransaction(); - } - else if (isolationLevel > _transaction.IsolationLevel) - throw new Exception("Already in a transaction with a lower isolation level."); - } - - // Internal helper to cleanup transaction stuff - void CleanupTransaction() - { - OnEndTransaction(); - - if (_transactionCancelled) - _transaction.Rollback(); - else - _transaction.Commit(); - - _transaction.Dispose(); - _transaction = null; - - CloseSharedConnection(); - } - - // Abort the entire outer most transaction scope - public void AbortTransaction() - { - _transactionCancelled = true; - //TODO what shall we do if transactionDepth is already zero? - if ((--_transactionDepth) == 0) - CleanupTransaction(); - } - - // Complete the transaction - public void CompleteTransaction() - { - //TODO what shall we do if transactionDepth is already zero? - if ((--_transactionDepth) == 0) - CleanupTransaction(); - } - - // in NPoco this is in DatabaseType - private static string GetSqlForTransactionLevel(IsolationLevel isolationLevel) - { - switch (isolationLevel) - { - case IsolationLevel.ReadCommitted: - return "SET TRANSACTION ISOLATION LEVEL READ COMMITTED"; - case IsolationLevel.ReadUncommitted: - return "SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED"; - case IsolationLevel.RepeatableRead: - return "SET TRANSACTION ISOLATION LEVEL REPEATABLE READ"; - case IsolationLevel.Serializable: - return "SET TRANSACTION ISOLATION LEVEL SERIALIZABLE"; - case IsolationLevel.Snapshot: - return "SET TRANSACTION ISOLATION LEVEL SNAPSHOT"; - default: - return "SET TRANSACTION ISOLATION LEVEL READ COMMITTED"; - } - } - - // Helper to handle named parameters from object properties - static Regex rxParams = new Regex(@"(? args_dest) - { - return rxParams.Replace(_sql, m => - { - string param = m.Value.Substring(1); - - object arg_val; - - int paramIndex; - if (int.TryParse(param, out paramIndex)) - { - // Numbered parameter - if (paramIndex < 0 || paramIndex >= args_src.Length) - throw new ArgumentOutOfRangeException(string.Format("Parameter '@{0}' specified but only {1} parameters supplied (in `{2}`)", paramIndex, args_src.Length, _sql)); - arg_val = args_src[paramIndex]; - } - else - { - // Look for a property on one of the arguments with this name - bool found = false; - arg_val = null; - foreach (var o in args_src) - { - var pi = o.GetType().GetProperty(param); - if (pi != null) - { - arg_val = pi.GetValue(o, null); - found = true; - break; - } - } - - if (!found) - throw new ArgumentException(string.Format("Parameter '@{0}' specified but none of the passed arguments have a property with this name (in '{1}')", param, _sql)); - } - - // Expand collections to parameter lists - if ((arg_val as System.Collections.IEnumerable) != null && - (arg_val as string) == null && - (arg_val as byte[]) == null) - { - var sb = new StringBuilder(); - foreach (var i in arg_val as System.Collections.IEnumerable) - { - sb.Append((sb.Length == 0 ? "@" : ",@") + args_dest.Count.ToString()); - args_dest.Add(i); - } - return sb.ToString(); - } - else - { - args_dest.Add(arg_val); - return "@" + (args_dest.Count - 1).ToString(); - } - } - ); - } - - // Add a parameter to a DB command - internal void AddParam(IDbCommand cmd, object item, string ParameterPrefix) - { - // Convert value to from poco type to db type - if (Database.Mapper != null && item!=null) - { - var fn = Database.Mapper.GetToDbConverter(item.GetType()); - if (fn!=null) - item = fn(item); - } - - // Support passed in parameters - var idbParam = item as IDbDataParameter; - if (idbParam != null) - { - idbParam.ParameterName = string.Format("{0}{1}", ParameterPrefix, cmd.Parameters.Count); - cmd.Parameters.Add(idbParam); - return; - } - - var p = cmd.CreateParameter(); - p.ParameterName = string.Format("{0}{1}", ParameterPrefix, cmd.Parameters.Count); - if (item == null) - { - p.Value = DBNull.Value; - } - else - { - var t = item.GetType(); - if (t.IsEnum) // PostgreSQL .NET driver wont cast enum to int - { - p.Value = (int)item; - } - else if (t == typeof(Guid)) - { - p.Value = item.ToString(); - p.DbType = DbType.String; - p.Size = 40; - } - else if (t == typeof(string)) - { - // out of memory exception occurs if trying to save more than 4000 characters to SQL Server CE NText column. - //Set before attempting to set Size, or Size will always max out at 4000 - if ((item as string).Length + 1 > 4000 && p.GetType().Name == "SqlCeParameter") - p.GetType().GetProperty("SqlDbType").SetValue(p, SqlDbType.NText, null); - - p.Size = (item as string).Length + 1; - if(p.Size < 4000) - p.Size = Math.Max((item as string).Length + 1, 4000); // Help query plan caching by using common size - - p.Value = item; - } - else if (t == typeof(AnsiString)) - { - // Thanks @DataChomp for pointing out the SQL Server indexing performance hit of using wrong string type on varchar - p.Size = Math.Max((item as AnsiString).Value.Length + 1, 4000); - p.Value = (item as AnsiString).Value; - p.DbType = DbType.AnsiString; - } - else if (t == typeof(bool) && _dbType != DBType.PostgreSQL) - { - p.Value = ((bool)item) ? 1 : 0; - } - else if (item.GetType().Name == "SqlGeography") //SqlGeography is a CLR Type - { - p.GetType().GetProperty("UdtTypeName").SetValue(p, "geography", null); //geography is the equivalent SQL Server Type - p.Value = item; - } - - else if (item.GetType().Name == "SqlGeometry") //SqlGeometry is a CLR Type - { - p.GetType().GetProperty("UdtTypeName").SetValue(p, "geometry", null); //geography is the equivalent SQL Server Type - p.Value = item; - } - else - { - p.Value = item; - } - } - - cmd.Parameters.Add(p); - } - - // Create a command - static Regex rxParamsPrefix = new Regex(@"(?(); - sql = ProcessParams(sql, args, new_args); - args = new_args.ToArray(); - } - - // Perform parameter prefix replacements - if (_paramPrefix != "@") - sql = rxParamsPrefix.Replace(sql, m => _paramPrefix + m.Value.Substring(1)); - sql = sql.Replace("@@", "@"); // <- double @@ escapes a single @ - - // Create the command and add parameters - IDbCommand cmd = connection.CreateCommand(); - cmd.Connection = connection; - cmd.CommandText = sql; - cmd.Transaction = _transaction; - foreach (var item in args) - { - AddParam(cmd, item, _paramPrefix); - } - - if (_dbType == DBType.Oracle) - { - cmd.GetType().GetProperty("BindByName").SetValue(cmd, true, null); - } - - if (!String.IsNullOrEmpty(sql)) - DoPreExecute(cmd); - - return cmd; - } - - // Override this to log/capture exceptions - public virtual void OnException(Exception x) - { - System.Diagnostics.Debug.WriteLine(x.ToString()); - System.Diagnostics.Debug.WriteLine(LastCommand); - } - - // Override this to log commands, or modify command before execution - public virtual IDbConnection OnConnectionOpened(IDbConnection conn) { return conn; } - public virtual void OnConnectionClosing(IDbConnection conn) { } - public virtual void OnExecutingCommand(IDbCommand cmd) { } - public virtual void OnExecutedCommand(IDbCommand cmd) { } - - // Execute a non-query command - public int Execute(string sql, params object[] args) - { - try - { - OpenSharedConnection(); - try - { - using (var cmd = CreateCommand(_sharedConnection, sql, args)) - { - var retv=cmd.ExecuteNonQueryWithRetry(); - OnExecutedCommand(cmd); - return retv; - } - } - finally - { - CloseSharedConnection(); - } - } - catch (Exception x) - { - OnException(x); - throw; - } - } - - public int Execute(Sql sql) - { - return Execute(sql.SQL, sql.Arguments); - } - - // Execute and cast a scalar property - public T ExecuteScalar(string sql, params object[] args) - { - try - { - OpenSharedConnection(); - try - { - using (var cmd = CreateCommand(_sharedConnection, sql, args)) - { - object val = cmd.ExecuteScalarWithRetry(); - OnExecutedCommand(cmd); - - if (val == null || val == DBNull.Value) - return default(T); - - Type t = typeof(T); - Type u = Nullable.GetUnderlyingType(t); - - return (T)Convert.ChangeType(val, u ?? t); - } - } - finally - { - CloseSharedConnection(); - } - } - catch (Exception x) - { - OnException(x); - throw; - } - } - - public T ExecuteScalar(Sql sql) - { - return ExecuteScalar(sql.SQL, sql.Arguments); - } - - Regex rxSelect = new Regex(@"\A\s*(SELECT|EXECUTE|CALL)\s", RegexOptions.Compiled | RegexOptions.Singleline | RegexOptions.IgnoreCase | RegexOptions.Multiline); - Regex rxFrom = new Regex(@"\A\s*FROM\s", RegexOptions.Compiled | RegexOptions.Singleline | RegexOptions.IgnoreCase | RegexOptions.Multiline); - string AddSelectClause(string sql) - { - if (sql.StartsWith(";")) - return sql.Substring(1); - - if (!rxSelect.IsMatch(sql)) - { - var pd = PocoData.ForType(typeof(T)); - var tableName = EscapeTableName(pd.TableInfo.TableName); - string cols = string.Join(", ", (from c in pd.QueryColumns select tableName + "." + EscapeSqlIdentifier(c)).ToArray()); - if (!rxFrom.IsMatch(sql)) - sql = string.Format("SELECT {0} FROM {1} {2}", cols, tableName, sql); - else - sql = string.Format("SELECT {0} {1}", cols, sql); - } - return sql; - } - - public bool EnableAutoSelect { get; set; } - public bool EnableNamedParams { get; set; } - public bool ForceDateTimesToUtc { get; set; } - - // Return a typed list of pocos - public List Fetch(string sql, params object[] args) - { - return Query(sql, args).ToList(); - } - - public List Fetch(Sql sql) - { - return Fetch(sql.SQL, sql.Arguments); - } - - static Regex rxColumns = new Regex(@"\A\s*SELECT\s+((?:\((?>\((?)|\)(?<-depth>)|.?)*(?(depth)(?!))\)|.)*?)(?\((?)|\)(?<-depth>)|.?)*(?(depth)(?!))\)|[\w\(\)\.])+(?:\s+(?:ASC|DESC))?(?:\s*,\s*(?:\((?>\((?)|\)(?<-depth>)|.?)*(?(depth)(?!))\)|[\w\(\)\.])+(?:\s+(?:ASC|DESC))?)*", RegexOptions.IgnoreCase | RegexOptions.Multiline | RegexOptions.Singleline | RegexOptions.Compiled); - static Regex rxDistinct = new Regex(@"\ADISTINCT\s", RegexOptions.IgnoreCase | RegexOptions.Multiline | RegexOptions.Singleline | RegexOptions.Compiled); - public static bool SplitSqlForPaging(string sql, out string sqlCount, out string sqlSelectRemoved, out string sqlOrderBy) - { - sqlSelectRemoved = null; - sqlCount = null; - sqlOrderBy = null; - - // Extract the columns from "SELECT FROM" - var m = rxColumns.Match(sql); - if (!m.Success) - return false; - - // Save column list and replace with COUNT(*) - Group g = m.Groups[1]; - sqlSelectRemoved = sql.Substring(g.Index); - - if (rxDistinct.IsMatch(sqlSelectRemoved)) - sqlCount = sql.Substring(0, g.Index) + "COUNT(" + m.Groups[1].ToString().Trim() + ") " + sql.Substring(g.Index + g.Length); - else - sqlCount = sql.Substring(0, g.Index) + "COUNT(*) " + sql.Substring(g.Index + g.Length); - - - // Look for an "ORDER BY " clause - m = rxOrderBy.Match(sqlCount); - if (!m.Success) - { - sqlOrderBy = null; - } - else - { - g = m.Groups[0]; - sqlOrderBy = g.ToString(); - sqlCount = sqlCount.Substring(0, g.Index) + sqlCount.Substring(g.Index + g.Length); - } - - return true; - } - - public void BuildPageQueries(long skip, long take, string sql, ref object[] args, out string sqlCount, out string sqlPage) - { - // Add auto select clause - if (EnableAutoSelect) - sql = AddSelectClause(sql); - - // Split the SQL into the bits we need - string sqlSelectRemoved, sqlOrderBy; - if (!SplitSqlForPaging(sql, out sqlCount, out sqlSelectRemoved, out sqlOrderBy)) - throw new Exception("Unable to parse SQL statement for paged query"); - if (_dbType == DBType.Oracle && sqlSelectRemoved.StartsWith("*")) - throw new Exception("Query must alias '*' when performing a paged query.\neg. select t.* from table t order by t.id"); - - // Build the SQL for the actual final result - if (_dbType == DBType.SqlServer || _dbType == DBType.Oracle) - { - sqlSelectRemoved = rxOrderBy.Replace(sqlSelectRemoved, ""); - if (rxDistinct.IsMatch(sqlSelectRemoved)) - { - sqlSelectRemoved = "peta_inner.* FROM (SELECT " + sqlSelectRemoved + ") peta_inner"; - } - sqlPage = string.Format("SELECT * FROM (SELECT ROW_NUMBER() OVER ({0}) peta_rn, {1}) peta_paged WHERE peta_rn>@{2} AND peta_rn<=@{3}", - sqlOrderBy==null ? "ORDER BY (SELECT NULL)" : sqlOrderBy, sqlSelectRemoved, args.Length, args.Length + 1); - args = args.Concat(new object[] { skip, skip+take }).ToArray(); - } - else if (_dbType == DBType.SqlServerCE) - { - sqlPage = string.Format("{0}\nOFFSET @{1} ROWS FETCH NEXT @{2} ROWS ONLY", sql, args.Length, args.Length + 1); - args = args.Concat(new object[] { skip, take }).ToArray(); - } - else - { - sqlPage = string.Format("{0}\nLIMIT @{1} OFFSET @{2}", sql, args.Length, args.Length + 1); - args = args.Concat(new object[] { take, skip }).ToArray(); - } - - } - - // Fetch a page - public Page Page(long page, long itemsPerPage, string sql, params object[] args) - { - string sqlCount, sqlPage; - BuildPageQueries((page-1)*itemsPerPage, itemsPerPage, sql, ref args, out sqlCount, out sqlPage); - - // Save the one-time command time out and use it for both queries - int saveTimeout = OneTimeCommandTimeout; - - // Setup the paged result - var result = new Page(); - result.CurrentPage = page; - result.ItemsPerPage = itemsPerPage; - result.TotalItems = ExecuteScalar(sqlCount, args); - result.TotalPages = result.TotalItems / itemsPerPage; - if ((result.TotalItems % itemsPerPage) != 0) - result.TotalPages++; - - OneTimeCommandTimeout = saveTimeout; - - // Get the records - result.Items = Fetch(sqlPage, args); - - // Done - return result; - } - - public Page Page(long page, long itemsPerPage, Sql sql) - { - return Page(page, itemsPerPage, sql.SQL, sql.Arguments); - } - - - public List Fetch(long page, long itemsPerPage, string sql, params object[] args) - { - return SkipTake((page - 1) * itemsPerPage, itemsPerPage, sql, args); - } - - public List Fetch(long page, long itemsPerPage, Sql sql) - { - return SkipTake((page - 1) * itemsPerPage, itemsPerPage, sql.SQL, sql.Arguments); - } - - public List SkipTake(long skip, long take, string sql, params object[] args) - { - string sqlCount, sqlPage; - BuildPageQueries(skip, take, sql, ref args, out sqlCount, out sqlPage); - return Fetch(sqlPage, args); - } - - public List SkipTake(long skip, long take, Sql sql) - { - return SkipTake(skip, take, sql.SQL, sql.Arguments); - } - - // Return an enumerable collection of pocos - public IEnumerable Query(string sql, params object[] args) - { - if (EnableAutoSelect) - sql = AddSelectClause(sql); - - OpenSharedConnection(); - try - { - using (var cmd = CreateCommand(_sharedConnection, sql, args)) - { - IDataReader r; - var pd = PocoData.ForType(typeof(T)); - try - { - r = cmd.ExecuteReaderWithRetry(); - OnExecutedCommand(cmd); - } - catch (Exception x) - { - OnException(x); - throw; - } - var factory = pd.GetFactory(cmd.CommandText, _sharedConnection.ConnectionString, ForceDateTimesToUtc, 0, r.FieldCount, r) as Func; - using (r) - { - while (true) - { - T poco; - try - { - if (!r.Read()) - yield break; - poco = factory(r); - } - catch (Exception x) - { - OnException(x); - throw; - } - - yield return poco; - } - } - } - } - finally - { - CloseSharedConnection(); - } - } - - // Multi Fetch - public List Fetch(Func cb, string sql, params object[] args) { return Query(cb, sql, args).ToList(); } - public List Fetch(Func cb, string sql, params object[] args) { return Query(cb, sql, args).ToList(); } - public List Fetch(Func cb, string sql, params object[] args) { return Query(cb, sql, args).ToList(); } - public List Fetch(Func cb, string sql, params object[] args) { return Query(cb, sql, args).ToList(); } - - // Multi Query - public IEnumerable Query(Func cb, string sql, params object[] args) { return Query(new Type[] { typeof(T1), typeof(T2) }, cb, sql, args); } - public IEnumerable Query(Func cb, string sql, params object[] args) { return Query(new Type[] { typeof(T1), typeof(T2), typeof(T3)}, cb, sql, args); } - public IEnumerable Query(Func cb, string sql, params object[] args) { return Query(new Type[] { typeof(T1), typeof(T2), typeof(T3), typeof(T4)}, cb, sql, args); } - public IEnumerable Query(Func cb, string sql, params object[] args) { return Query(new Type[] { typeof(T1), typeof(T2), typeof(T3), typeof(T4), typeof(T5) }, cb, sql, args); } - - // Multi Fetch (SQL builder) - public List Fetch(Func cb, Sql sql) { return Query(cb, sql.SQL, sql.Arguments).ToList(); } - public List Fetch(Func cb, Sql sql) { return Query(cb, sql.SQL, sql.Arguments).ToList(); } - public List Fetch(Func cb, Sql sql) { return Query(cb, sql.SQL, sql.Arguments).ToList(); } - public List Fetch(Func cb, Sql sql) { return Query(cb, sql.SQL, sql.Arguments).ToList(); } - - // Multi Query (SQL builder) - public IEnumerable Query(Func cb, Sql sql) { return Query(new Type[] { typeof(T1), typeof(T2) }, cb, sql.SQL, sql.Arguments); } - public IEnumerable Query(Func cb, Sql sql) { return Query(new Type[] { typeof(T1), typeof(T2), typeof(T3) }, cb, sql.SQL, sql.Arguments); } - public IEnumerable Query(Func cb, Sql sql) { return Query(new Type[] { typeof(T1), typeof(T2), typeof(T3), typeof(T4) }, cb, sql.SQL, sql.Arguments); } - public IEnumerable Query(Func cb, Sql sql) { return Query(new Type[] { typeof(T1), typeof(T2), typeof(T3), typeof(T4), typeof(T5) }, cb, sql.SQL, sql.Arguments); } - - // Multi Fetch (Simple) - public List Fetch(string sql, params object[] args) { return Query(sql, args).ToList(); } - public List Fetch(string sql, params object[] args) { return Query(sql, args).ToList(); } - public List Fetch(string sql, params object[] args) { return Query(sql, args).ToList(); } - public List Fetch(string sql, params object[] args) { return Query(sql, args).ToList(); } - - // Multi Query (Simple) - public IEnumerable Query(string sql, params object[] args) { return Query(new Type[] { typeof(T1), typeof(T2) }, null, sql, args); } - public IEnumerable Query(string sql, params object[] args) { return Query(new Type[] { typeof(T1), typeof(T2), typeof(T3) }, null, sql, args); } - public IEnumerable Query(string sql, params object[] args) { return Query(new Type[] { typeof(T1), typeof(T2), typeof(T3), typeof(T4) }, null, sql, args); } - public IEnumerable Query(string sql, params object[] args) { return Query(new Type[] { typeof(T1), typeof(T2), typeof(T3), typeof(T4), typeof(T5) }, null, sql, args); } - - // Multi Fetch (Simple) (SQL builder) - public List Fetch(Sql sql) { return Query(sql.SQL, sql.Arguments).ToList(); } - public List Fetch(Sql sql) { return Query(sql.SQL, sql.Arguments).ToList(); } - public List Fetch(Sql sql) { return Query(sql.SQL, sql.Arguments).ToList(); } - public List Fetch(Sql sql) { return Query(sql.SQL, sql.Arguments).ToList(); } - - // Multi Query (Simple) (SQL builder) - public IEnumerable Query(Sql sql) { return Query(new Type[] { typeof(T1), typeof(T2) }, null, sql.SQL, sql.Arguments); } - public IEnumerable Query(Sql sql) { return Query(new Type[] { typeof(T1), typeof(T2), typeof(T3) }, null, sql.SQL, sql.Arguments); } - public IEnumerable Query(Sql sql) { return Query(new Type[] { typeof(T1), typeof(T2), typeof(T3), typeof(T4) }, null, sql.SQL, sql.Arguments); } - public IEnumerable Query(Sql sql) { return Query(new Type[] { typeof(T1), typeof(T2), typeof(T3), typeof(T4), typeof(T5) }, null, sql.SQL, sql.Arguments); } - - // Automagically guess the property relationships between various POCOs and create a delegate that will set them up - Delegate GetAutoMapper(Type[] types) - { - // Build a key - var kb = new StringBuilder(); - foreach (var t in types) - { - kb.Append(t.ToString()); - kb.Append(":"); - } - var key = kb.ToString(); - - // Check cache - RWLock.EnterReadLock(); - try - { - Delegate mapper; - if (AutoMappers.TryGetValue(key, out mapper)) - return mapper; - } - finally - { - RWLock.ExitReadLock(); - } - - // Create it - RWLock.EnterWriteLock(); - try - { - // Try again - Delegate mapper; - if (AutoMappers.TryGetValue(key, out mapper)) - return mapper; - - // Create a method - var m = new DynamicMethod("petapoco_automapper", types[0], types, true); - var il = m.GetILGenerator(); - - for (int i = 1; i < types.Length; i++) - { - bool handled = false; - for (int j = i - 1; j >= 0; j--) - { - // Find the property - var candidates = from p in types[j].GetProperties() where p.PropertyType == types[i] select p; - if (candidates.Any() == false) - continue; - if (candidates.Count() > 1) - throw new InvalidOperationException(string.Format("Can't auto join {0} as {1} has more than one property of type {0}", types[i], types[j])); - - // Generate code - il.Emit(OpCodes.Ldarg_S, j); - il.Emit(OpCodes.Ldarg_S, i); - il.Emit(OpCodes.Callvirt, candidates.First().GetSetMethod(true)); - handled = true; - } - - if (!handled) - throw new InvalidOperationException(string.Format("Can't auto join {0}", types[i])); - } - - il.Emit(OpCodes.Ldarg_0); - il.Emit(OpCodes.Ret); - - // Cache it - var del = m.CreateDelegate(Expression.GetFuncType(types.Concat(types.Take(1)).ToArray())); - AutoMappers.Add(key, del); - return del; - } - finally - { - RWLock.ExitWriteLock(); - } - } - - // Find the split point in a result set for two different pocos and return the poco factory for the first - Delegate FindSplitPoint(Type typeThis, Type typeNext, string sql, IDataReader r, ref int pos) - { - // Last? - if (typeNext == null) - return PocoData.ForType(typeThis).GetFactory(sql, _sharedConnection.ConnectionString, ForceDateTimesToUtc, pos, r.FieldCount - pos, r); - - // Get PocoData for the two types - PocoData pdThis = PocoData.ForType(typeThis); - PocoData pdNext = PocoData.ForType(typeNext); - - // Find split point - int firstColumn = pos; - var usedColumns = new Dictionary(); - for (; pos < r.FieldCount; pos++) - { - // Split if field name has already been used, or if the field doesn't exist in current poco but does in the next - string fieldName = r.GetName(pos); - if (usedColumns.ContainsKey(fieldName) || (!pdThis.Columns.ContainsKey(fieldName) && pdNext.Columns.ContainsKey(fieldName))) - { - return pdThis.GetFactory(sql, _sharedConnection.ConnectionString, ForceDateTimesToUtc, firstColumn, pos - firstColumn, r); - } - usedColumns.Add(fieldName, true); - } - - throw new InvalidOperationException(string.Format("Couldn't find split point between {0} and {1}", typeThis, typeNext)); - } - - - // Instance data used by the Multipoco factory delegate - essentially a list of the nested poco factories to call - public class MultiPocoFactory - { - - public MultiPocoFactory(IEnumerable dels) - { - Delegates = new List(dels); - } - private List Delegates { get; set; } - private Delegate GetItem(int index) { return Delegates[index]; } - - /// - /// Calls the delegate at the specified index and returns its values - /// - /// - /// - /// - private object CallDelegate(int index, IDataReader reader) - { - var d = GetItem(index); - var output = d.DynamicInvoke(reader); - return output; - } - - /// - /// Calls the callback delegate and passes in the output of all delegates as the parameters - /// - /// - /// - /// - /// - /// - public TRet CallCallback(Delegate callback, IDataReader dr, int count) - { - var args = new List(); - for(var i = 0;i CreateMultiPocoFactory(Type[] types, string sql, IDataReader r) - { - // Call each delegate - var dels = new List(); - int pos = 0; - for (int i=0; i mpFactory.CallCallback(arg3, reader, types.Length); - } - - // Various cached stuff - static Dictionary MultiPocoFactories = new Dictionary(); - static Dictionary AutoMappers = new Dictionary(); - static System.Threading.ReaderWriterLockSlim RWLock = new System.Threading.ReaderWriterLockSlim(); - - // Get (or create) the multi-poco factory for a query - Func GetMultiPocoFactory(Type[] types, string sql, IDataReader r) - { - // Build a key string (this is crap, should address this at some point) - var kb = new StringBuilder(); - kb.Append(typeof(TRet).ToString()); - kb.Append(":"); - foreach (var t in types) - { - kb.Append(":"); - kb.Append(t.ToString()); - } - kb.Append(":"); kb.Append(_sharedConnection.ConnectionString); - kb.Append(":"); kb.Append(ForceDateTimesToUtc); - kb.Append(":"); kb.Append(sql); - string key = kb.ToString(); - - // Check cache - RWLock.EnterReadLock(); - try - { - object oFactory; - if (MultiPocoFactories.TryGetValue(key, out oFactory)) - { - //mpFactory = oFactory; - return (Func)oFactory; - } - } - finally - { - RWLock.ExitReadLock(); - } - - // Cache it - RWLock.EnterWriteLock(); - try - { - // Check again - object oFactory; ; - if (MultiPocoFactories.TryGetValue(key, out oFactory)) - { - return (Func)oFactory; - } - - // Create the factory - var factory = CreateMultiPocoFactory(types, sql, r); - - MultiPocoFactories.Add(key, factory); - return factory; - } - finally - { - RWLock.ExitWriteLock(); - } - - } - - // Actual implementation of the multi-poco query - public IEnumerable Query(Type[] types, Delegate cb, string sql, params object[] args) - { - OpenSharedConnection(); - try - { - using (var cmd = CreateCommand(_sharedConnection, sql, args)) - { - IDataReader r; - try - { - r = cmd.ExecuteReaderWithRetry(); - OnExecutedCommand(cmd); - } - catch (Exception x) - { - OnException(x); - throw; - } - var factory = GetMultiPocoFactory(types, sql, r); - if (cb == null) - cb = GetAutoMapper(types.ToArray()); - bool bNeedTerminator=false; - using (r) - { - while (true) - { - TRet poco; - try - { - if (!r.Read()) - break; - poco = factory(r, cb); - } - catch (Exception x) - { - OnException(x); - throw; - } - - if (poco != null) - yield return poco; - else - bNeedTerminator = true; - } - if (bNeedTerminator) - { - var poco = (TRet)(cb as Delegate).DynamicInvoke(new object[types.Length]); - if (poco != null) - yield return poco; - else - yield break; - } - } - } - } - finally - { - CloseSharedConnection(); - } - } - - - public IEnumerable Query(Sql sql) - { - return Query(sql.SQL, sql.Arguments); - } - - public bool Exists(object primaryKey) - { - return FirstOrDefault(string.Format("WHERE {0}=@0", EscapeSqlIdentifier(PocoData.ForType(typeof(T)).TableInfo.PrimaryKey)), primaryKey) != null; - } - public T Single(object primaryKey) - { - return Single(string.Format("WHERE {0}=@0", EscapeSqlIdentifier(PocoData.ForType(typeof(T)).TableInfo.PrimaryKey)), primaryKey); - } - public T SingleOrDefault(object primaryKey) - { - return SingleOrDefault(string.Format("WHERE {0}=@0", EscapeSqlIdentifier(PocoData.ForType(typeof(T)).TableInfo.PrimaryKey)), primaryKey); - } - public T Single(string sql, params object[] args) - { - return Query(sql, args).Single(); - } - public T SingleOrDefault(string sql, params object[] args) - { - return Query(sql, args).SingleOrDefault(); - } - public T First(string sql, params object[] args) - { - return Query(sql, args).First(); - } - public T FirstOrDefault(string sql, params object[] args) - { - return Query(sql, args).FirstOrDefault(); - } - - public T Single(Sql sql) - { - return Query(sql).Single(); - } - public T SingleOrDefault(Sql sql) - { - return Query(sql).SingleOrDefault(); - } - public T First(Sql sql) - { - return Query(sql).First(); - } - public T FirstOrDefault(Sql sql) - { - return Query(sql).FirstOrDefault(); - } - - public string EscapeTableName(string str) - { - // Assume table names with "dot", or opening sq is already escaped - return str.IndexOf('.') >= 0 ? str : EscapeSqlIdentifier(str); - } - public string EscapeSqlIdentifier(string str) - { - switch (_dbType) - { - case DBType.MySql: - return string.Format("`{0}`", str); - - case DBType.PostgreSQL: - case DBType.Oracle: - return string.Format("\"{0}\"", str); - - default: - return string.Format("[{0}]", str); - } - } - - public object Insert(string tableName, string primaryKeyName, object poco) - { - return Insert(tableName, primaryKeyName, true, poco); - } - - // Insert a poco into a table. If the poco has a property with the same name - // as the primary key the id of the new record is assigned to it. Either way, - // the new id is returned. - public object Insert(string tableName, string primaryKeyName, bool autoIncrement, object poco) - { - try - { - OpenSharedConnection(); - try - { - using (var cmd = CreateCommand(_sharedConnection, "")) - { - var pd = PocoData.ForObject(poco, primaryKeyName); - var names = new List(); - var values = new List(); - var index = 0; - foreach (var i in pd.Columns) - { - // Don't insert result columns - if (i.Value.ResultColumn) - continue; - - // Don't insert the primary key (except under oracle where we need bring in the next sequence value) - if (autoIncrement && primaryKeyName != null && string.Compare(i.Key, primaryKeyName, true)==0) - { - if (_dbType == DBType.Oracle && !string.IsNullOrEmpty(pd.TableInfo.SequenceName)) - { - names.Add(i.Key); - values.Add(string.Format("{0}.nextval", pd.TableInfo.SequenceName)); - } - continue; - } - - names.Add(EscapeSqlIdentifier(i.Key)); - values.Add(string.Format("{0}{1}", _paramPrefix, index++)); - AddParam(cmd, i.Value.GetValue(poco), _paramPrefix); - } - - cmd.CommandText = string.Format("INSERT INTO {0} ({1}) VALUES ({2})", - EscapeTableName(tableName), - string.Join(",", names.ToArray()), - string.Join(",", values.ToArray()) - ); - - if (!autoIncrement) - { - DoPreExecute(cmd); - cmd.ExecuteNonQueryWithRetry(); - OnExecutedCommand(cmd); - return true; - } - - - object id; - switch (_dbType) - { - case DBType.SqlServerCE: - DoPreExecute(cmd); - cmd.ExecuteNonQueryWithRetry(); - OnExecutedCommand(cmd); - id = ExecuteScalar("SELECT @@@IDENTITY AS NewID;"); - break; - case DBType.SqlServer: - cmd.CommandText += ";\nSELECT SCOPE_IDENTITY() AS NewID;"; - DoPreExecute(cmd); - id = cmd.ExecuteScalarWithRetry(); - OnExecutedCommand(cmd); - break; - case DBType.PostgreSQL: - if (primaryKeyName != null) - { - cmd.CommandText += string.Format("returning {0} as NewID", EscapeSqlIdentifier(primaryKeyName)); - DoPreExecute(cmd); - id = cmd.ExecuteScalarWithRetry(); - } - else - { - id = -1; - DoPreExecute(cmd); - cmd.ExecuteNonQueryWithRetry(); - } - OnExecutedCommand(cmd); - break; - case DBType.Oracle: - if (primaryKeyName != null) - { - cmd.CommandText += string.Format(" returning {0} into :newid", EscapeSqlIdentifier(primaryKeyName)); - var param = cmd.CreateParameter(); - param.ParameterName = ":newid"; - param.Value = DBNull.Value; - param.Direction = ParameterDirection.ReturnValue; - param.DbType = DbType.Int64; - cmd.Parameters.Add(param); - DoPreExecute(cmd); - cmd.ExecuteNonQueryWithRetry(); - id = param.Value; - } - else - { - id = -1; - DoPreExecute(cmd); - cmd.ExecuteNonQueryWithRetry(); - } - OnExecutedCommand(cmd); - break; - case DBType.SQLite: - if (primaryKeyName != null) - { - cmd.CommandText += ";\nSELECT last_insert_rowid();"; - DoPreExecute(cmd); - id = cmd.ExecuteScalarWithRetry(); - } - else - { - id = -1; - DoPreExecute(cmd); - cmd.ExecuteNonQueryWithRetry(); - } - OnExecutedCommand(cmd); - break; - default: - cmd.CommandText += ";\nSELECT @@IDENTITY AS NewID;"; - DoPreExecute(cmd); - id = cmd.ExecuteScalarWithRetry(); - OnExecutedCommand(cmd); - break; - } - - - // Assign the ID back to the primary key property - if (primaryKeyName != null) - { - PocoColumn pc; - if (pd.Columns.TryGetValue(primaryKeyName, out pc)) - { - pc.SetValue(poco, pc.ChangeType(id)); - } - } - - return id; - } - } - finally - { - CloseSharedConnection(); - } - } - catch (Exception x) - { - OnException(x); - throw; - } - } - - // Insert an annotated poco object - public object Insert(object poco) - { - var pd = PocoData.ForType(poco.GetType()); - return Insert(pd.TableInfo.TableName, pd.TableInfo.PrimaryKey, pd.TableInfo.AutoIncrement, poco); - } - - public int Update(string tableName, string primaryKeyName, object poco, object primaryKeyValue) - { - return Update(tableName, primaryKeyName, poco, primaryKeyValue, null); - } - - - // Update a record with values from a poco. primary key value can be either supplied or read from the poco - public int Update(string tableName, string primaryKeyName, object poco, object primaryKeyValue, IEnumerable columns) - { - try - { - OpenSharedConnection(); - try - { - using (var cmd = CreateCommand(_sharedConnection, "")) - { - var sb = new StringBuilder(); - var index = 0; - var pd = PocoData.ForObject(poco,primaryKeyName); - if (columns == null) - { - foreach (var i in pd.Columns) - { - // Don't update the primary key, but grab the value if we don't have it - if (string.Compare(i.Key, primaryKeyName, true) == 0) - { - if (primaryKeyValue == null) - primaryKeyValue = i.Value.GetValue(poco); - continue; - } - - // Dont update result only columns - if (i.Value.ResultColumn) - continue; - - // Build the sql - if (index > 0) - sb.Append(", "); - sb.AppendFormat("{0} = {1}{2}", EscapeSqlIdentifier(i.Key), _paramPrefix, index++); - - // Store the parameter in the command - AddParam(cmd, i.Value.GetValue(poco), _paramPrefix); - } - } - else - { - foreach (var colname in columns) - { - var pc = pd.Columns[colname]; - - // Build the sql - if (index > 0) - sb.Append(", "); - sb.AppendFormat("{0} = {1}{2}", EscapeSqlIdentifier(colname), _paramPrefix, index++); - - // Store the parameter in the command - AddParam(cmd, pc.GetValue(poco), _paramPrefix); - } - - // Grab primary key value - if (primaryKeyValue == null) - { - var pc = pd.Columns[primaryKeyName]; - primaryKeyValue = pc.GetValue(poco); - } - - } - - cmd.CommandText = string.Format("UPDATE {0} SET {1} WHERE {2} = {3}{4}", - EscapeTableName(tableName), sb.ToString(), EscapeSqlIdentifier(primaryKeyName), _paramPrefix, index++); - AddParam(cmd, primaryKeyValue, _paramPrefix); - - DoPreExecute(cmd); - - // Do it - var retv=cmd.ExecuteNonQueryWithRetry(); - OnExecutedCommand(cmd); - return retv; - } - } - finally - { - CloseSharedConnection(); - } - } - catch (Exception x) - { - OnException(x); - throw; - } - } - - public int Update(string tableName, string primaryKeyName, object poco) - { - return Update(tableName, primaryKeyName, poco, null); - } - - public int Update(string tableName, string primaryKeyName, object poco, IEnumerable columns) - { - return Update(tableName, primaryKeyName, poco, null, columns); - } - - public int Update(object poco, IEnumerable columns) - { - return Update(poco, null, columns); - } - - public int Update(object poco) - { - return Update(poco, null, null); - } - - public int Update(object poco, object primaryKeyValue) - { - return Update(poco, primaryKeyValue, null); - } - public int Update(object poco, object primaryKeyValue, IEnumerable columns) - { - var pd = PocoData.ForType(poco.GetType()); - return Update(pd.TableInfo.TableName, pd.TableInfo.PrimaryKey, poco, primaryKeyValue, columns); - } - - public int Update(string sql, params object[] args) - { - var pd = PocoData.ForType(typeof(T)); - return Execute(string.Format("UPDATE {0} {1}", EscapeTableName(pd.TableInfo.TableName), sql), args); - } - - public int Update(Sql sql) - { - var pd = PocoData.ForType(typeof(T)); - return Execute(new Sql(string.Format("UPDATE {0}", EscapeTableName(pd.TableInfo.TableName))).Append(sql)); - } - - public int Delete(string tableName, string primaryKeyName, object poco) - { - return Delete(tableName, primaryKeyName, poco, null); - } - - public int Delete(string tableName, string primaryKeyName, object poco, object primaryKeyValue) - { - // If primary key value not specified, pick it up from the object - if (primaryKeyValue == null) - { - var pd = PocoData.ForObject(poco,primaryKeyName); - PocoColumn pc; - if (pd.Columns.TryGetValue(primaryKeyName, out pc)) - { - primaryKeyValue = pc.GetValue(poco); - } - } - - // Do it - var sql = string.Format("DELETE FROM {0} WHERE {1}=@0", EscapeTableName(tableName), EscapeSqlIdentifier(primaryKeyName)); - return Execute(sql, primaryKeyValue); - } - - public int Delete(object poco) - { - var pd = PocoData.ForType(poco.GetType()); - return Delete(pd.TableInfo.TableName, pd.TableInfo.PrimaryKey, poco); - } - - public int Delete(object pocoOrPrimaryKey) - { - if (pocoOrPrimaryKey.GetType() == typeof(T)) - return Delete(pocoOrPrimaryKey); - var pd = PocoData.ForType(typeof(T)); - return Delete(pd.TableInfo.TableName, pd.TableInfo.PrimaryKey, null, pocoOrPrimaryKey); - } - - public int Delete(string sql, params object[] args) - { - var pd = PocoData.ForType(typeof(T)); - return Execute(string.Format("DELETE FROM {0} {1}", EscapeTableName(pd.TableInfo.TableName), sql), args); - } - - public int Delete(Sql sql) - { - var pd = PocoData.ForType(typeof(T)); - return Execute(new Sql(string.Format("DELETE FROM {0}", EscapeTableName(pd.TableInfo.TableName))).Append(sql)); - } - - // Check if a poco represents a new record - public bool IsNew(string primaryKeyName, object poco) - { - var pd = PocoData.ForObject(poco, primaryKeyName); - object pk; - PocoColumn pc; - if (pd.Columns.TryGetValue(primaryKeyName, out pc)) - { - pk = pc.GetValue(poco); - } -#if !PETAPOCO_NO_DYNAMIC - else if (poco.GetType() == typeof(System.Dynamic.ExpandoObject)) - { - return true; - } -#endif - else - { - var pi = poco.GetType().GetProperty(primaryKeyName); - if (pi == null) - throw new ArgumentException(string.Format("The object doesn't have a property matching the primary key column name '{0}'", primaryKeyName)); - pk = pi.GetValue(poco, null); - } - - if (pk == null) - return true; - - var type = pk.GetType(); - - if (type.IsValueType) - { - // Common primary key types - if (type == typeof(long)) - return (long)pk == 0; - else if (type == typeof(ulong)) - return (ulong)pk == 0; - else if (type == typeof(int)) - return (int)pk == 0; - else if (type == typeof(uint)) - return (uint)pk == 0; - - // Create a default instance and compare - return pk == Activator.CreateInstance(pk.GetType()); - } - else - { - return pk == null; - } - } - - public bool IsNew(object poco) - { - var pd = PocoData.ForType(poco.GetType()); - if (!pd.TableInfo.AutoIncrement) - throw new InvalidOperationException("IsNew() and Save() are only supported on tables with auto-increment/identity primary key columns"); - return IsNew(pd.TableInfo.PrimaryKey, poco); - } - - // Insert new record or Update existing record - public void Save(string tableName, string primaryKeyName, object poco) - { - if (IsNew(primaryKeyName, poco)) - { - Insert(tableName, primaryKeyName, true, poco); - } - else - { - Update(tableName, primaryKeyName, poco); - } - } - - public void Save(object poco) - { - var pd = PocoData.ForType(poco.GetType()); - Save(pd.TableInfo.TableName, pd.TableInfo.PrimaryKey, poco); - } - - public int CommandTimeout { get; set; } - public int OneTimeCommandTimeout { get; set; } - - void DoPreExecute(IDbCommand cmd) - { - // Setup command timeout - if (OneTimeCommandTimeout != 0) - { - cmd.CommandTimeout = OneTimeCommandTimeout; - OneTimeCommandTimeout = 0; - } - else if (CommandTimeout!=0) - { - cmd.CommandTimeout = CommandTimeout; - } - - // Call hook - OnExecutingCommand(cmd); - - // Save it - _lastSql = cmd.CommandText; - _lastArgs = (from IDataParameter parameter in cmd.Parameters select parameter.Value).ToArray(); - } - - public string LastSQL { get { return _lastSql; } } - public object[] LastArgs { get { return _lastArgs; } } - public string LastCommand - { - get { return FormatCommand(_lastSql, _lastArgs); } - } - - public string FormatCommand(IDbCommand cmd) - { - return FormatCommand(cmd.CommandText, (from IDataParameter parameter in cmd.Parameters select parameter.Value).ToArray()); - } - - public string FormatCommand(string sql, object[] args) - { - var sb = new StringBuilder(); - if (sql == null) - return ""; - sb.Append(sql); - if (args != null && args.Length > 0) - { - sb.Append("\n"); - for (int i = 0; i < args.Length; i++) - { - sb.AppendFormat("\t -> {0}{1} [{2}] = \"{3}\"\n", _paramPrefix, i, args[i].GetType().Name, args[i]); - } - sb.Remove(sb.Length - 1, 1); - } - return sb.ToString(); - } - - - public static IMapper Mapper - { - get; - set; - } - - public class PocoColumn - { - public string ColumnName; - public PropertyInfo PropertyInfo; - public bool ResultColumn; - public virtual void SetValue(object target, object val) { PropertyInfo.SetValue(target, val, null); } - public virtual object GetValue(object target) { return PropertyInfo.GetValue(target, null); } - public virtual object ChangeType(object val) { return Convert.ChangeType(val, PropertyInfo.PropertyType); } - } - public class ExpandoColumn : PocoColumn - { - public override void SetValue(object target, object val) { (target as IDictionary)[ColumnName]=val; } - public override object GetValue(object target) - { - object val=null; - (target as IDictionary).TryGetValue(ColumnName, out val); - return val; - } - public override object ChangeType(object val) { return val; } - } - - /// - /// Container for a Memory cache object - /// - /// - /// Better to have one memory cache instance than many so it's memory management can be handled more effectively - /// http://stackoverflow.com/questions/8463962/using-multiple-instances-of-memorycache - /// - internal class ManagedCache - { - public ObjectCache GetCache() - { - return ObjectCache; - } - - static readonly ObjectCache ObjectCache = new MemoryCache("NPoco"); - - } - - public class PocoData - { - //USE ONLY FOR TESTING - internal static bool UseLongKeys = false; - //USE ONLY FOR TESTING - default is one hr - internal static int SlidingExpirationSeconds = 3600; - - public static PocoData ForObject(object o, string primaryKeyName) - { - var t = o.GetType(); -#if !PETAPOCO_NO_DYNAMIC - if (t == typeof(System.Dynamic.ExpandoObject)) - { - var pd = new PocoData(); - pd.TableInfo = new TableInfo(); - pd.Columns = new Dictionary(StringComparer.OrdinalIgnoreCase); - pd.Columns.Add(primaryKeyName, new ExpandoColumn() { ColumnName = primaryKeyName }); - pd.TableInfo.PrimaryKey = primaryKeyName; - pd.TableInfo.AutoIncrement = true; - foreach (var col in (o as IDictionary).Keys) - { - if (col!=primaryKeyName) - pd.Columns.Add(col, new ExpandoColumn() { ColumnName = col }); - } - return pd; - } - else -#endif - return ForType(t); - } - - public static PocoData ForType(Type t) - { -#if !PETAPOCO_NO_DYNAMIC - if (t == typeof(System.Dynamic.ExpandoObject)) - throw new InvalidOperationException("Can't use dynamic types with this method"); -#endif - // Check cache - InnerLock.EnterReadLock(); - PocoData pd; - try - { - if (m_PocoDatas.TryGetValue(t, out pd)) - return pd; - } - finally - { - InnerLock.ExitReadLock(); - } - - - // Cache it - InnerLock.EnterWriteLock(); - try - { - // Check again - if (m_PocoDatas.TryGetValue(t, out pd)) - return pd; - - // Create it - pd = new PocoData(t); - - m_PocoDatas.Add(t, pd); - } - finally - { - InnerLock.ExitWriteLock(); - } - - return pd; - } - - public PocoData() - { - } - - public PocoData(Type t) - { - type = t; - TableInfo=new TableInfo(); - - // Get the table name - var a = t.GetCustomAttributes(typeof(TableNameAttribute), true); - TableInfo.TableName = a.Length == 0 ? t.Name : (a[0] as TableNameAttribute).Value; - - // Get the primary key - a = t.GetCustomAttributes(typeof(PrimaryKeyAttribute), true); - TableInfo.PrimaryKey = a.Length == 0 ? "ID" : (a[0] as PrimaryKeyAttribute).Value; - TableInfo.SequenceName = a.Length == 0 ? null : (a[0] as PrimaryKeyAttribute).sequenceName; - TableInfo.AutoIncrement = a.Length == 0 ? false : (a[0] as PrimaryKeyAttribute).autoIncrement; - - // Call column mapper - if (Database.Mapper != null) - Database.Mapper.GetTableInfo(t, TableInfo); - - // Work out bound properties - bool ExplicitColumns = t.GetCustomAttributes(typeof(ExplicitColumnsAttribute), true).Length > 0; - Columns = new Dictionary(StringComparer.OrdinalIgnoreCase); - - foreach (var pi in t.GetProperties()) - { - // Work out if properties is to be included - var ColAttrs = pi.GetCustomAttributes(typeof(ColumnAttribute), true); - if (ExplicitColumns) - { - if (ColAttrs.Length == 0) - continue; - } - else - { - if (pi.GetCustomAttributes(typeof(IgnoreAttribute), true).Length != 0) - continue; - } - - var pc = new PocoColumn(); - pc.PropertyInfo = pi; - - // Work out the DB column name - if (ColAttrs.Length > 0) - { - var colattr = (ColumnAttribute)ColAttrs[0]; - pc.ColumnName = colattr.Name; - if ((colattr as ResultColumnAttribute) != null) - pc.ResultColumn = true; - } - if (pc.ColumnName == null) - { - pc.ColumnName = pi.Name; - if (Database.Mapper != null && !Database.Mapper.MapPropertyToColumn(t, pi, ref pc.ColumnName, ref pc.ResultColumn)) - continue; - } - - // Store it - Columns.Add(pc.ColumnName, pc); - } - - // Build column list for automatic select - QueryColumns = (from c in Columns where !c.Value.ResultColumn select c.Key).ToArray(); - - } - - static bool IsIntegralType(Type t) - { - var tc = Type.GetTypeCode(t); - return tc >= TypeCode.SByte && tc <= TypeCode.UInt64; - } - - - - // Create factory function that can convert a IDataReader record into a POCO - public Delegate GetFactory(string sql, string connString, bool ForceDateTimesToUtc, int firstColumn, int countColumns, IDataReader r) - { - - //TODO: It would be nice to remove the irrelevant SQL parts - for a mapping operation anything after the SELECT clause isn't required. - // This would ensure less duplicate entries that get cached, currently both of these queries would be cached even though they are - // returning the same structured data: - // SELECT * FROM MyTable ORDER BY MyColumn - // SELECT * FROM MyTable ORDER BY MyColumn DESC - - string key; - if (UseLongKeys) - { - key = string.Format("{0}:{1}:{2}:{3}:{4}", sql, connString, ForceDateTimesToUtc, firstColumn, countColumns); - } - else - { - //Create a hashed key, we don't want to store so much string data in memory - var combiner = new HashCodeCombiner(); - combiner.AddCaseInsensitiveString(sql); - combiner.AddCaseInsensitiveString(connString); - combiner.AddObject(ForceDateTimesToUtc); - combiner.AddInt(firstColumn); - combiner.AddInt(countColumns); - key = combiner.GetCombinedHashCode(); - } - - - var objectCache = _managedCache.GetCache(); - - Func factory = () => - { - // Create the method - var m = new DynamicMethod("petapoco_factory_" + objectCache.GetCount(), type, new Type[] { typeof(IDataReader) }, true); - var il = m.GetILGenerator(); - -#if !PETAPOCO_NO_DYNAMIC - if (type == typeof(object)) - { - // var poco=new T() - il.Emit(OpCodes.Newobj, typeof(System.Dynamic.ExpandoObject).GetConstructor(Type.EmptyTypes)); // obj - - MethodInfo fnAdd = typeof(IDictionary).GetMethod("Add"); - - // Enumerate all fields generating a set assignment for the column - for (int i = firstColumn; i < firstColumn + countColumns; i++) - { - var srcType = r.GetFieldType(i); - - il.Emit(OpCodes.Dup); // obj, obj - il.Emit(OpCodes.Ldstr, r.GetName(i)); // obj, obj, fieldname - - // Get the converter - Func converter = null; - if (Database.Mapper != null) - converter = Database.Mapper.GetFromDbConverter(null, srcType); - if (ForceDateTimesToUtc && converter == null && srcType == typeof(DateTime)) - converter = delegate(object src) { return new DateTime(((DateTime)src).Ticks, DateTimeKind.Utc); }; - - // Setup stack for call to converter - AddConverterToStack(il, converter); - - // r[i] - il.Emit(OpCodes.Ldarg_0); // obj, obj, fieldname, converter?, rdr - il.Emit(OpCodes.Ldc_I4, i); // obj, obj, fieldname, converter?, rdr,i - il.Emit(OpCodes.Callvirt, fnGetValue); // obj, obj, fieldname, converter?, value - - // Convert DBNull to null - il.Emit(OpCodes.Dup); // obj, obj, fieldname, converter?, value, value - il.Emit(OpCodes.Isinst, typeof(DBNull)); // obj, obj, fieldname, converter?, value, (value or null) - var lblNotNull = il.DefineLabel(); - il.Emit(OpCodes.Brfalse_S, lblNotNull); // obj, obj, fieldname, converter?, value - il.Emit(OpCodes.Pop); // obj, obj, fieldname, converter? - if (converter != null) - il.Emit(OpCodes.Pop); // obj, obj, fieldname, - il.Emit(OpCodes.Ldnull); // obj, obj, fieldname, null - if (converter != null) - { - var lblReady = il.DefineLabel(); - il.Emit(OpCodes.Br_S, lblReady); - il.MarkLabel(lblNotNull); - il.Emit(OpCodes.Callvirt, fnInvoke); - il.MarkLabel(lblReady); - } - else - { - il.MarkLabel(lblNotNull); - } - - il.Emit(OpCodes.Callvirt, fnAdd); - } - } - else -#endif - if (type.IsValueType || type == typeof(string) || type == typeof(byte[])) - { - // Do we need to install a converter? - var srcType = r.GetFieldType(0); - var converter = GetConverter(ForceDateTimesToUtc, null, srcType, type); - - // "if (!rdr.IsDBNull(i))" - il.Emit(OpCodes.Ldarg_0); // rdr - il.Emit(OpCodes.Ldc_I4_0); // rdr,0 - il.Emit(OpCodes.Callvirt, fnIsDBNull); // bool - var lblCont = il.DefineLabel(); - il.Emit(OpCodes.Brfalse_S, lblCont); - il.Emit(OpCodes.Ldnull); // null - var lblFin = il.DefineLabel(); - il.Emit(OpCodes.Br_S, lblFin); - - il.MarkLabel(lblCont); - - // Setup stack for call to converter - AddConverterToStack(il, converter); - - il.Emit(OpCodes.Ldarg_0); // rdr - il.Emit(OpCodes.Ldc_I4_0); // rdr,0 - il.Emit(OpCodes.Callvirt, fnGetValue); // value - - // Call the converter - if (converter != null) - il.Emit(OpCodes.Callvirt, fnInvoke); - - il.MarkLabel(lblFin); - il.Emit(OpCodes.Unbox_Any, type); // value converted - } - else - { - // var poco=new T() - il.Emit(OpCodes.Newobj, type.GetConstructor(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic, null, new Type[0], null)); - - // Enumerate all fields generating a set assignment for the column - for (int i = firstColumn; i < firstColumn + countColumns; i++) - { - // Get the PocoColumn for this db column, ignore if not known - PocoColumn pc; - if (!Columns.TryGetValue(r.GetName(i), out pc)) - continue; - - // Get the source type for this column - var srcType = r.GetFieldType(i); - var dstType = pc.PropertyInfo.PropertyType; - - // "if (!rdr.IsDBNull(i))" - il.Emit(OpCodes.Ldarg_0); // poco,rdr - il.Emit(OpCodes.Ldc_I4, i); // poco,rdr,i - il.Emit(OpCodes.Callvirt, fnIsDBNull); // poco,bool - var lblNext = il.DefineLabel(); - il.Emit(OpCodes.Brtrue_S, lblNext); // poco - - il.Emit(OpCodes.Dup); // poco,poco - - // Do we need to install a converter? - var converter = GetConverter(ForceDateTimesToUtc, pc, srcType, dstType); - - // Fast - bool Handled = false; - if (converter == null) - { - var valuegetter = typeof(IDataRecord).GetMethod("Get" + srcType.Name, new Type[] { typeof(int) }); - if (valuegetter != null - && valuegetter.ReturnType == srcType - && (valuegetter.ReturnType == dstType || valuegetter.ReturnType == Nullable.GetUnderlyingType(dstType))) - { - il.Emit(OpCodes.Ldarg_0); // *,rdr - il.Emit(OpCodes.Ldc_I4, i); // *,rdr,i - il.Emit(OpCodes.Callvirt, valuegetter); // *,value - - // Convert to Nullable - if (Nullable.GetUnderlyingType(dstType) != null) - { - il.Emit(OpCodes.Newobj, dstType.GetConstructor(new Type[] { Nullable.GetUnderlyingType(dstType) })); - } - - il.Emit(OpCodes.Callvirt, pc.PropertyInfo.GetSetMethod(true)); // poco - Handled = true; - } - } - - // Not so fast - if (!Handled) - { - // Setup stack for call to converter - AddConverterToStack(il, converter); - - // "value = rdr.GetValue(i)" - il.Emit(OpCodes.Ldarg_0); // *,rdr - il.Emit(OpCodes.Ldc_I4, i); // *,rdr,i - il.Emit(OpCodes.Callvirt, fnGetValue); // *,value - - // Call the converter - if (converter != null) - il.Emit(OpCodes.Callvirt, fnInvoke); - - // Assign it - il.Emit(OpCodes.Unbox_Any, pc.PropertyInfo.PropertyType); // poco,poco,value - il.Emit(OpCodes.Callvirt, pc.PropertyInfo.GetSetMethod(true)); // poco - } - - il.MarkLabel(lblNext); - } - - var fnOnLoaded = RecurseInheritedTypes(type, (x) => x.GetMethod("OnLoaded", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic, null, new Type[0], null)); - if (fnOnLoaded != null) - { - il.Emit(OpCodes.Dup); - il.Emit(OpCodes.Callvirt, fnOnLoaded); - } - } - - il.Emit(OpCodes.Ret); - - // return it - var del = m.CreateDelegate(Expression.GetFuncType(typeof(IDataReader), type)); - - return del; - }; - - //lazy usage of AddOrGetExisting ref: http://stackoverflow.com/questions/10559279/how-to-deal-with-costly-building-operations-using-memorycache/15894928#15894928 - var newValue = new Lazy(factory); - // the line belows returns existing item or adds the new value if it doesn't exist - var value = (Lazy)objectCache.AddOrGetExisting(key, newValue, new CacheItemPolicy - { - //sliding expiration of 1 hr, if the same key isn't used in this - // timeframe it will be removed from the cache - SlidingExpiration = new TimeSpan(0, 0, SlidingExpirationSeconds) - }); - return (value ?? newValue).Value; // Lazy handles the locking itself - - } - - private static void AddConverterToStack(ILGenerator il, Func converter) - { - if (converter != null) - { - // Add the converter - int converterIndex = m_Converters.Count; - m_Converters.Add(converter); - - // Generate IL to push the converter onto the stack - il.Emit(OpCodes.Ldsfld, fldConverters); - il.Emit(OpCodes.Ldc_I4, converterIndex); - il.Emit(OpCodes.Callvirt, fnListGetItem); // Converter - } - } - - private static Func GetConverter(bool forceDateTimesToUtc, PocoColumn pc, Type srcType, Type dstType) - { - Func converter = null; - - // Get converter from the mapper - if (Database.Mapper != null) - { - if (pc != null) - { - converter = Database.Mapper.GetFromDbConverter(pc.PropertyInfo, srcType); - } - else - { - var m2 = Database.Mapper as IMapper2; - if (m2 != null) - { - converter = m2.GetFromDbConverter(dstType, srcType); - } - } - } - - // Standard DateTime->Utc mapper - if (forceDateTimesToUtc && converter == null && srcType == typeof(DateTime) && (dstType == typeof(DateTime) || dstType == typeof(DateTime?))) - { - converter = delegate(object src) { return new DateTime(((DateTime)src).Ticks, DateTimeKind.Utc); }; - } - - // Forced type conversion including integral types -> enum - if (converter == null) - { - if (dstType.IsEnum && IsIntegralType(srcType)) - { - if (srcType != typeof(int)) - { - converter = delegate(object src) { return Convert.ChangeType(src, typeof(int), null); }; - } - } - else if (!dstType.IsAssignableFrom(srcType)) - { - converter = delegate(object src) { return Convert.ChangeType(src, dstType, null); }; - } - } - return converter; - } - - - static T RecurseInheritedTypes(Type t, Func cb) - { - while (t != null) - { - T info = cb(t); - if (info != null) - return info; - t = t.BaseType; - } - return default(T); - } - - ManagedCache _managedCache = new ManagedCache(); - static Dictionary m_PocoDatas = new Dictionary(); - static List> m_Converters = new List>(); - static MethodInfo fnGetValue = typeof(IDataRecord).GetMethod("GetValue", new Type[] { typeof(int) }); - static MethodInfo fnIsDBNull = typeof(IDataRecord).GetMethod("IsDBNull"); - static FieldInfo fldConverters = typeof(PocoData).GetField("m_Converters", BindingFlags.Static | BindingFlags.GetField | BindingFlags.NonPublic); - static MethodInfo fnListGetItem = typeof(List>).GetProperty("Item").GetGetMethod(); - static MethodInfo fnInvoke = typeof(Func).GetMethod("Invoke"); - public Type type; - public string[] QueryColumns { get; private set; } - public TableInfo TableInfo { get; private set; } - public Dictionary Columns { get; private set; } - static System.Threading.ReaderWriterLockSlim InnerLock = new System.Threading.ReaderWriterLockSlim(); - - /// - /// Returns a report of the current cache being utilized by PetaPoco - /// - /// - public static string PrintDebugCacheReport(out double totalBytes, out IEnumerable allKeys) - { - var managedCache = new ManagedCache(); - - var sb = new StringBuilder(); - sb.AppendLine("m_PocoDatas:"); - foreach (var pocoData in m_PocoDatas) - { - sb.AppendFormat("\t{0}\n", pocoData.Key); - sb.AppendFormat("\t\tTable:{0} - Col count:{1}\n", pocoData.Value.TableInfo.TableName, pocoData.Value.QueryColumns.Length); - } - - var cache = managedCache.GetCache(); - allKeys = cache.Select(x => x.Key).ToArray(); - - sb.AppendFormat("\tTotal Poco data count:{0}\n", allKeys.Count()); - - var keys = string.Join("", cache.Select(x => x.Key)); - //Bytes in .Net are stored as utf-16 = unicode little endian - totalBytes = Encoding.Unicode.GetByteCount(keys); - - sb.AppendFormat("\tTotal byte for keys:{0}\n", totalBytes); - - sb.AppendLine("\tAll Poco cache items:"); - - foreach (var item in cache) - { - sb.AppendFormat("\t\t Key -> {0}\n", item.Key); - sb.AppendFormat("\t\t Value -> {0}\n", item.Value); - } - - sb.AppendLine("-------------------END REPORT------------------------"); - return sb.ToString(); - } - } - - - // Member variables - string _connectionString; - string _providerName; - DbProviderFactory _factory; - IDbConnection _sharedConnection; - IDbTransaction _transaction; - int _sharedConnectionDepth; - int _transactionDepth; - bool _transactionCancelled; - string _lastSql; - object[] _lastArgs; - string _paramPrefix = "@"; - IsolationLevel _isolationLevel; - } - - // Transaction object helps maintain transaction depth counts - public class Transaction : IDisposable - { - public Transaction(Database db, IsolationLevel isolationLevel) - { - _db = db; - _db.BeginTransaction(isolationLevel); - } - - public virtual void Complete() - { - _db.CompleteTransaction(); - _db = null; - } - - public void Dispose() - { - //TODO prevent multiple calls to Dispose - if (_db != null) - _db.AbortTransaction(); - } - - Database _db; - } - - // Simple helper class for building SQL statments - public class Sql - { - public Sql() - { - } - - public Sql(string sql, params object[] args) - { - _sql = sql; - _args = args; - } - - string _sql; - object[] _args; - Sql _rhs; - string _sqlFinal; - object[] _argsFinal; - - private void Build() - { - // already built? - if (_sqlFinal != null) - return; - - // Build it - var sb = new StringBuilder(); - var args = new List(); - Build(sb, args, null); - _sqlFinal = sb.ToString(); - _argsFinal = args.ToArray(); - } - - public string SQL - { - get - { - Build(); - return _sqlFinal; - } - } - - public object[] Arguments - { - get - { - Build(); - return _argsFinal; - } - } - - public Sql Append(Sql sql) - { - if (_rhs != null) - _rhs.Append(sql); - else - _rhs = sql; - - return this; - } - - public Sql Append(string sql, params object[] args) - { - return Append(new Sql(sql, args)); - } - - static bool Is(Sql sql, string sqltype) - { - return sql != null && sql._sql != null && sql._sql.StartsWith(sqltype, StringComparison.InvariantCultureIgnoreCase); - } - - private void Build(StringBuilder sb, List args, Sql lhs) - { - if (!String.IsNullOrEmpty(_sql)) - { - // Add SQL to the string - if (sb.Length > 0) - { - sb.Append("\n"); - } - - var sql = Database.ProcessParams(_sql, _args, args); - - if (Is(lhs, "WHERE ") && Is(this, "WHERE ")) - sql = "AND " + sql.Substring(6); - if (Is(lhs, "ORDER BY ") && Is(this, "ORDER BY ")) - sql = ", " + sql.Substring(9); - - sb.Append(sql); - } - - // Now do rhs - if (_rhs != null) - _rhs.Build(sb, args, this); - } - - public Sql Where(string sql, params object[] args) - { - return Append(new Sql("WHERE (" + sql + ")", args)); - } - - public Sql OrderBy(params object[] columns) - { - return Append(new Sql("ORDER BY " + String.Join(", ", (from x in columns select x.ToString()).ToArray()))); - } - - public Sql Select(params object[] columns) - { - return Append(new Sql("SELECT " + String.Join(", ", (from x in columns select x.ToString()).ToArray()))); - } - - public Sql From(params object[] tables) - { - return Append(new Sql("FROM " + String.Join(", ", (from x in tables select x.ToString()).ToArray()))); - } - - public Sql GroupBy(params object[] columns) - { - return Append(new Sql("GROUP BY " + String.Join(", ", (from x in columns select x.ToString()).ToArray()))); - } - - private SqlJoinClause Join(string JoinType, string table) - { - return new SqlJoinClause(Append(new Sql(JoinType + table))); - } - - public SqlJoinClause InnerJoin(string table) { return Join("INNER JOIN ", table); } - public SqlJoinClause LeftJoin(string table) { return Join("LEFT JOIN ", table); } - public SqlJoinClause LeftOuterJoin(string table) { return Join("LEFT OUTER JOIN ", table); } - public SqlJoinClause RightJoin(string table) { return Join("RIGHT JOIN ", table); } - - public class SqlJoinClause - { - private readonly Sql _sql; - - public SqlJoinClause(Sql sql) - { - _sql = sql; - } - - public Sql On(string onClause, params object[] args) - { - return _sql.Append("ON " + onClause, args); - } - } - } - -} diff --git a/src/Umbraco.Core/Persistence/PetaPocoCommandExtensions.cs b/src/Umbraco.Core/Persistence/PetaPocoCommandExtensions.cs deleted file mode 100644 index f1b41f2420..0000000000 --- a/src/Umbraco.Core/Persistence/PetaPocoCommandExtensions.cs +++ /dev/null @@ -1,277 +0,0 @@ -using System; -using System.Data; -using System.Data.SqlClient; -using Umbraco.Core.Persistence.FaultHandling; - -namespace Umbraco.Core.Persistence -{ - /// - /// Provides a set of extension methods adding retry capabilities into the standard implementation, which is used in PetaPoco. - /// - public static class PetaPocoCommandExtensions - { - #region ExecuteNonQueryWithRetry method implementations - /// - /// Executes a Transact-SQL statement against the connection and returns the number of rows affected. Uses the default retry policy when executing the command. - /// - /// The command object that is required as per extension method declaration. - /// The number of rows affected. - public static int ExecuteNonQueryWithRetry(this IDbCommand command) - { - var connectionString = command.Connection.ConnectionString ?? string.Empty; - return ExecuteNonQueryWithRetry(command, RetryPolicyFactory.GetDefaultSqlCommandRetryPolicyByConnectionString(connectionString)); - } - - /// - /// Executes a Transact-SQL statement against the connection and returns the number of rows affected. Uses the specified retry policy when executing the command. - /// - /// The command object that is required as per extension method declaration. - /// The retry policy defining whether to retry a command if a connection fails while executing the command. - /// The number of rows affected. - public static int ExecuteNonQueryWithRetry(this IDbCommand command, RetryPolicy retryPolicy) - { - var connectionString = command.Connection.ConnectionString ?? string.Empty; - return ExecuteNonQueryWithRetry(command, retryPolicy, RetryPolicyFactory.GetDefaultSqlConnectionRetryPolicyByConnectionString(connectionString)); - } - - /// - /// Executes a Transact-SQL statement against the connection and returns the number of rows affected. Uses the specified retry policy when executing the command. - /// Uses a separate specified retry policy when establishing a connection. - /// - /// The command object that is required as per extension method declaration. - /// The command retry policy defining whether to retry a command if it fails while executing. - /// The connection retry policy defining whether to re-establish a connection if it drops while executing the command. - /// The number of rows affected. - public static int ExecuteNonQueryWithRetry(this IDbCommand command, RetryPolicy cmdRetryPolicy, RetryPolicy conRetryPolicy) - { - //GuardConnectionIsNotNull(command); - - // Check if retry policy was specified, if not, use the default retry policy. - return (cmdRetryPolicy ?? RetryPolicy.NoRetry).ExecuteAction(() => - { - var hasOpenConnection = EnsureValidConnection(command, conRetryPolicy); - - try - { - return command.ExecuteNonQuery(); - } - finally - { - if (hasOpenConnection && command.Connection != null && command.Connection.State == ConnectionState.Open) - { - //Connection is closed in PetaPoco, so no need to do it here (?) - //command.Connection.Close(); - } - } - }); - } - #endregion - - #region ExecuteReaderWithRetry method implementations - /// - /// Sends the specified command to the connection and builds a SqlDataReader object containing the results. - /// Uses the default retry policy when executing the command. - /// - /// The command object that is required as per extension method declaration. - /// A System.Data.IDataReader object. - public static IDataReader ExecuteReaderWithRetry(this IDbCommand command) - { - var connectionString = command.Connection.ConnectionString ?? string.Empty; - return ExecuteReaderWithRetry(command, RetryPolicyFactory.GetDefaultSqlCommandRetryPolicyByConnectionString(connectionString)); - } - - /// - /// Sends the specified command to the connection and builds a SqlDataReader object containing the results. - /// Uses the specified retry policy when executing the command. - /// - /// The command object that is required as per extension method declaration. - /// The retry policy defining whether to retry a command if a connection fails while executing the command. - /// A System.Data.IDataReader object. - public static IDataReader ExecuteReaderWithRetry(this IDbCommand command, RetryPolicy retryPolicy) - { - var connectionString = command.Connection.ConnectionString ?? string.Empty; - return ExecuteReaderWithRetry(command, retryPolicy, RetryPolicyFactory.GetDefaultSqlConnectionRetryPolicyByConnectionString(connectionString)); - } - - /// - /// Sends the specified command to the connection and builds a SqlDataReader object containing the results. - /// Uses the specified retry policy when executing the command. Uses a separate specified retry policy when - /// establishing a connection. - /// - /// The command object that is required as per extension method declaration. - /// The command retry policy defining whether to retry a command if it fails while executing. - /// The connection retry policy defining whether to re-establish a connection if it drops while executing the command. - /// A System.Data.IDataReader object. - public static IDataReader ExecuteReaderWithRetry(this IDbCommand command, RetryPolicy cmdRetryPolicy, RetryPolicy conRetryPolicy) - { - //GuardConnectionIsNotNull(command); - - // Check if retry policy was specified, if not, use the default retry policy. - return (cmdRetryPolicy ?? RetryPolicy.NoRetry).ExecuteAction(() => - { - var hasOpenConnection = EnsureValidConnection(command, conRetryPolicy); - - try - { - return command.ExecuteReader(); - } - catch (Exception) - { - if (hasOpenConnection && command.Connection != null && command.Connection.State == ConnectionState.Open) - { - //command.Connection.Close(); - } - - throw; - } - }); - } - - /// - /// Sends the specified command to the connection and builds a SqlDataReader object using one of the - /// CommandBehavior values. Uses the default retry policy when executing the command. - /// - /// The command object that is required as per extension method declaration. - /// One of the System.Data.CommandBehavior values. - /// A System.Data.IDataReader object. - public static IDataReader ExecuteReaderWithRetry(this IDbCommand command, CommandBehavior behavior) - { - var connectionString = command.Connection.ConnectionString ?? string.Empty; - return ExecuteReaderWithRetry(command, behavior, RetryPolicyFactory.GetDefaultSqlCommandRetryPolicyByConnectionString(connectionString)); - } - - /// - /// Sends the specified command to the connection and builds a SqlDataReader object using one of the - /// CommandBehavior values. Uses the specified retry policy when executing the command. - /// - /// The command object that is required as per extension method declaration. - /// One of the System.Data.CommandBehavior values. - /// The retry policy defining whether to retry a command if a connection fails while executing the command. - /// A System.Data.SqlClient.SqlDataReader object. - public static IDataReader ExecuteReaderWithRetry(this IDbCommand command, CommandBehavior behavior, RetryPolicy retryPolicy) - { - var connectionString = command.Connection.ConnectionString ?? string.Empty; - return ExecuteReaderWithRetry(command, behavior, retryPolicy, RetryPolicyFactory.GetDefaultSqlConnectionRetryPolicyByConnectionString(connectionString)); - } - - /// - /// Sends the specified command to the connection and builds a SqlDataReader object using one of the - /// CommandBehavior values. Uses the specified retry policy when executing the command. - /// Uses a separate specified retry policy when establishing a connection. - /// - /// The command object that is required as per extension method declaration. - /// One of the System.Data.CommandBehavior values. - /// The command retry policy defining whether to retry a command if it fails while executing. - /// The connection retry policy defining whether to re-establish a connection if it drops while executing the command. - /// A System.Data.IDataReader object. - public static IDataReader ExecuteReaderWithRetry(this IDbCommand command, CommandBehavior behavior, RetryPolicy cmdRetryPolicy, RetryPolicy conRetryPolicy) - { - //GuardConnectionIsNotNull(command); - - // Check if retry policy was specified, if not, use the default retry policy. - return (cmdRetryPolicy ?? RetryPolicy.NoRetry).ExecuteAction(() => - { - var hasOpenConnection = EnsureValidConnection(command, conRetryPolicy); - - try - { - return command.ExecuteReader(behavior); - } - catch (Exception) - { - if (hasOpenConnection && command.Connection != null && command.Connection.State == ConnectionState.Open) - { - //command.Connection.Close(); - } - - throw; - } - }); - } - #endregion - - #region ExecuteScalarWithRetry method implementations - /// - /// Executes the query, and returns the first column of the first row in the result set returned by the query. Additional columns or rows are ignored. - /// Uses the default retry policy when executing the command. - /// - /// The command object that is required as per extension method declaration. - /// The first column of the first row in the result set, or a null reference if the result set is empty. Returns a maximum of 2033 characters. - public static object ExecuteScalarWithRetry(this IDbCommand command) - { - var connectionString = command.Connection.ConnectionString ?? string.Empty; - return ExecuteScalarWithRetry(command, RetryPolicyFactory.GetDefaultSqlCommandRetryPolicyByConnectionString(connectionString)); - } - - /// - /// Executes the query, and returns the first column of the first row in the result set returned by the query. Additional columns or rows are ignored. - /// Uses the specified retry policy when executing the command. - /// - /// The command object that is required as per extension method declaration. - /// The retry policy defining whether to retry a command if a connection fails while executing the command. - /// The first column of the first row in the result set, or a null reference if the result set is empty. Returns a maximum of 2033 characters. - public static object ExecuteScalarWithRetry(this IDbCommand command, RetryPolicy retryPolicy) - { - var connectionString = command.Connection.ConnectionString ?? string.Empty; - return ExecuteScalarWithRetry(command, retryPolicy, RetryPolicyFactory.GetDefaultSqlConnectionRetryPolicyByConnectionString(connectionString)); - } - /// - /// Executes the query, and returns the first column of the first row in the result set returned by the query. Additional columns or rows are ignored. - /// Uses the specified retry policy when executing the command. Uses a separate specified retry policy when establishing a connection. - /// - /// The command object that is required as per extension method declaration. - /// The command retry policy defining whether to retry a command if it fails while executing. - /// The connection retry policy defining whether to re-establish a connection if it drops while executing the command. - /// The first column of the first row in the result set, or a null reference if the result set is empty. Returns a maximum of 2033 characters. - public static object ExecuteScalarWithRetry(this IDbCommand command, RetryPolicy cmdRetryPolicy, RetryPolicy conRetryPolicy) - { - //GuardConnectionIsNotNull(command); - - // Check if retry policy was specified, if not, use the default retry policy. - return (cmdRetryPolicy ?? RetryPolicy.NoRetry).ExecuteAction(() => - { - var hasOpenConnection = EnsureValidConnection(command, conRetryPolicy); - - try - { - return command.ExecuteScalar(); - } - finally - { - if (hasOpenConnection && command.Connection != null && command.Connection.State == ConnectionState.Open) - { - //Connection is closed in PetaPoco, so no need to do it here (?) - //command.Connection.Close(); - } - } - }); - } - #endregion - - /// - /// Ensure a valid connection in case a connection hasn't been opened by PetaPoco (which shouldn't be possible by the way). - /// - /// - /// - /// - private static bool EnsureValidConnection(IDbCommand command, RetryPolicy retryPolicy) - { - if (command != null) - { - //GuardConnectionIsNotNull(command); - - // Verify whether or not the connection is valid and is open. This code may be retried therefore - // it is important to ensure that a connection is re-established should it have previously failed. - if (command.Connection.State != ConnectionState.Open) - { - // Attempt to open the connection using the retry policy that matches the policy for SQL commands. - command.Connection.OpenWithRetry(retryPolicy); - - return true; - } - } - - return false; - } - } -} \ No newline at end of file diff --git a/src/Umbraco.Core/Persistence/PetaPocoConnectionExtensions.cs b/src/Umbraco.Core/Persistence/PetaPocoConnectionExtensions.cs deleted file mode 100644 index e13608bc31..0000000000 --- a/src/Umbraco.Core/Persistence/PetaPocoConnectionExtensions.cs +++ /dev/null @@ -1,35 +0,0 @@ -using System.Data; -using Umbraco.Core.Persistence.FaultHandling; - -namespace Umbraco.Core.Persistence -{ - /// - /// Provides a set of extension methods adding retry capabilities into the standard interface, which is used in PetaPoco. - /// - public static class PetaPocoConnectionExtensions - { - /// - /// Opens a database connection with the connection settings specified in the ConnectionString property of the connection object. - /// Uses the default retry policy when opening the connection. - /// - /// The connection object that is required as per extension method declaration. - public static void OpenWithRetry(this IDbConnection connection) - { - var connectionString = connection.ConnectionString ?? string.Empty; - var retryPolicy = RetryPolicyFactory.GetDefaultSqlConnectionRetryPolicyByConnectionString(connectionString); - OpenWithRetry(connection, retryPolicy); - } - - /// - /// Opens a database connection with the connection settings specified in the ConnectionString property of the connection object. - /// Uses the specified retry policy when opening the connection. - /// - /// The connection object that is required as per extension method declaration. - /// The retry policy defining whether to retry a request if the connection fails to be opened. - public static void OpenWithRetry(this IDbConnection connection, RetryPolicy retryPolicy) - { - // Check if retry policy was specified, if not, use the default retry policy. - (retryPolicy != null ? retryPolicy : RetryPolicy.NoRetry).ExecuteAction(connection.Open); - } - } -} \ No newline at end of file diff --git a/src/Umbraco.Core/Persistence/PetaPocoSqlExtensions.cs b/src/Umbraco.Core/Persistence/PetaPocoSqlExtensions.cs deleted file mode 100644 index 8603481376..0000000000 --- a/src/Umbraco.Core/Persistence/PetaPocoSqlExtensions.cs +++ /dev/null @@ -1,143 +0,0 @@ -using System; -using System.Collections; -using System.Linq; -using System.Linq.Expressions; -using System.Reflection; -using Umbraco.Core.Persistence.Querying; -using Umbraco.Core.Persistence.SqlSyntax; - -namespace Umbraco.Core.Persistence -{ - /// - /// Extension methods adding strong types to PetaPoco's Sql Builder - /// - public static class PetaPocoSqlExtensions - { - - public static Sql From(this Sql sql, ISqlSyntaxProvider sqlSyntax) - { - var type = typeof(T); - var tableNameAttribute = type.FirstAttribute(); - string tableName = tableNameAttribute == null ? string.Empty : tableNameAttribute.Value; - - return sql.From(sqlSyntax.GetQuotedTableName(tableName)); - } - - public static Sql Where(this Sql sql, ISqlSyntaxProvider sqlSyntax, Expression> predicate) - { - var expresionist = new PocoToSqlExpressionHelper(sqlSyntax); - var whereExpression = expresionist.Visit(predicate); - return sql.Where(whereExpression, expresionist.GetSqlParameters()); - } - - public static Sql WhereIn(this Sql sql, ISqlSyntaxProvider sqlSyntax, Expression> fieldSelector, IEnumerable values) - { - var expresionist = new PocoToSqlExpressionHelper(sqlSyntax); - var fieldExpression = expresionist.Visit(fieldSelector); - return sql.Where(fieldExpression + " IN (@values)", new {@values = values}); - } - - public static Sql OrderBy(this Sql sql, ISqlSyntaxProvider sqlSyntax, Expression> columnMember) - { - var column = ExpressionHelper.FindProperty(columnMember) as PropertyInfo; - var columnName = column.FirstAttribute().Name; - - var type = typeof(TColumn); - var tableNameAttribute = type.FirstAttribute(); - string tableName = tableNameAttribute == null ? string.Empty : tableNameAttribute.Value; - - //need to ensure the order by is in brackets, see: https://github.com/toptensoftware/PetaPoco/issues/177 - var syntax = string.Format("({0}.{1})", - sqlSyntax.GetQuotedTableName(tableName), - sqlSyntax.GetQuotedColumnName(columnName)); - - return sql.OrderBy(syntax); - } - - public static Sql OrderByDescending(this Sql sql, ISqlSyntaxProvider sqlSyntax, Expression> columnMember) - { - var column = ExpressionHelper.FindProperty(columnMember) as PropertyInfo; - var columnName = column.FirstAttribute().Name; - - var type = typeof(TColumn); - var tableNameAttribute = type.FirstAttribute(); - string tableName = tableNameAttribute == null ? string.Empty : tableNameAttribute.Value; - - var syntax = string.Format("{0}.{1} DESC", - sqlSyntax.GetQuotedTableName(tableName), - sqlSyntax.GetQuotedColumnName(columnName)); - - return sql.OrderBy(syntax); - } - - public static Sql GroupBy(this Sql sql, ISqlSyntaxProvider sqlProvider, Expression> columnMember) - { - var column = ExpressionHelper.FindProperty(columnMember) as PropertyInfo; - var columnName = column.FirstAttribute().Name; - - return sql.GroupBy(sqlProvider.GetQuotedColumnName(columnName)); - } - - public static Sql.SqlJoinClause InnerJoin(this Sql sql, ISqlSyntaxProvider sqlSyntax) - { - var type = typeof(T); - var tableNameAttribute = type.FirstAttribute(); - string tableName = tableNameAttribute == null ? string.Empty : tableNameAttribute.Value; - - return sql.InnerJoin(sqlSyntax.GetQuotedTableName(tableName)); - } - - public static Sql.SqlJoinClause LeftJoin(this Sql sql, ISqlSyntaxProvider sqlSyntax) - { - var type = typeof(T); - var tableNameAttribute = type.FirstAttribute(); - string tableName = tableNameAttribute == null ? string.Empty : tableNameAttribute.Value; - - return sql.LeftJoin(sqlSyntax.GetQuotedTableName(tableName)); - } - - public static Sql.SqlJoinClause LeftOuterJoin(this Sql sql, ISqlSyntaxProvider sqlSyntax) - { - var type = typeof(T); - var tableNameAttribute = type.FirstAttribute(); - string tableName = tableNameAttribute == null ? string.Empty : tableNameAttribute.Value; - - return sql.LeftOuterJoin(sqlSyntax.GetQuotedTableName(tableName)); - } - - public static Sql.SqlJoinClause RightJoin(this Sql sql, ISqlSyntaxProvider sqlSyntax) - { - var type = typeof(T); - var tableNameAttribute = type.FirstAttribute(); - string tableName = tableNameAttribute == null ? string.Empty : tableNameAttribute.Value; - - return sql.RightJoin(sqlSyntax.GetQuotedTableName(tableName)); - } - - public static Sql On(this Sql.SqlJoinClause sql, ISqlSyntaxProvider sqlSyntax, Expression> leftMember, - Expression> rightMember, params object[] args) - { - var leftType = typeof(TLeft); - var rightType = typeof(TRight); - var leftTableName = leftType.FirstAttribute().Value; - var rightTableName = rightType.FirstAttribute().Value; - - var left = ExpressionHelper.FindProperty(leftMember) as PropertyInfo; - var right = ExpressionHelper.FindProperty(rightMember) as PropertyInfo; - var leftColumnName = left.FirstAttribute().Name; - var rightColumnName = right.FirstAttribute().Name; - - string onClause = string.Format("{0}.{1} = {2}.{3}", - sqlSyntax.GetQuotedTableName(leftTableName), - sqlSyntax.GetQuotedColumnName(leftColumnName), - sqlSyntax.GetQuotedTableName(rightTableName), - sqlSyntax.GetQuotedColumnName(rightColumnName)); - return sql.On(onClause); - } - - public static Sql OrderByDescending(this Sql sql, params object[] columns) - { - return sql.Append(new Sql("ORDER BY " + String.Join(", ", (from x in columns select x + " DESC").ToArray()))); - } - } -} \ No newline at end of file diff --git a/src/Umbraco.Core/Persistence/Querying/BaseExpressionHelper.cs b/src/Umbraco.Core/Persistence/Querying/BaseExpressionHelper.cs index 05d9646b18..50e1ea0106 100644 --- a/src/Umbraco.Core/Persistence/Querying/BaseExpressionHelper.cs +++ b/src/Umbraco.Core/Persistence/Querying/BaseExpressionHelper.cs @@ -10,6 +10,8 @@ using Umbraco.Core.Persistence.SqlSyntax; namespace Umbraco.Core.Persistence.Querying { + // fixme.npoco - are we basically duplicating entire parts of NPoco just because of SqlSyntax ?! + internal abstract class BaseExpressionHelper : BaseExpressionHelper { protected BaseExpressionHelper(ISqlSyntaxProvider sqlSyntax) @@ -151,13 +153,13 @@ namespace Umbraco.Core.Persistence.Querying { // deal with (x != true|false) - most common var constRight = b.Right as ConstantExpression; - if (constRight != null && constRight.Type == typeof(bool)) + if (constRight != null && constRight.Type == typeof (bool)) return ((bool) constRight.Value) ? VisitNot(b.Left) : VisitNotNot(b.Left); right = Visit(b.Right); // deal with (true|false != x) - why not var constLeft = b.Left as ConstantExpression; - if (constLeft != null && constLeft.Type == typeof(bool)) + if (constLeft != null && constLeft.Type == typeof (bool)) return ((bool) constLeft.Value) ? VisitNot(b.Right) : VisitNotNot(b.Right); left = Visit(b.Left); } @@ -578,11 +580,11 @@ namespace Umbraco.Core.Persistence.Querying /// /// Logic that is shared with the expression helpers /// - internal class BaseExpressionHelper + internal abstract class BaseExpressionHelper { public ISqlSyntaxProvider SqlSyntax { get; private set; } - public BaseExpressionHelper(ISqlSyntaxProvider sqlSyntax) + protected BaseExpressionHelper(ISqlSyntaxProvider sqlSyntax) { SqlSyntax = sqlSyntax; } diff --git a/src/Umbraco.Core/Persistence/Querying/PocoToSqlExpressionHelper.cs b/src/Umbraco.Core/Persistence/Querying/PocoToSqlExpressionHelper.cs index 32e86f9512..958854727a 100644 --- a/src/Umbraco.Core/Persistence/Querying/PocoToSqlExpressionHelper.cs +++ b/src/Umbraco.Core/Persistence/Querying/PocoToSqlExpressionHelper.cs @@ -1,63 +1,51 @@ using System; -using System.Collections; -using System.Collections.Generic; -using System.Collections.ObjectModel; using System.Linq; using System.Linq.Expressions; -using System.Text; -using Umbraco.Core.Persistence.SqlSyntax; +using NPoco; namespace Umbraco.Core.Persistence.Querying { internal class PocoToSqlExpressionHelper : BaseExpressionHelper { - private readonly Database.PocoData _pd; + private readonly PocoData _pd; - public PocoToSqlExpressionHelper(ISqlSyntaxProvider sqlSyntaxProvider) - : base(sqlSyntaxProvider) + public PocoToSqlExpressionHelper(SqlContext sqlContext) + : base(sqlContext.SqlSyntax) { - _pd = new Database.PocoData(typeof(T)); + _pd = sqlContext.PocoDataFactory.ForType(typeof (T)); } protected override string VisitMemberAccess(MemberExpression m) { - if (m.Expression != null && - m.Expression.NodeType == ExpressionType.Parameter - && m.Expression.Type == typeof(T)) + if (m.Expression != null && m.Expression.NodeType == ExpressionType.Parameter && m.Expression.Type == typeof (T)) { - string field = GetFieldName(_pd, m.Member.Name); + var field = GetFieldName(_pd, m.Member.Name); return field; } if (m.Expression != null && m.Expression.NodeType == ExpressionType.Convert) { - string field = GetFieldName(_pd, m.Member.Name); + var field = GetFieldName(_pd, m.Member.Name); return field; } var member = Expression.Convert(m, typeof(object)); var lambda = Expression.Lambda>(member); var getter = lambda.Compile(); - object o = getter(); + var o = getter(); SqlParameters.Add(o); - return string.Format("@{0}", SqlParameters.Count - 1); - - //return GetQuotedValue(o, o != null ? o.GetType() : null); + return $"@{SqlParameters.Count - 1}"; } - protected virtual string GetFieldName(Database.PocoData pocoData, string name) + protected virtual string GetFieldName(PocoData pocoData, string name) { - var column = pocoData.Columns.FirstOrDefault(x => x.Value.PropertyInfo.Name == name); - return string.Format("{0}.{1}", - SqlSyntax.GetQuotedTableName(pocoData.TableInfo.TableName), - SqlSyntax.GetQuotedColumnName(column.Value.ColumnName)); - } + var column = pocoData.Columns.FirstOrDefault(x => x.Value.MemberInfoData.Name == name); + var tableName = SqlSyntax.GetQuotedTableName(pocoData.TableInfo.TableName); + var columnName = SqlSyntax.GetQuotedColumnName(column.Value.ColumnName); - //protected bool IsFieldName(string quotedExp) - //{ - // return true; - //} + return $"{tableName}.{columnName}"; + } } } \ No newline at end of file diff --git a/src/Umbraco.Core/Persistence/Querying/SqlTranslator.cs b/src/Umbraco.Core/Persistence/Querying/SqlTranslator.cs index b012293340..94434fca74 100644 --- a/src/Umbraco.Core/Persistence/Querying/SqlTranslator.cs +++ b/src/Umbraco.Core/Persistence/Querying/SqlTranslator.cs @@ -1,4 +1,5 @@ using System; +using NPoco; namespace Umbraco.Core.Persistence.Querying { @@ -8,9 +9,9 @@ namespace Umbraco.Core.Persistence.Querying /// internal class SqlTranslator { - private readonly Sql _sql; + private readonly Sql _sql; - public SqlTranslator(Sql sql, IQuery query) + public SqlTranslator(Sql sql, IQuery query) { if (sql == null) throw new Exception("Sql cannot be null"); @@ -22,7 +23,7 @@ namespace Umbraco.Core.Persistence.Querying } } - public Sql Translate() + public Sql Translate() { return _sql; } diff --git a/src/Umbraco.Core/Persistence/Relators/AccessRulesRelator.cs b/src/Umbraco.Core/Persistence/Relators/AccessRulesRelator.cs deleted file mode 100644 index bcb33f3597..0000000000 --- a/src/Umbraco.Core/Persistence/Relators/AccessRulesRelator.cs +++ /dev/null @@ -1,51 +0,0 @@ -using System; -using System.Collections.Generic; -using Umbraco.Core.Models.Rdbms; - -namespace Umbraco.Core.Persistence.Relators -{ - internal class AccessRulesRelator - { - internal AccessDto Current; - - internal AccessDto Map(AccessDto a, AccessRuleDto p) - { - // Terminating call. Since we can return null from this function - // we need to be ready for PetaPoco to callback later with null - // parameters - if (a == null) - return Current; - - // Is this the same AccessDto as the current one we're processing - if (Current != null && Current.Id == a.Id) - { - // Yes, just add this AccessRuleDto to the current AccessDto's collection - if (p.Id != default(Guid)) - { - Current.Rules.Add(p); - } - - - // Return null to indicate we're not done with this AccessDto yet - return null; - } - - // This is a different AccessDto to the current one, or this is the - // first time through and we don't have a Tab yet - - // Save the current AccessDto - var prev = Current; - - // Setup the new current AccessDto - Current = a; - Current.Rules = new List(); - if (p.Id != default(Guid)) - { - Current.Rules.Add(p); - } - - // Return the now populated previous AccessDto (or null if first time through) - return prev; - } - } -} \ No newline at end of file diff --git a/src/Umbraco.Core/Persistence/Relators/DictionaryLanguageTextRelator.cs b/src/Umbraco.Core/Persistence/Relators/DictionaryLanguageTextRelator.cs deleted file mode 100644 index 6e2173471c..0000000000 --- a/src/Umbraco.Core/Persistence/Relators/DictionaryLanguageTextRelator.cs +++ /dev/null @@ -1,43 +0,0 @@ -using System.Collections.Generic; -using Umbraco.Core.Models.Rdbms; - -namespace Umbraco.Core.Persistence.Relators -{ - internal class DictionaryLanguageTextRelator - { - internal DictionaryDto Current; - - internal DictionaryDto Map(DictionaryDto a, LanguageTextDto p) - { - // Terminating call. Since we can return null from this function - // we need to be ready for PetaPoco to callback later with null - // parameters - if (a == null) - return Current; - - // Is this the same DictionaryItem as the current one we're processing - if (Current != null && Current.UniqueId == a.UniqueId) - { - // Yes, just add this LanguageTextDto to the current DictionaryItem's collection - Current.LanguageTextDtos.Add(p); - - // Return null to indicate we're not done with this DictionaryItem yet - return null; - } - - // This is a different DictionaryItem to the current one, or this is the - // first time through and we don't have a Tab yet - - // Save the current DictionaryItem - var prev = Current; - - // Setup the new current DictionaryItem - Current = a; - Current.LanguageTextDtos = new List(); - Current.LanguageTextDtos.Add(p); - - // Return the now populated previous DictionaryItem (or null if first time through) - return prev; - } - } -} \ No newline at end of file diff --git a/src/Umbraco.Core/Persistence/Relators/GroupPropertyTypeRelator.cs b/src/Umbraco.Core/Persistence/Relators/GroupPropertyTypeRelator.cs deleted file mode 100644 index 616882f068..0000000000 --- a/src/Umbraco.Core/Persistence/Relators/GroupPropertyTypeRelator.cs +++ /dev/null @@ -1,48 +0,0 @@ -using System.Collections.Generic; -using Umbraco.Core.Models.Rdbms; - -namespace Umbraco.Core.Persistence.Relators -{ - internal class GroupPropertyTypeRelator - { - internal PropertyTypeGroupDto current; - - internal PropertyTypeGroupDto Map(PropertyTypeGroupDto a, PropertyTypeDto p, DataTypeDto d) - { - // Terminating call. Since we can return null from this function - // we need to be ready for PetaPoco to callback later with null - // parameters - if (a == null) - return current; - - //Set the PropertyTypeDto's DataTypeDto object - if (p.DataTypeId == d.DataTypeId) - p.DataTypeDto = d; - - // Is this the same Group as the current one we're processing - if (current != null && current.Id == a.Id) - { - // Yes, just add this PropertyType to the current Group's collection of PropertyTypes - current.PropertyTypeDtos.Add(p); - - // Return null to indicate we're not done with this Group yet - return null; - } - - // This is a different Group to the current one, or this is the - // first time through and we don't have a Tab yet - - // Save the current Group - var prev = current; - - // Setup the new current Group - current = a; - current.PropertyTypeDtos = new List(); - current.PropertyTypeDtos.Add(p); - - // Return the now populated previous Tab (or null if first time through) - return prev; - } - - } -} \ No newline at end of file diff --git a/src/Umbraco.Core/Persistence/Relators/MacroPropertyRelator.cs b/src/Umbraco.Core/Persistence/Relators/MacroPropertyRelator.cs deleted file mode 100644 index 2f457edfd8..0000000000 --- a/src/Umbraco.Core/Persistence/Relators/MacroPropertyRelator.cs +++ /dev/null @@ -1,89 +0,0 @@ -using System.Collections.Generic; -using Umbraco.Core.Models.Rdbms; - -namespace Umbraco.Core.Persistence.Relators -{ - //internal class TaskUserRelator - //{ - // internal TaskDto Current; - - // internal TaskDto Map(TaskDto a, UserDto p) - // { - // // Terminating call. Since we can return null from this function - // // we need to be ready for PetaPoco to callback later with null - // // parameters - // if (a == null) - // return Current; - - // // Is this the same TaskDto as the current one we're processing - // if (Current != null && Current.Id == a.Id) - // { - // // Yes, set the user - // Current.MacroPropertyDtos.Add(p); - - // // Return null to indicate we're not done with this Macro yet - // return null; - // } - - // // This is a different Macro to the current one, or this is the - // // first time through and we don't have one yet - - // // Save the current Macro - // var prev = Current; - - // // Setup the new current Macro - // Current = a; - // Current.MacroPropertyDtos = new List(); - // //this can be null since we are doing a left join - // if (p.Alias != null) - // { - // Current.MacroPropertyDtos.Add(p); - // } - - // // Return the now populated previous Macro (or null if first time through) - // return prev; - // } - //} - - internal class MacroPropertyRelator - { - internal MacroDto Current; - - internal MacroDto Map(MacroDto a, MacroPropertyDto p) - { - // Terminating call. Since we can return null from this function - // we need to be ready for PetaPoco to callback later with null - // parameters - if (a == null) - return Current; - - // Is this the same DictionaryItem as the current one we're processing - if (Current != null && Current.Id == a.Id) - { - // Yes, just add this MacroPropertyDtos to the current item's collection - Current.MacroPropertyDtos.Add(p); - - // Return null to indicate we're not done with this Macro yet - return null; - } - - // This is a different Macro to the current one, or this is the - // first time through and we don't have one yet - - // Save the current Macro - var prev = Current; - - // Setup the new current Macro - Current = a; - Current.MacroPropertyDtos = new List(); - //this can be null since we are doing a left join - if (p.Alias != null) - { - Current.MacroPropertyDtos.Add(p); - } - - // Return the now populated previous Macro (or null if first time through) - return prev; - } - } -} \ No newline at end of file diff --git a/src/Umbraco.Core/Persistence/Relators/PropertyTypePropertyGroupRelator.cs b/src/Umbraco.Core/Persistence/Relators/PropertyTypePropertyGroupRelator.cs deleted file mode 100644 index bf307ea594..0000000000 --- a/src/Umbraco.Core/Persistence/Relators/PropertyTypePropertyGroupRelator.cs +++ /dev/null @@ -1,63 +0,0 @@ -using System.Collections.Generic; -using System.Linq; -using Umbraco.Core.Models.Rdbms; - -namespace Umbraco.Core.Persistence.Relators -{ - internal class PropertyTypePropertyGroupRelator - { - internal MemberTypeReadOnlyDto Current; - - internal MemberTypeReadOnlyDto Map(MemberTypeReadOnlyDto a, PropertyTypeReadOnlyDto p, PropertyTypeGroupReadOnlyDto g) - { - // Terminating call. Since we can return null from this function - // we need to be ready for PetaPoco to callback later with null - // parameters - if (a == null) - return Current; - - // Is this the same MemberTypeReadOnlyDto as the current one we're processing - if (Current != null && Current.UniqueId == a.UniqueId) - { - //This property may already be added so we need to check for that - if (p.Id.HasValue && Current.PropertyTypes.Any(x => x.Id == p.Id.Value) == false) - { - // Add this PropertyTypeReadOnlyDto to the current MemberTypeReadOnlyDto's collection - Current.PropertyTypes.Add(p); - } - - if (g.Id.HasValue && Current.PropertyTypeGroups != null && Current.PropertyTypeGroups.Any(x => x.Id == g.Id.Value) == false) - { - Current.PropertyTypeGroups.Add(g); - } - - // Return null to indicate we're not done with this MemberTypeReadOnlyDto yet - return null; - } - - // This is a different MemberTypeReadOnlyDto to the current one, or this is the - // first time through and we don't have a Tab yet - - // Save the current MemberTypeReadOnlyDto - var prev = Current; - - // Setup the new current MemberTypeReadOnlyDto - Current = a; - Current.PropertyTypes = new List(); - //this can be null since we are doing a left join - if (p.Id.HasValue) - { - Current.PropertyTypes.Add(p); - } - - Current.PropertyTypeGroups = new List(); - if (g.Id.HasValue) - { - Current.PropertyTypeGroups.Add(g); - } - - // Return the now populated previous MemberTypeReadOnlyDto (or null if first time through) - return prev; - } - } -} \ No newline at end of file diff --git a/src/Umbraco.Core/Persistence/Relators/UserSectionRelator.cs b/src/Umbraco.Core/Persistence/Relators/UserSectionRelator.cs deleted file mode 100644 index 923348e729..0000000000 --- a/src/Umbraco.Core/Persistence/Relators/UserSectionRelator.cs +++ /dev/null @@ -1,50 +0,0 @@ -using System.Collections.Generic; -using Umbraco.Core.Models.Rdbms; - -namespace Umbraco.Core.Persistence.Relators -{ - internal class UserSectionRelator - { - internal UserDto Current; - - internal UserDto Map(UserDto a, User2AppDto p) - { - // Terminating call. Since we can return null from this function - // we need to be ready for PetaPoco to callback later with null - // parameters - if (a == null) - return Current; - - // Is this the same DictionaryItem as the current one we're processing - if (Current != null && Current.Id == a.Id) - { - if (p.AppAlias.IsNullOrWhiteSpace() == false) - { - // Yes, just add this User2AppDto to the current item's collection - Current.User2AppDtos.Add(p); - } - - // Return null to indicate we're not done with this User yet - return null; - } - - // This is a different User to the current one, or this is the - // first time through and we don't have one yet - - // Save the current User - var prev = Current; - - // Setup the new current User - Current = a; - Current.User2AppDtos = new List(); - //this can be null since we are doing a left join - if (p.AppAlias.IsNullOrWhiteSpace() == false) - { - Current.User2AppDtos.Add(p); - } - - // Return the now populated previous User (or null if first time through) - return prev; - } - } -} \ No newline at end of file diff --git a/src/Umbraco.Core/Persistence/Repositories/AuditRepository.cs b/src/Umbraco.Core/Persistence/Repositories/AuditRepository.cs index 710dbf1d30..4d3fc22a06 100644 --- a/src/Umbraco.Core/Persistence/Repositories/AuditRepository.cs +++ b/src/Umbraco.Core/Persistence/Repositories/AuditRepository.cs @@ -1,6 +1,7 @@ using System; using System.Collections.Generic; using System.Linq; +using NPoco; using Umbraco.Core.Logging; using Umbraco.Core.Models; using Umbraco.Core.Models.Rdbms; @@ -11,7 +12,7 @@ using Umbraco.Core.Persistence.UnitOfWork; namespace Umbraco.Core.Persistence.Repositories { - internal class AuditRepository : PetaPocoRepositoryBase, IAuditRepository + internal class AuditRepository : NPocoRepositoryBase, IAuditRepository { public AuditRepository(IDatabaseUnitOfWork work, CacheHelper cache, ILogger logger, ISqlSyntaxProvider sqlSyntax, IMappingResolver mappingResolver) : base(work, cache, logger, sqlSyntax, mappingResolver) @@ -63,11 +64,17 @@ namespace Umbraco.Core.Persistence.Repositories return dtos.Select(x => new AuditItem(x.NodeId, x.Comment, Enum.Parse(x.Header), x.UserId)).ToArray(); } - protected override Sql GetBaseQuery(bool isCount) + protected override Sql GetBaseQuery(bool isCount) { - var sql = new Sql(); - sql.Select(isCount ? "COUNT(*)" : "*") - .From(SqlSyntax); + var sql = Sql(); + + sql = isCount + ? sql.SelectCount() + : sql.Select(); + + sql + .From(); + return sql; } diff --git a/src/Umbraco.Core/Persistence/Repositories/ContentPreviewRepository.cs b/src/Umbraco.Core/Persistence/Repositories/ContentPreviewRepository.cs index e40460ee7d..d07ee15926 100644 --- a/src/Umbraco.Core/Persistence/Repositories/ContentPreviewRepository.cs +++ b/src/Umbraco.Core/Persistence/Repositories/ContentPreviewRepository.cs @@ -1,6 +1,7 @@ using System; using System.Collections.Generic; using System.Xml.Linq; +using NPoco; using Umbraco.Core.Logging; using Umbraco.Core.Models; using Umbraco.Core.Models.Rdbms; @@ -14,7 +15,7 @@ namespace Umbraco.Core.Persistence.Repositories /// /// Private class to handle preview insert/update based on standard principles and units of work with transactions /// - internal class ContentPreviewRepository : PetaPocoRepositoryBase> + internal class ContentPreviewRepository : NPocoRepositoryBase> where TContent : IContentBase { public ContentPreviewRepository(IDatabaseUnitOfWork work, CacheHelper cache, ILogger logger, ISqlSyntaxProvider sqlSyntax, IMappingResolver mappingResolver) @@ -38,7 +39,7 @@ namespace Umbraco.Core.Persistence.Repositories throw new NotImplementedException(); } - protected override Sql GetBaseQuery(bool isCount) + protected override Sql GetBaseQuery(bool isCount) { throw new NotImplementedException(); } diff --git a/src/Umbraco.Core/Persistence/Repositories/ContentRepository.cs b/src/Umbraco.Core/Persistence/Repositories/ContentRepository.cs index 56f0af8490..fb0121f8dd 100644 --- a/src/Umbraco.Core/Persistence/Repositories/ContentRepository.cs +++ b/src/Umbraco.Core/Persistence/Repositories/ContentRepository.cs @@ -7,6 +7,8 @@ using System.Linq.Expressions; using System.Net.Http.Headers; using System.Text; using System.Xml.Linq; +using NPoco; +using StackExchange.Profiling.Helpers.Dapper; using Umbraco.Core.Configuration; using Umbraco.Core.Dynamics; using Umbraco.Core.IO; @@ -63,10 +65,10 @@ namespace Umbraco.Core.Persistence.Repositories { var sql = GetBaseQuery(false) .Where(GetBaseWhereClause(), new { Id = id }) - .Where(SqlSyntax, x => x.Newest) - .OrderByDescending(SqlSyntax, x => x.VersionDate); + .Where(x => x.Newest) + .OrderByDescending(x => x.VersionDate); - var dto = Database.Fetch(sql).FirstOrDefault(); + var dto = Database.Fetch(sql).FirstOrDefault(); if (dto == null) return null; @@ -85,9 +87,9 @@ namespace Umbraco.Core.Persistence.Repositories } //we only want the newest ones with this method - sql.Where(SqlSyntax, x => x.Newest); + sql.Where(x => x.Newest); - return ProcessQuery(sql); + return MapQueryDtos(Database.Fetch(sql)); } protected override IEnumerable PerformGetByQuery(IQuery query) @@ -95,18 +97,18 @@ namespace Umbraco.Core.Persistence.Repositories var sqlClause = GetBaseQuery(false); var translator = new SqlTranslator(sqlClause, query); var sql = translator.Translate() - .Where(SqlSyntax, x => x.Newest) - .OrderByDescending(SqlSyntax, x => x.VersionDate) - .OrderBy(SqlSyntax, x => x.SortOrder); + .Where(x => x.Newest) + .OrderByDescending(x => x.VersionDate) + .OrderBy(x => x.SortOrder); - return ProcessQuery(sql); + return MapQueryDtos(Database.Fetch(sql)); } #endregion - #region Overrides of PetaPocoRepositoryBase + #region Overrides of NPocoRepositoryBase - protected override Sql GetBaseQuery(bool isCount) + protected override Sql GetBaseQuery(bool isCount) { var sqlx = string.Format("LEFT OUTER JOIN {0} {1} ON ({1}.{2}={0}.{2} AND {1}.{3}=1)", SqlSyntax.GetQuotedTableName("cmsDocument"), @@ -114,23 +116,32 @@ namespace Umbraco.Core.Persistence.Repositories SqlSyntax.GetQuotedColumnName("nodeId"), SqlSyntax.GetQuotedColumnName("published")); - var sql = new Sql(); - sql.Select(isCount ? "COUNT(*)" : "*") - .From(SqlSyntax) - .InnerJoin(SqlSyntax) - .On(SqlSyntax, left => left.VersionId, right => right.VersionId) - .InnerJoin(SqlSyntax) - .On(SqlSyntax, left => left.NodeId, right => right.NodeId) - .InnerJoin(SqlSyntax) - .On(SqlSyntax, left => left.NodeId, right => right.NodeId) + var sql = Sql(); - // cannot do this because PetaPoco does not know how to alias the table + sql = isCount + ? sql.SelectCount() + : sql.Select(r => + r.Select(rr => + rr.Select(rrr => + rrr.Select())) + .Select(tableAlias: "cmsDocument2")); + + sql + .From() + .InnerJoin() + .On(left => left.VersionId, right => right.VersionId) + .InnerJoin() + .On(left => left.NodeId, right => right.NodeId) + .InnerJoin() + .On(left => left.NodeId, right => right.NodeId) + + // cannot do this because NPoco does not know how to alias the table //.LeftOuterJoin() //.On(left => left.NodeId, right => right.NodeId) // so have to rely on writing our own SQL .Append(sqlx/*, new { @published = true }*/) - .Where(SqlSyntax, x => x.NodeObjectType == NodeObjectTypeId); + .Where(x => x.NodeObjectType == NodeObjectTypeId); return sql; } @@ -180,11 +191,11 @@ namespace Umbraco.Core.Persistence.Repositories //Remove all the data first, if anything fails after this it's no problem the transaction will be reverted if (contentTypeIds == null) { - var subQuery = new Sql() + var subQuery = Sql() .Select("DISTINCT cmsContentXml.nodeId") - .From(SqlSyntax) - .InnerJoin(SqlSyntax) - .On(SqlSyntax, left => left.NodeId, right => right.NodeId); + .From() + .InnerJoin() + .On(left => left.NodeId, right => right.NodeId); var deleteSql = SqlSyntax.GetDeleteSubquery("cmsContentXml", "nodeId", subQuery); Database.Execute(deleteSql); @@ -194,13 +205,13 @@ namespace Umbraco.Core.Persistence.Repositories foreach (var id in contentTypeIds) { var id1 = id; - var subQuery = new Sql() + var subQuery = Sql() .Select("cmsDocument.nodeId") - .From(SqlSyntax) - .InnerJoin(SqlSyntax) - .On(SqlSyntax, left => left.NodeId, right => right.NodeId) - .Where(SqlSyntax, dto => dto.Published) - .Where(SqlSyntax, dto => dto.ContentTypeId == id1); + .From() + .InnerJoin() + .On(left => left.NodeId, right => right.NodeId) + .Where(dto => dto.Published) + .Where( dto => dto.ContentTypeId == id1); var deleteSql = SqlSyntax.GetDeleteSubquery("cmsContentXml", "nodeId", subQuery); Database.Execute(deleteSql); @@ -228,7 +239,7 @@ namespace Umbraco.Core.Persistence.Repositories } } - private void RebuildXmlStructuresProcessQuery(Func serializer, IQuery query, Transaction tr, int pageSize) + private void RebuildXmlStructuresProcessQuery(Func serializer, IQuery query, ITransaction tr, int pageSize) { var pageIndex = 0; var total = long.MinValue; @@ -240,10 +251,9 @@ namespace Umbraco.Core.Persistence.Repositories // because that method is used to query 'latest' content items where in this case we don't necessarily // want latest content items because a pulished content item might not actually be the latest. // see: http://issues.umbraco.org/issue/U4-6322 & http://issues.umbraco.org/issue/U4-5982 - var descendants = GetPagedResultsByQuery(query, pageIndex, pageSize, out total, - new Tuple("cmsDocument", "nodeId"), - ProcessQuery, "Path", Direction.Ascending); - + var descendants = GetPagedResultsByQuery(query, pageIndex, pageSize, out total, + MapQueryDtos, "Path", Direction.Ascending, true); + var xmlItems = (from descendant in descendants let xml = serializer(descendant) select new ContentXmlDto { NodeId = descendant.Id, Xml = xml.ToDataString() }).ToArray(); @@ -261,9 +271,9 @@ namespace Umbraco.Core.Persistence.Repositories { var sql = GetBaseQuery(false); sql.Where("cmsContentVersion.VersionId = @VersionId", new { VersionId = versionId }); - sql.OrderByDescending(SqlSyntax, x => x.VersionDate); + sql.OrderByDescending(x => x.VersionDate); - var dto = Database.Fetch(sql).FirstOrDefault(); + var dto = Database.Fetch(sql).FirstOrDefault(); if (dto == null) return null; @@ -275,13 +285,13 @@ namespace Umbraco.Core.Persistence.Repositories public override void DeleteVersion(Guid versionId) { - var sql = new Sql() - .Select("*") - .From(SqlSyntax) - .InnerJoin(SqlSyntax).On(SqlSyntax, left => left.VersionId, right => right.VersionId) - .Where(SqlSyntax, x => x.VersionId == versionId) - .Where(SqlSyntax, x => x.Newest != true); - var dto = Database.Fetch(sql).FirstOrDefault(); + var sql = Sql() + .SelectAll() + .From() + .InnerJoin().On(left => left.VersionId, right => right.VersionId) + .Where(x => x.VersionId == versionId) + .Where(x => x.Newest != true); + var dto = Database.Fetch(sql).FirstOrDefault(); if (dto == null) return; @@ -295,14 +305,14 @@ namespace Umbraco.Core.Persistence.Repositories public override void DeleteVersions(int id, DateTime versionDate) { - var sql = new Sql() - .Select("*") - .From(SqlSyntax) - .InnerJoin(SqlSyntax).On(SqlSyntax, left => left.VersionId, right => right.VersionId) - .Where(SqlSyntax, x => x.NodeId == id) - .Where(SqlSyntax, x => x.VersionDate < versionDate) - .Where(SqlSyntax, x => x.Newest != true); - var list = Database.Fetch(sql); + var sql = Sql() + .SelectAll() + .From() + .InnerJoin().On(left => left.VersionId, right => right.VersionId) + .Where(x => x.NodeId == id) + .Where(x => x.VersionDate < versionDate) + .Where(x => x.Newest != true); + var list = Database.Fetch(sql); if (list.Any() == false) return; using (var transaction = Database.GetTransaction()) @@ -330,14 +340,14 @@ namespace Umbraco.Core.Persistence.Repositories protected override void PersistDeletedItem(IContent entity) { - //We need to clear out all access rules but we need to do this in a manual way since + //We need to clear out all access rules but we need to do this in a manual way since // nothing in that table is joined to a content id - var subQuery = new Sql() + var subQuery = Sql() .Select("umbracoAccessRule.accessId") - .From(SqlSyntax) - .InnerJoin(SqlSyntax) - .On(SqlSyntax, left => left.AccessId, right => right.Id) - .Where(SqlSyntax, dto => dto.NodeId == entity.Id); + .From() + .InnerJoin() + .On(left => left.AccessId, right => right.Id) + .Where(dto => dto.NodeId == entity.Id); Database.Execute(SqlSyntax.GetDeleteSubquery("umbracoAccessRule", "accessId", subQuery)); //now let the normal delete clauses take care of everything else @@ -377,7 +387,7 @@ namespace Umbraco.Core.Persistence.Repositories nodeDto.Path = parent.Path; nodeDto.Level = short.Parse(level.ToString(CultureInfo.InvariantCulture)); nodeDto.SortOrder = sortOrder; - var o = Database.IsNew(nodeDto) ? Convert.ToInt32(Database.Insert(nodeDto)) : Database.Update(nodeDto); + var o = Database.IsNew(nodeDto) ? Convert.ToInt32(Database.Insert(nodeDto)) : Database.Update(nodeDto); //Update with new correct path nodeDto.Path = string.Concat(parent.Path, ",", nodeDto.NodeId); @@ -390,7 +400,7 @@ namespace Umbraco.Core.Persistence.Repositories entity.Level = level; //Assign the same permissions to it as the parent node - // http://issues.umbraco.org/issue/U4-2161 + // http://issues.umbraco.org/issue/U4-2161 var permissionsRepo = new PermissionRepository(UnitOfWork, _cacheHelper, SqlSyntax); var parentPermissions = permissionsRepo.GetPermissionsForEntity(entity.ParentId).ToArray(); //if there are parent permissions then assign them, otherwise leave null and permissions will become the @@ -661,12 +671,12 @@ namespace Umbraco.Core.Persistence.Repositories var sqlClause = GetBaseQuery(false); var translator = new SqlTranslator(sqlClause, query); var sql = translator.Translate() - .Where(SqlSyntax, x => x.Published) - .OrderBy(SqlSyntax, x => x.Level) - .OrderBy(SqlSyntax, x => x.SortOrder); + .Where(x => x.Published) + .OrderBy(x => x.Level) + .OrderBy(x => x.SortOrder); //NOTE: This doesn't allow properties to be part of the query - var dtos = Database.Fetch(sql); + var dtos = Database.Fetch(sql); foreach (var dto in dtos) { @@ -689,8 +699,8 @@ namespace Umbraco.Core.Persistence.Repositories public int CountPublished() { - var sql = GetBaseQuery(true).Where(SqlSyntax, x => x.Trashed == false) - .Where(SqlSyntax, x => x.Published == true); + var sql = GetBaseQuery(true).Where(x => x.Trashed == false) + .Where(x => x.Published == true); return Database.ExecuteScalar(sql); } @@ -716,7 +726,7 @@ namespace Umbraco.Core.Persistence.Repositories /// /// /// - /// + /// public void AssignEntityPermission(IContent entity, char permission, IEnumerable userIds) { var repo = new PermissionRepository(UnitOfWork, _cacheHelper, SqlSyntax); @@ -767,31 +777,20 @@ namespace Umbraco.Core.Persistence.Repositories /// Total records query would return without paging /// Field to order by /// Direction to order by + /// Flag to indicate when ordering by system field /// Search text filter /// An Enumerable list of objects public IEnumerable GetPagedResultsByQuery(IQuery query, long pageIndex, int pageSize, out long totalRecords, - string orderBy, Direction orderDirection, string filter = "") + string orderBy, Direction orderDirection, bool orderBySystemField, string filter = "") { - - //NOTE: This uses the GetBaseQuery method but that does not take into account the required 'newest' field which is - // what we always require for a paged result, so we'll ensure it's included in the filter - - var args = new List(); - var sbWhere = new StringBuilder("AND (cmsDocument.newest = 1)"); - + var filterSql = Sql().Append("AND (cmsDocument.newest = 1)"); if (filter.IsNullOrWhiteSpace() == false) - { - sbWhere.Append(" AND (cmsDocument." + SqlSyntax.GetQuotedColumnName("text") + " LIKE @" + args.Count + ")"); - args.Add("%" + filter + "%"); - } - - Func> filterCallback = () => new Tuple(sbWhere.ToString(), args.ToArray()); - - return GetPagedResultsByQuery(query, pageIndex, pageSize, out totalRecords, - new Tuple("cmsDocument", "nodeId"), - ProcessQuery, orderBy, orderDirection, - filterCallback); + filterSql.Append("AND (cmsDocument." + SqlSyntax.GetQuotedColumnName("text") + " LIKE @0)", "%" + filter + "%"); + return GetPagedResultsByQuery(query, pageIndex, pageSize, out totalRecords, + MapQueryDtos, + orderBy, orderDirection, orderBySystemField, + filterSql); } /// @@ -801,7 +800,7 @@ namespace Umbraco.Core.Persistence.Repositories /// public XElement GetContentXml(int contentId) { - var sql = new Sql().Select("*").From(SqlSyntax).Where(SqlSyntax, d => d.NodeId == contentId); + var sql = Sql().SelectAll().From().Where(d => d.NodeId == contentId); var dto = Database.SingleOrDefault(sql); if (dto == null) return null; return XElement.Parse(dto.Xml); @@ -815,8 +814,8 @@ namespace Umbraco.Core.Persistence.Repositories /// public XElement GetContentPreviewXml(int contentId, Guid version) { - var sql = new Sql().Select("*").From(SqlSyntax) - .Where(SqlSyntax, d => d.NodeId == contentId && d.VersionId == version); + var sql = Sql().SelectAll().From() + .Where(d => d.NodeId == contentId && d.VersionId == version); var dto = Database.SingleOrDefault(sql); if (dto == null) return null; return XElement.Parse(dto.Xml); @@ -848,11 +847,8 @@ namespace Umbraco.Core.Persistence.Repositories return base.GetDatabaseFieldNameForOrderBy(orderBy); } - private IEnumerable ProcessQuery(Sql sql) + private IEnumerable MapQueryDtos(List dtos) { - //NOTE: This doesn't allow properties to be part of the query - var dtos = Database.Fetch(sql); - //nothing found if (dtos.Any() == false) return Enumerable.Empty(); @@ -884,7 +880,7 @@ namespace Umbraco.Core.Persistence.Repositories d.dto.ContentVersionDto.ContentDto.NodeDto.CreateDate, d.contentType)); - var propertyData = GetPropertyCollection(sql, docDefs); + var propertyData = GetPropertyCollection(docDefs.ToArray()); return dtosWithContentTypes.Select(d => CreateContentFromDto( d.dto, @@ -950,7 +946,7 @@ namespace Umbraco.Core.Persistence.Repositories var docDef = new DocumentDefinition(dto.NodeId, versionId, content.UpdateDate, content.CreateDate, contentType); - var properties = GetPropertyCollection(docSql, new[] { docDef }); + var properties = GetPropertyCollection(new[] { docDef }); content.Properties = properties[dto.NodeId]; @@ -965,10 +961,10 @@ namespace Umbraco.Core.Persistence.Repositories if (EnsureUniqueNaming == false) return nodeName; - var sql = new Sql(); - sql.Select("*") - .From(SqlSyntax) - .Where(SqlSyntax, x => x.NodeObjectType == NodeObjectTypeId && x.ParentId == parentId && x.Text.StartsWith(nodeName)); + var sql = Sql() + .SelectAll() + .From() + .Where(x => x.NodeObjectType == NodeObjectTypeId && x.ParentId == parentId && x.Text.StartsWith(nodeName)); int uniqueNumber = 1; var currentName = nodeName; diff --git a/src/Umbraco.Core/Persistence/Repositories/ContentTypeBaseRepository.cs b/src/Umbraco.Core/Persistence/Repositories/ContentTypeBaseRepository.cs index 5055f60ab9..5856bea59a 100644 --- a/src/Umbraco.Core/Persistence/Repositories/ContentTypeBaseRepository.cs +++ b/src/Umbraco.Core/Persistence/Repositories/ContentTypeBaseRepository.cs @@ -6,6 +6,7 @@ using System.Globalization; using System.Linq; using System.Text; using System.Threading.Tasks; +using NPoco; using Umbraco.Core.Events; using Umbraco.Core.Exceptions; using Umbraco.Core.Logging; @@ -16,7 +17,6 @@ using Umbraco.Core.Models.Rdbms; using Umbraco.Core.Persistence.Factories; using Umbraco.Core.Persistence.Mappers; using Umbraco.Core.Persistence.Querying; -using Umbraco.Core.Persistence.Relators; using Umbraco.Core.Persistence.SqlSyntax; using Umbraco.Core.Persistence.UnitOfWork; using Umbraco.Core.Services; @@ -28,7 +28,7 @@ namespace Umbraco.Core.Persistence.Repositories /// /// Exposes shared functionality /// - internal abstract class ContentTypeBaseRepository : PetaPocoRepositoryBase, IReadRepository + internal abstract class ContentTypeBaseRepository : NPocoRepositoryBase, IReadRepository where TEntity : class, IContentTypeComposition { protected ContentTypeBaseRepository(IDatabaseUnitOfWork work, CacheHelper cache, ILogger logger, ISqlSyntaxProvider sqlSyntax, IMappingResolver mappingResolver) @@ -92,24 +92,21 @@ namespace Umbraco.Core.Persistence.Repositories /// protected IEnumerable PerformGetByQuery(IQuery query) { - var sqlClause = new Sql(); - sqlClause.Select("*") - .From(SqlSyntax) - .RightJoin(SqlSyntax) - .On(SqlSyntax, left => left.Id, right => right.PropertyTypeGroupId) - .InnerJoin(SqlSyntax) - .On(SqlSyntax, left => left.DataTypeId, right => right.DataTypeId); + var sqlClause = Sql() + .SelectAll() + .From() + .RightJoin() + .On(left => left.Id, right => right.PropertyTypeGroupId) + .InnerJoin() + .On(left => left.DataTypeId, right => right.DataTypeId); var translator = new SqlTranslator(sqlClause, query); var sql = translator.Translate() - .OrderBy(SqlSyntax, x => x.PropertyTypeGroupId); + .OrderBy(x => x.PropertyTypeGroupId); - var dtos = Database.Fetch(new GroupPropertyTypeRelator().Map, sql); - - foreach (var dto in dtos.DistinctBy(x => x.ContentTypeNodeId)) - { - yield return dto.ContentTypeNodeId; - } + return Database + .FetchOneToMany(x => x.PropertyTypeDtos, sql) + .Select(x => x.ContentTypeNodeId).Distinct(); } protected virtual PropertyType CreatePropertyType(string propertyEditorAlias, DataTypeDatabaseType dbType, string propertyTypeAlias) @@ -145,7 +142,7 @@ AND umbracoNode.nodeObjectType = @objectType", nodeDto.Path = parent.Path; nodeDto.Level = short.Parse(level.ToString(CultureInfo.InvariantCulture)); nodeDto.SortOrder = sortOrder; - var o = Database.IsNew(nodeDto) ? Convert.ToInt32(Database.Insert(nodeDto)) : Database.Update(nodeDto); + var o = Database.IsNew(nodeDto) ? Convert.ToInt32(Database.Insert(nodeDto)) : Database.Update(nodeDto); //Update with new correct path nodeDto.Path = string.Concat(parent.Path, ",", nodeDto.NodeId); @@ -272,15 +269,15 @@ AND umbracoNode.id <> @id", compositionBase.RemovedContentTypeKeyTracker.Any()) { //Find Content based on the current ContentType - var sql = new Sql(); - sql.Select("*") - .From(SqlSyntax) - .InnerJoin(SqlSyntax) - .On(SqlSyntax, left => left.NodeId, right => right.NodeId) - .Where(SqlSyntax, x => x.NodeObjectType == new Guid(Constants.ObjectTypes.Document)) - .Where(SqlSyntax, x => x.ContentTypeId == entity.Id); + var sql = Sql() + .SelectAll() + .From() + .InnerJoin() + .On(left => left.NodeId, right => right.NodeId) + .Where(x => x.NodeObjectType == new Guid(Constants.ObjectTypes.Document)) + .Where(x => x.ContentTypeId == entity.Id); - var contentDtos = Database.Fetch(sql); + var contentDtos = Database.Fetch(sql); //Loop through all tracked keys, which corresponds to the ContentTypes that has been removed from the composition foreach (var key in compositionBase.RemovedContentTypeKeyTracker) { @@ -294,13 +291,13 @@ AND umbracoNode.id <> @id", { var nodeId = contentDto.NodeId; var propertyTypeId = propertyType.Id; - var propertySql = new Sql().Select("cmsPropertyData.id") - .From(SqlSyntax) - .InnerJoin(SqlSyntax) - .On(SqlSyntax, - left => left.PropertyTypeId, right => right.Id) - .Where(SqlSyntax, x => x.NodeId == nodeId) - .Where(SqlSyntax, x => x.Id == propertyTypeId); + var propertySql = Sql() + .Select("cmsPropertyData.id") + .From() + .InnerJoin() + .On(left => left.PropertyTypeId, right => right.Id) + .Where(x => x.NodeId == nodeId) + .Where(x => x.Id == propertyTypeId); //Finally delete the properties that match our criteria for removing a ContentType from the composition Database.Delete(new Sql("WHERE id IN (" + propertySql.SQL + ")", propertySql.Arguments)); @@ -424,30 +421,32 @@ AND umbracoNode.id <> @id", protected IEnumerable GetAllowedContentTypeIds(int id) { - var sql = new Sql(); - sql.Select("*") - .From(SqlSyntax) - .LeftJoin(SqlSyntax) - .On(SqlSyntax, left => left.AllowedId, right => right.NodeId) - .Where(SqlSyntax, x => x.Id == id); + var sql = Sql() + .SelectAll() + .From() + .LeftJoin() + .On(left => left.AllowedId, right => right.NodeId) + .Where(x => x.Id == id); - var allowedContentTypeDtos = Database.Fetch(sql); + var allowedContentTypeDtos = Database.Fetch(sql); return allowedContentTypeDtos.Select(x => new ContentTypeSort(new Lazy(() => x.AllowedId), x.SortOrder, x.ContentTypeDto.Alias)).ToList(); } protected PropertyGroupCollection GetPropertyGroupCollection(int id, DateTime createDate, DateTime updateDate) { - var sql = new Sql(); - sql.Select("*") - .From(SqlSyntax) - .LeftJoin(SqlSyntax) - .On(SqlSyntax, left => left.Id, right => right.PropertyTypeGroupId) - .LeftJoin(SqlSyntax) - .On(SqlSyntax, left => left.DataTypeId, right => right.DataTypeId) - .Where(SqlSyntax, x => x.ContentTypeNodeId == id) - .OrderBy(SqlSyntax, x => x.Id); + var sql = Sql() + .SelectAll() + .From() + .LeftJoin() + .On(left => left.Id, right => right.PropertyTypeGroupId) + .LeftJoin() + .On(left => left.DataTypeId, right => right.DataTypeId) + .Where(x => x.ContentTypeNodeId == id) + .OrderBy(x => x.Id); - var dtos = Database.Fetch(new GroupPropertyTypeRelator().Map, sql); + + var dtos = Database + .Fetch(sql); var propertyGroupFactory = new PropertyGroupFactory(id, createDate, updateDate, CreatePropertyType); var propertyGroups = propertyGroupFactory.BuildEntity(dtos); @@ -456,14 +455,14 @@ AND umbracoNode.id <> @id", protected PropertyTypeCollection GetPropertyTypeCollection(int id, DateTime createDate, DateTime updateDate) { - var sql = new Sql(); - sql.Select("*") - .From(SqlSyntax) - .InnerJoin(SqlSyntax) - .On(SqlSyntax, left => left.DataTypeId, right => right.DataTypeId) - .Where(SqlSyntax, x => x.ContentTypeId == id); + var sql = Sql() + .SelectAll() + .From() + .InnerJoin() + .On(left => left.DataTypeId, right => right.DataTypeId) + .Where(x => x.ContentTypeId == id); - var dtos = Database.Fetch(sql); + var dtos = Database.Fetch(sql); //TODO Move this to a PropertyTypeFactory var list = new List(); @@ -531,11 +530,11 @@ AND umbracoNode.id <> @id", //we cannot try to assign a data type of it's empty if (propertyType.PropertyEditorAlias.IsNullOrWhiteSpace() == false) { - var sql = new Sql() - .Select("*") - .From(SqlSyntax) + var sql = Sql() + .SelectAll() + .From() .Where("propertyEditorAlias = @propertyEditorAlias", new { propertyEditorAlias = propertyType.PropertyEditorAlias }) - .OrderBy(SqlSyntax, typeDto => typeDto.DataTypeId); + .OrderBy(typeDto => typeDto.DataTypeId); var datatype = Database.FirstOrDefault(sql); //we cannot assign a data type if one was not found if (datatype != null) @@ -849,7 +848,7 @@ AND umbracoNode.id <> @id", return mediaType; } - internal static IEnumerable MapContentTypes(Database db, ISqlSyntaxProvider sqlSyntax, + internal static IEnumerable MapContentTypes(Database db, ISqlSyntaxProvider sqlSyntax, out IDictionary> associatedTemplates, out IDictionary> parentContentTypeIds) { diff --git a/src/Umbraco.Core/Persistence/Repositories/ContentTypeRepository.cs b/src/Umbraco.Core/Persistence/Repositories/ContentTypeRepository.cs index 05dfebc786..02941434db 100644 --- a/src/Umbraco.Core/Persistence/Repositories/ContentTypeRepository.cs +++ b/src/Umbraco.Core/Persistence/Repositories/ContentTypeRepository.cs @@ -1,6 +1,7 @@ using System; using System.Collections.Generic; using System.Linq; +using NPoco; using Umbraco.Core.Cache; using Umbraco.Core.Events; using Umbraco.Core.Exceptions; @@ -12,7 +13,6 @@ using Umbraco.Core.Models.Rdbms; using Umbraco.Core.Persistence.Factories; using Umbraco.Core.Persistence.Mappers; using Umbraco.Core.Persistence.Querying; -using Umbraco.Core.Persistence.Relators; using Umbraco.Core.Persistence.SqlSyntax; using Umbraco.Core.Persistence.UnitOfWork; using Umbraco.Core.Services; @@ -39,7 +39,7 @@ namespace Umbraco.Core.Persistence.Repositories { //Use a FullDataSet cache policy - this will cache the entire GetAll result in a single collection return _cachePolicyFactory ?? (_cachePolicyFactory = new FullDataSetRepositoryCachePolicyFactory( - RuntimeCache, GetEntityId, () => PerformGetAll(), + RuntimeCache, GetEntityId, () => PerformGetAll(), //allow this cache to expire expires:true)); } @@ -67,9 +67,9 @@ namespace Umbraco.Core.Persistence.Repositories { var sqlClause = GetBaseQuery(false); var translator = new SqlTranslator(sqlClause, query); - var sql = translator.Translate(); + var sql = translator.Translate(); - var dtos = Database.Fetch(sql); + var dtos = Database.Fetch(sql); return //This returns a lookup from the GetAll cached looup @@ -79,7 +79,7 @@ namespace Umbraco.Core.Persistence.Repositories //order the result by name .OrderBy(x => x.Name); } - + /// /// Gets all entities of the specified query /// @@ -112,10 +112,11 @@ namespace Umbraco.Core.Persistence.Repositories /// public IEnumerable GetAllContentTypeAliases(params Guid[] objectTypes) { - var sql = new Sql().Select("cmsContentType.alias") - .From(SqlSyntax) - .InnerJoin(SqlSyntax) - .On(SqlSyntax, dto => dto.NodeId, dto => dto.NodeId); + var sql = Sql() + .Select("cmsContentType.alias") + .From() + .InnerJoin() + .On(dto => dto.NodeId, dto => dto.NodeId); if (objectTypes.Any()) { @@ -125,17 +126,23 @@ namespace Umbraco.Core.Persistence.Repositories return Database.Fetch(sql); } - protected override Sql GetBaseQuery(bool isCount) + protected override Sql GetBaseQuery(bool isCount) { - var sql = new Sql(); + var sql = Sql(); - sql.Select(isCount ? "COUNT(*)" : "*") - .From(SqlSyntax) - .InnerJoin(SqlSyntax) - .On(SqlSyntax, left => left.NodeId, right => right.NodeId) - .LeftJoin(SqlSyntax) - .On(SqlSyntax, left => left.ContentTypeNodeId, right => right.NodeId) - .Where(SqlSyntax, x => x.NodeObjectType == NodeObjectTypeId); + sql = isCount + ? sql.SelectCount() + : sql.Select(r => + r.Select(rr => + rr.Select())); + + sql + .From() + .InnerJoin() + .On(left => left.NodeId, right => right.NodeId) + .LeftJoin() + .On(left => left.ContentTypeNodeId, right => right.NodeId) + .Where(x => x.NodeObjectType == NodeObjectTypeId); return sql; } @@ -169,7 +176,7 @@ namespace Umbraco.Core.Persistence.Repositories { get { return new Guid(Constants.ObjectTypes.DocumentType); } } - + /// /// Deletes a content type /// @@ -188,18 +195,19 @@ namespace Umbraco.Core.Persistence.Repositories PersistDeletedItem((IEntity)child); } - //Before we call the base class methods to run all delete clauses, we need to first + //Before we call the base class methods to run all delete clauses, we need to first // delete all of the property data associated with this document type. Normally this will // be done in the ContentTypeService by deleting all associated content first, but in some cases // like when we switch a document type, there is property data left over that is linked // to the previous document type. So we need to ensure it's removed. - var sql = new Sql().Select("DISTINCT cmsPropertyData.propertytypeid") - .From(SqlSyntax) - .InnerJoin(SqlSyntax) - .On(SqlSyntax, dto => dto.PropertyTypeId, dto => dto.Id) - .InnerJoin(SqlSyntax) - .On(SqlSyntax, dto => dto.NodeId, dto => dto.ContentTypeId) - .Where(SqlSyntax, dto => dto.NodeId == entity.Id); + var sql = Sql() + .Select("DISTINCT cmsPropertyData.propertytypeid") + .From() + .InnerJoin() + .On(dto => dto.PropertyTypeId, dto => dto.Id) + .InnerJoin() + .On(dto => dto.NodeId, dto => dto.ContentTypeId) + .Where(dto => dto.NodeId == entity.Id); //Delete all cmsPropertyData where propertytypeid EXISTS in the subquery above Database.Execute(SqlSyntax.GetDeleteSubquery("cmsPropertyData", "propertytypeid", sql)); @@ -282,7 +290,7 @@ namespace Umbraco.Core.Persistence.Repositories entity.ResetDirtyProperties(); } - + protected override IContentType PerformGet(Guid id) { //use the underlying GetAll which will force cache all content types diff --git a/src/Umbraco.Core/Persistence/Repositories/ContentXmlRepository.cs b/src/Umbraco.Core/Persistence/Repositories/ContentXmlRepository.cs index 4b7c8a273a..c6258fe9a8 100644 --- a/src/Umbraco.Core/Persistence/Repositories/ContentXmlRepository.cs +++ b/src/Umbraco.Core/Persistence/Repositories/ContentXmlRepository.cs @@ -1,6 +1,7 @@ using System; using System.Collections.Generic; using System.Xml.Linq; +using NPoco; using Umbraco.Core.Logging; using Umbraco.Core.Models; using Umbraco.Core.Models.Rdbms; @@ -14,7 +15,7 @@ namespace Umbraco.Core.Persistence.Repositories /// /// Internal class to handle content/published xml insert/update based on standard principles and units of work with transactions /// - internal class ContentXmlRepository : PetaPocoRepositoryBase> + internal class ContentXmlRepository : NPocoRepositoryBase> where TContent : IContentBase { public ContentXmlRepository(IDatabaseUnitOfWork work, CacheHelper cache, ILogger logger, ISqlSyntaxProvider sqlSyntax, IMappingResolver mappingResolver) @@ -38,7 +39,7 @@ namespace Umbraco.Core.Persistence.Repositories throw new NotImplementedException(); } - protected override Sql GetBaseQuery(bool isCount) + protected override Sql GetBaseQuery(bool isCount) { throw new NotImplementedException(); } diff --git a/src/Umbraco.Core/Persistence/Repositories/DataTypeDefinitionRepository.cs b/src/Umbraco.Core/Persistence/Repositories/DataTypeDefinitionRepository.cs index 5bef1a2b5e..d6c9d05d54 100644 --- a/src/Umbraco.Core/Persistence/Repositories/DataTypeDefinitionRepository.cs +++ b/src/Umbraco.Core/Persistence/Repositories/DataTypeDefinitionRepository.cs @@ -5,6 +5,7 @@ using System.Globalization; using System.Linq; using System.Text.RegularExpressions; using System.Threading; +using NPoco; using Umbraco.Core.Cache; using Umbraco.Core.Events; using Umbraco.Core.Exceptions; @@ -25,7 +26,7 @@ namespace Umbraco.Core.Persistence.Repositories /// /// Represents a repository for doing CRUD operations for /// - internal class DataTypeDefinitionRepository : PetaPocoRepositoryBase, IDataTypeDefinitionRepository + internal class DataTypeDefinitionRepository : NPocoRepositoryBase, IDataTypeDefinitionRepository { private readonly IContentTypeRepository _contentTypeRepository; private readonly DataTypePreValueRepository _preValRepository; @@ -56,10 +57,10 @@ namespace Umbraco.Core.Persistence.Repositories } else { - dataTypeSql.Where(SqlSyntax, x => x.NodeObjectType == NodeObjectTypeId); + dataTypeSql.Where(x => x.NodeObjectType == NodeObjectTypeId); } - var dtos = Database.Fetch(dataTypeSql); + var dtos = Database.Fetch(dataTypeSql); return dtos.Select(factory.BuildEntity).ToArray(); } @@ -71,7 +72,7 @@ namespace Umbraco.Core.Persistence.Repositories var translator = new SqlTranslator(sqlClause, query); var sql = translator.Translate(); - var dtos = Database.Fetch(sql); + var dtos = Database.Fetch(sql); return dtos.Select(factory.BuildEntity).ToArray(); } @@ -111,16 +112,22 @@ namespace Umbraco.Core.Persistence.Repositories #endregion - #region Overrides of PetaPocoRepositoryBase + #region Overrides of NPocoRepositoryBase - protected override Sql GetBaseQuery(bool isCount) + protected override Sql GetBaseQuery(bool isCount) { - var sql = new Sql(); - sql.Select(isCount ? "COUNT(*)" : "*") - .From(SqlSyntax) - .InnerJoin(SqlSyntax) - .On(SqlSyntax, left => left.DataTypeId, right => right.NodeId) - .Where(SqlSyntax, x => x.NodeObjectType == NodeObjectTypeId); + var sql = Sql(); + + sql = isCount + ? sql.SelectCount() + : sql.Select(r => + r.Select()); + + sql + .From() + .InnerJoin() + .On(left => left.DataTypeId, right => right.NodeId) + .Where(x => x.NodeObjectType == NodeObjectTypeId); return sql; } @@ -175,7 +182,7 @@ WHERE umbracoNode." + SqlSyntax.GetQuotedColumnName("text") + "= @name", new { n nodeDto.Path = parent.Path; nodeDto.Level = short.Parse(level.ToString(CultureInfo.InvariantCulture)); nodeDto.SortOrder = sortOrder; - var o = Database.IsNew(nodeDto) ? Convert.ToInt32(Database.Insert(nodeDto)) : Database.Update(nodeDto); + var o = Database.IsNew(nodeDto) ? Convert.ToInt32(Database.Insert(nodeDto)) : Database.Update(nodeDto); //Update with new correct path nodeDto.Path = string.Concat(parent.Path, ",", nodeDto.NodeId); @@ -275,8 +282,8 @@ AND umbracoNode.id <> @id", #endregion - - + + public PreValueCollection GetPreValuesCollectionByDataTypeId(int dataTypeId) { var cached = RuntimeCache.GetCacheItemsByKeySearch(GetPrefixedCacheKey(dataTypeId)); @@ -387,10 +394,11 @@ AND umbracoNode.id <> @id", if (dataType.HasIdentity) { //first just get all pre-values for this data type so we can compare them to see if we need to insert or update or replace - var sql = new Sql().Select("*") - .From(SqlSyntax) - .Where(SqlSyntax, dto => dto.DataTypeNodeId == dataType.Id) - .OrderBy(SqlSyntax, dto => dto.SortOrder); + var sql = Sql() + .SelectAll() + .From() + .Where(dto => dto.DataTypeNodeId == dataType.Id) + .OrderBy(dto => dto.SortOrder); currentVals = Database.Fetch(sql).ToArray(); } @@ -477,12 +485,12 @@ AND umbracoNode.id <> @id", private string EnsureUniqueNodeName(string nodeName, int id = 0) { - - var sql = new Sql(); - sql.Select("*") - .From(SqlSyntax) - .Where(SqlSyntax, x => x.NodeObjectType == NodeObjectTypeId && x.Text.StartsWith(nodeName)); + + var sql = Sql() + .SelectAll() + .From() + .Where(x => x.NodeObjectType == NodeObjectTypeId && x.Text.StartsWith(nodeName)); int uniqueNumber = 1; var currentName = nodeName; @@ -520,7 +528,7 @@ AND umbracoNode.id <> @id", /// /// Private class to handle pre-value crud based on standard principles and units of work with transactions /// - private class DataTypePreValueRepository : PetaPocoRepositoryBase + private class DataTypePreValueRepository : NPocoRepositoryBase { public DataTypePreValueRepository(IDatabaseUnitOfWork work, CacheHelper cache, ILogger logger, ISqlSyntaxProvider sqlSyntax, IMappingResolver mappingResolver) : base(work, cache, logger, sqlSyntax, mappingResolver) @@ -543,7 +551,7 @@ AND umbracoNode.id <> @id", throw new NotImplementedException(); } - protected override Sql GetBaseQuery(bool isCount) + protected override Sql GetBaseQuery(bool isCount) { throw new NotImplementedException(); } @@ -579,7 +587,7 @@ AND umbracoNode.id <> @id", } //NOTE: We used to check that the Alias was unique for the given DataTypeNodeId prevalues list, BUT - // in reality there is no need to check the uniqueness of this alias because the only way that this code executes is + // in reality there is no need to check the uniqueness of this alias because the only way that this code executes is // based on an IDictionary dictionary being passed to this repository and a dictionary // must have unique aliases by definition, so there is no need for this additional check @@ -599,10 +607,10 @@ AND umbracoNode.id <> @id", { throw new InvalidOperationException("Cannot update a pre value for a data type that has no identity"); } - + //NOTE: We used to check that the Alias was unique for the given DataTypeNodeId prevalues list, BUT // this causes issues when sorting the pre-values (http://issues.umbraco.org/issue/U4-5670) but in reality - // there is no need to check the uniqueness of this alias because the only way that this code executes is + // there is no need to check the uniqueness of this alias because the only way that this code executes is // based on an IDictionary dictionary being passed to this repository and a dictionary // must have unique aliases by definition, so there is no need for this additional check @@ -617,7 +625,7 @@ AND umbracoNode.id <> @id", Database.Update(dto); } - + } internal static class PreValueConverter diff --git a/src/Umbraco.Core/Persistence/Repositories/DictionaryRepository.cs b/src/Umbraco.Core/Persistence/Repositories/DictionaryRepository.cs index 5d553801d3..c210a783fa 100644 --- a/src/Umbraco.Core/Persistence/Repositories/DictionaryRepository.cs +++ b/src/Umbraco.Core/Persistence/Repositories/DictionaryRepository.cs @@ -1,6 +1,7 @@ using System; using System.Collections.Generic; using System.Linq; +using NPoco; using Umbraco.Core.Cache; using Umbraco.Core.Logging; using Umbraco.Core.Models; @@ -10,7 +11,6 @@ using Umbraco.Core.Models.Rdbms; using Umbraco.Core.Persistence.Factories; using Umbraco.Core.Persistence.Mappers; using Umbraco.Core.Persistence.Querying; -using Umbraco.Core.Persistence.Relators; using Umbraco.Core.Persistence.SqlSyntax; using Umbraco.Core.Persistence.UnitOfWork; @@ -19,7 +19,7 @@ namespace Umbraco.Core.Persistence.Repositories /// /// Represents a repository for doing CRUD operations for /// - internal class DictionaryRepository : PetaPocoRepositoryBase, IDictionaryRepository + internal class DictionaryRepository : NPocoRepositoryBase, IDictionaryRepository { private readonly IMappingResolver _mappingResolver; @@ -51,9 +51,12 @@ namespace Umbraco.Core.Persistence.Repositories { var sql = GetBaseQuery(false) .Where(GetBaseWhereClause(), new { Id = id }) - .OrderBy(SqlSyntax, x => x.UniqueId); + .OrderBy(x => x.UniqueId); + + var dto = Database + .FetchOneToMany(x => x.LanguageTextDtos, sql) + .FirstOrDefault(); - var dto = Database.Fetch(new DictionaryLanguageTextRelator().Map, sql).FirstOrDefault(); if (dto == null) return null; @@ -74,8 +77,9 @@ namespace Umbraco.Core.Persistence.Repositories sql.Where("cmsDictionary.pk in (@ids)", new { ids = ids }); } - return Database.Fetch(new DictionaryLanguageTextRelator().Map, sql) - .Select(dto => ConvertFromDto(dto)); + return Database + .FetchOneToMany(x => x.LanguageTextDtos, sql) + .Select(dto => ConvertFromDto(dto)); } protected override IEnumerable PerformGetByQuery(IQuery query) @@ -83,30 +87,31 @@ namespace Umbraco.Core.Persistence.Repositories var sqlClause = GetBaseQuery(false); var translator = new SqlTranslator(sqlClause, query); var sql = translator.Translate(); - sql.OrderBy(SqlSyntax, x => x.UniqueId); + sql.OrderBy(x => x.UniqueId); - return Database.Fetch(new DictionaryLanguageTextRelator().Map, sql) + return Database + .FetchOneToMany(x => x.LanguageTextDtos, sql) .Select(x => ConvertFromDto(x)); } #endregion - #region Overrides of PetaPocoRepositoryBase + #region Overrides of NPocoRepositoryBase - protected override Sql GetBaseQuery(bool isCount) + protected override Sql GetBaseQuery(bool isCount) { - var sql = new Sql(); + var sql = Sql(); if (isCount) { - sql.Select("COUNT(*)") - .From(SqlSyntax); + sql.SelectCount() + .From(); } else { - sql.Select("*") - .From(SqlSyntax) - .LeftJoin(SqlSyntax) - .On(SqlSyntax, left => left.UniqueId, right => right.UniqueId); + sql.SelectAll() + .From() + .LeftJoin() + .On(left => left.UniqueId, right => right.UniqueId); } return sql; } @@ -226,7 +231,7 @@ namespace Umbraco.Core.Persistence.Repositories var entity = factory.BuildEntity(dto); var list = new List(); - foreach (var textDto in dto.LanguageTextDtos) + foreach (var textDto in dto.LanguageTextDtos.EmptyNull()) { if (textDto.LanguageId <= 0) continue; @@ -273,15 +278,16 @@ namespace Umbraco.Core.Persistence.Repositories .Select(@group => { var sqlClause = GetBaseQuery(false) - .Where(SqlSyntax, x => x.Parent != null) + .Where(x => x.Parent != null) .Where(string.Format("{0} IN (@parentIds)", SqlSyntax.GetQuotedColumnName("parent")), new { parentIds = @group }); var translator = new SqlTranslator(sqlClause, Query); var sql = translator.Translate(); - sql.OrderBy(SqlSyntax, x => x.UniqueId); + sql.OrderBy(x => x.UniqueId); - return Database.Fetch(new DictionaryLanguageTextRelator().Map, sql) - .Select(x => ConvertFromDto(x)); + return Database + .FetchOneToMany(x=> x.LanguageTextDtos, sql) + .Select(ConvertFromDto); }); }; @@ -305,10 +311,11 @@ namespace Umbraco.Core.Persistence.Repositories protected override IEnumerable PerformFetch(Sql sql) { - return Database.Fetch(new DictionaryLanguageTextRelator().Map, sql); + return Database + .FetchOneToMany(x => x.LanguageTextDtos, sql); } - protected override Sql GetBaseQuery(bool isCount) + protected override Sql GetBaseQuery(bool isCount) { return _dictionaryRepository.GetBaseQuery(isCount); } @@ -362,10 +369,11 @@ namespace Umbraco.Core.Persistence.Repositories protected override IEnumerable PerformFetch(Sql sql) { - return Database.Fetch(new DictionaryLanguageTextRelator().Map, sql); + return Database + .FetchOneToMany(x => x.LanguageTextDtos, sql); } - protected override Sql GetBaseQuery(bool isCount) + protected override Sql GetBaseQuery(bool isCount) { return _dictionaryRepository.GetBaseQuery(isCount); } diff --git a/src/Umbraco.Core/Persistence/Repositories/DomainRepository.cs b/src/Umbraco.Core/Persistence/Repositories/DomainRepository.cs index c24c0cd3fa..29de099ab9 100644 --- a/src/Umbraco.Core/Persistence/Repositories/DomainRepository.cs +++ b/src/Umbraco.Core/Persistence/Repositories/DomainRepository.cs @@ -2,6 +2,7 @@ using System; using System.Collections.Generic; using System.Data; using System.Linq; +using NPoco; using Umbraco.Core.Cache; using Umbraco.Core.Logging; using Umbraco.Core.Models; @@ -17,7 +18,7 @@ namespace Umbraco.Core.Persistence.Repositories { //TODO: We need to get a readonly ISO code for the domain assigned - internal class DomainRepository : PetaPocoRepositoryBase, IDomainRepository + internal class DomainRepository : NPocoRepositoryBase, IDomainRepository { public DomainRepository(IDatabaseUnitOfWork work, CacheHelper cache, ILogger logger, ISqlSyntaxProvider sqlSyntax, IMappingResolver mappingResolver) : base(work, cache, logger, sqlSyntax, mappingResolver) @@ -57,19 +58,19 @@ namespace Umbraco.Core.Persistence.Repositories throw new NotSupportedException("This repository does not support this method"); } - protected override Sql GetBaseQuery(bool isCount) + protected override Sql GetBaseQuery(bool isCount) { - var sql = new Sql(); + var sql = Sql(); if (isCount) { - sql.Select("COUNT(*)").From(SqlSyntax); + sql.SelectCount().From(); } else { sql.Select("umbracoDomains.*, umbracoLanguage.languageISOCode") - .From(SqlSyntax) - .LeftJoin(SqlSyntax) - .On(SqlSyntax, dto => dto.DefaultLanguage, dto => dto.Id); + .From() + .LeftJoin() + .On(dto => dto.DefaultLanguage, dto => dto.Id); } return sql; diff --git a/src/Umbraco.Core/Persistence/Repositories/EntityContainerRepository.cs b/src/Umbraco.Core/Persistence/Repositories/EntityContainerRepository.cs index 3e4c2f7ef6..353caedc00 100644 --- a/src/Umbraco.Core/Persistence/Repositories/EntityContainerRepository.cs +++ b/src/Umbraco.Core/Persistence/Repositories/EntityContainerRepository.cs @@ -1,6 +1,7 @@ using System; using System.Collections.Generic; using System.Linq; +using NPoco; using Umbraco.Core.Cache; using Umbraco.Core.Logging; using Umbraco.Core.Models; @@ -17,7 +18,7 @@ namespace Umbraco.Core.Persistence.Repositories /// /// An internal repository for managing entity containers such as doc type, media type, data type containers. /// - internal class EntityContainerRepository : PetaPocoRepositoryBase + internal class EntityContainerRepository : NPocoRepositoryBase { private readonly Guid _containerObjectType; @@ -70,7 +71,7 @@ namespace Umbraco.Core.Persistence.Repositories .Where("nodeObjectType=@umbracoObjectTypeId", new { umbracoObjectTypeId = NodeObjectTypeId }) .Where(string.Format("{0} IN (@ids)", SqlSyntax.GetQuotedColumnName("id")), new { ids = @group }); - sql.OrderBy(SqlSyntax, x => x.Level); + sql.OrderBy(x => x.Level); return Database.Fetch(sql).Select(CreateEntity); }); @@ -101,17 +102,14 @@ namespace Umbraco.Core.Persistence.Repositories return entity; } - protected override Sql GetBaseQuery(bool isCount) + protected override Sql GetBaseQuery(bool isCount) { - var sql = new Sql(); + var sql = Sql(); if (isCount) - { - sql.Select("COUNT(*)").From(SqlSyntax); - } + sql.SelectCount(); else - { - sql.Select("*").From(SqlSyntax); - } + sql.SelectAll(); + sql.From(); return sql; } @@ -134,15 +132,15 @@ namespace Umbraco.Core.Persistence.Repositories { EnsureContainerType(entity); - var nodeDto = Database.FirstOrDefault(new Sql().Select("*") - .From(SqlSyntax) - .Where(SqlSyntax, dto => dto.NodeId == entity.Id && dto.NodeObjectType == entity.ContainerObjectType)); + var nodeDto = Database.FirstOrDefault(Sql().SelectAll() + .From() + .Where(dto => dto.NodeId == entity.Id && dto.NodeObjectType == entity.ContainerObjectType)); if (nodeDto == null) return; // move children to the parent so they are not orphans - var childDtos = Database.Fetch(new Sql().Select("*") - .From(SqlSyntax) + var childDtos = Database.Fetch(Sql().SelectAll() + .From() .Where("parentID=@parentID AND (nodeObjectType=@containedObjectType OR nodeObjectType=@containerObjectType)", new { @@ -169,9 +167,9 @@ namespace Umbraco.Core.Persistence.Repositories Mandate.ParameterNotNullOrEmpty(entity.Name, "entity.Name"); // guard against duplicates - var nodeDto = Database.FirstOrDefault(new Sql().Select("*") - .From(SqlSyntax) - .Where(SqlSyntax, dto => dto.ParentId == entity.ParentId && dto.Text == entity.Name && dto.NodeObjectType == entity.ContainerObjectType)); + var nodeDto = Database.FirstOrDefault(Sql().SelectAll() + .From() + .Where(dto => dto.ParentId == entity.ParentId && dto.Text == entity.Name && dto.NodeObjectType == entity.ContainerObjectType)); if (nodeDto != null) throw new InvalidOperationException("A container with the same name already exists."); @@ -180,9 +178,9 @@ namespace Umbraco.Core.Persistence.Repositories var path = "-1"; if (entity.ParentId > -1) { - var parentDto = Database.FirstOrDefault(new Sql().Select("*") - .From(SqlSyntax) - .Where(SqlSyntax, dto => dto.NodeId == entity.ParentId && dto.NodeObjectType == entity.ContainerObjectType)); + var parentDto = Database.FirstOrDefault(Sql().SelectAll() + .From() + .Where(dto => dto.NodeId == entity.ParentId && dto.NodeObjectType == entity.ContainerObjectType)); if (parentDto == null) throw new NullReferenceException("Could not find parent container with id " + entity.ParentId); @@ -209,7 +207,7 @@ namespace Umbraco.Core.Persistence.Repositories // insert, get the id, update the path with the id var id = Convert.ToInt32(Database.Insert(nodeDto)); nodeDto.Path = nodeDto.Path + "," + nodeDto.NodeId; - Database.Save(nodeDto); + Database.Save(nodeDto); // refresh the entity entity.Id = id; @@ -230,16 +228,16 @@ namespace Umbraco.Core.Persistence.Repositories Mandate.ParameterNotNullOrEmpty(entity.Name, "entity.Name"); // find container to update - var nodeDto = Database.FirstOrDefault(new Sql().Select("*") - .From(SqlSyntax) - .Where(SqlSyntax, dto => dto.NodeId == entity.Id && dto.NodeObjectType == entity.ContainerObjectType)); + var nodeDto = Database.FirstOrDefault(Sql().SelectAll() + .From() + .Where(dto => dto.NodeId == entity.Id && dto.NodeObjectType == entity.ContainerObjectType)); if (nodeDto == null) throw new InvalidOperationException("Could not find container with id " + entity.Id); // guard against duplicates - var dupNodeDto = Database.FirstOrDefault(new Sql().Select("*") - .From(SqlSyntax) - .Where(SqlSyntax, dto => dto.ParentId == entity.ParentId && dto.Text == entity.Name && dto.NodeObjectType == entity.ContainerObjectType)); + var dupNodeDto = Database.FirstOrDefault(Sql().SelectAll() + .From() + .Where(dto => dto.ParentId == entity.ParentId && dto.Text == entity.Name && dto.NodeObjectType == entity.ContainerObjectType)); if (dupNodeDto != null && dupNodeDto.NodeId != nodeDto.NodeId) throw new InvalidOperationException("A container with the same name already exists."); @@ -251,9 +249,9 @@ namespace Umbraco.Core.Persistence.Repositories nodeDto.Path = "-1"; if (entity.ParentId > -1) { - var parent = Database.FirstOrDefault(new Sql().Select("*") - .From(SqlSyntax) - .Where(SqlSyntax, dto => dto.NodeId == entity.ParentId && dto.NodeObjectType == entity.ContainerObjectType)); + var parent = Database.FirstOrDefault( Sql().SelectAll() + .From() + .Where(dto => dto.NodeId == entity.ParentId && dto.NodeObjectType == entity.ContainerObjectType)); if (parent == null) throw new NullReferenceException("Could not find parent container with id " + entity.ParentId); diff --git a/src/Umbraco.Core/Persistence/Repositories/EntityRepository.cs b/src/Umbraco.Core/Persistence/Repositories/EntityRepository.cs index 190c34fa57..d79fc8aec4 100644 --- a/src/Umbraco.Core/Persistence/Repositories/EntityRepository.cs +++ b/src/Umbraco.Core/Persistence/Repositories/EntityRepository.cs @@ -1,12 +1,8 @@ using System; using System.Collections.Generic; -using System.Dynamic; -using System.Globalization; using System.Linq; -using System.Reflection; -using System.Text; +using NPoco; using Umbraco.Core.Models; -using Umbraco.Core; using Umbraco.Core.Models.EntityBase; using Umbraco.Core.Models.Rdbms; using Umbraco.Core.Persistence.Factories; @@ -14,7 +10,6 @@ using Umbraco.Core.Persistence.Mappers; using Umbraco.Core.Persistence.Querying; using Umbraco.Core.Persistence.SqlSyntax; using Umbraco.Core.Persistence.UnitOfWork; -using Umbraco.Core.Strings; namespace Umbraco.Core.Persistence.Repositories { @@ -26,13 +21,12 @@ namespace Umbraco.Core.Persistence.Repositories /// internal class EntityRepository : DisposableObject, IEntityRepository { - private readonly IDatabaseUnitOfWork _work; private readonly ISqlSyntaxProvider _sqlSyntax; private readonly QueryFactory _queryFactory; public EntityRepository(IDatabaseUnitOfWork work, ISqlSyntaxProvider sqlSyntax, IMappingResolver mappingResolver) { - _work = work; + UnitOfWork = work; _sqlSyntax = sqlSyntax; _queryFactory = new QueryFactory(_sqlSyntax, mappingResolver); } @@ -40,30 +34,23 @@ namespace Umbraco.Core.Persistence.Repositories /// /// Returns the Unit of Work added to the repository /// - protected internal IDatabaseUnitOfWork UnitOfWork - { - get { return _work; } - } + protected internal IDatabaseUnitOfWork UnitOfWork { get; } /// /// Internal for testing purposes /// - internal Guid UnitKey - { - get { return (Guid)_work.Key; } - } + internal Guid UnitKey => (Guid) UnitOfWork.Key; #region Query Methods - public Query Query - { - get { return _queryFactory.Create(); } - } + public Query Query => _queryFactory.Create(); + + public Sql Sql() { return NPoco.Sql.BuilderFor(new SqlContext(_sqlSyntax, UnitOfWork.Database));} public IUmbracoEntity GetByKey(Guid key) { var sql = GetBaseWhere(GetBase, false, false, key); - var nodeDto = _work.Database.FirstOrDefault(sql); + var nodeDto = UnitOfWork.Database.FirstOrDefault(sql); if (nodeDto == null) return null; @@ -75,39 +62,35 @@ namespace Umbraco.Core.Persistence.Repositories public IUmbracoEntity GetByKey(Guid key, Guid objectTypeId) { - bool isContent = objectTypeId == new Guid(Constants.ObjectTypes.Document); - bool isMedia = objectTypeId == new Guid(Constants.ObjectTypes.Media); + var isContent = objectTypeId == new Guid(Constants.ObjectTypes.Document); + var isMedia = objectTypeId == new Guid(Constants.ObjectTypes.Media); var sql = GetFullSqlForEntityType(key, isContent, isMedia, objectTypeId); - + if (isMedia) { //for now treat media differently //TODO: We should really use this methodology for Content/Members too!! since it includes properties and ALL of the dynamic db fields - var entities = _work.Database.Fetch( - new UmbracoEntityRelator().Map, sql); - - return entities.FirstOrDefault(); + return UnitOfWork.Database + .Fetch(sql) + .Transform(new UmbracoEntityRelator().MapAll) + .FirstOrDefault(); } - else - { - var nodeDto = _work.Database.FirstOrDefault(sql); - if (nodeDto == null) - return null; - var factory = new UmbracoEntityFactory(); - var entity = factory.BuildEntityFromDynamic(nodeDto); + var nodeDto = UnitOfWork.Database.FirstOrDefault(sql); + if (nodeDto == null) + return null; - return entity; - } - - + var factory = new UmbracoEntityFactory(); + var entity = factory.BuildEntityFromDynamic(nodeDto); + + return entity; } public virtual IUmbracoEntity Get(int id) { var sql = GetBaseWhere(GetBase, false, false, id); - var nodeDto = _work.Database.FirstOrDefault(sql); + var nodeDto = UnitOfWork.Database.FirstOrDefault(sql); if (nodeDto == null) return null; @@ -119,63 +102,49 @@ namespace Umbraco.Core.Persistence.Repositories public virtual IUmbracoEntity Get(int id, Guid objectTypeId) { - bool isContent = objectTypeId == new Guid(Constants.ObjectTypes.Document); - bool isMedia = objectTypeId == new Guid(Constants.ObjectTypes.Media); + var isContent = objectTypeId == new Guid(Constants.ObjectTypes.Document); + var isMedia = objectTypeId == new Guid(Constants.ObjectTypes.Media); var sql = GetFullSqlForEntityType(id, isContent, isMedia, objectTypeId); - + if (isMedia) { //for now treat media differently //TODO: We should really use this methodology for Content/Members too!! since it includes properties and ALL of the dynamic db fields - var entities = _work.Database.Fetch( - new UmbracoEntityRelator().Map, sql); - - return entities.FirstOrDefault(); - } - else - { - var nodeDto = _work.Database.FirstOrDefault(sql); - if (nodeDto == null) - return null; - - var factory = new UmbracoEntityFactory(); - var entity = factory.BuildEntityFromDynamic(nodeDto); - - return entity; + return UnitOfWork.Database + .Fetch(sql) + .Transform(new UmbracoEntityRelator().MapAll) + .FirstOrDefault(); } - + var nodeDto = UnitOfWork.Database.FirstOrDefault(sql); + if (nodeDto == null) + return null; + + var factory = new UmbracoEntityFactory(); + var entity = factory.BuildEntityFromDynamic(nodeDto); + + return entity; } public virtual IEnumerable GetAll(Guid objectTypeId, params int[] ids) { - if (ids.Any()) - { - return PerformGetAll(objectTypeId, sql1 => sql1.Where(" umbracoNode.id in (@ids)", new {ids = ids})); - } - else - { - return PerformGetAll(objectTypeId); - } + return ids.Any() + ? PerformGetAll(objectTypeId, sql1 => sql1.Where(" umbracoNode.id in (@ids)", new { /*ids =*/ ids })) + : PerformGetAll(objectTypeId); } public virtual IEnumerable GetAll(Guid objectTypeId, params Guid[] keys) { - if (keys.Any()) - { - return PerformGetAll(objectTypeId, sql1 => sql1.Where(" umbracoNode.uniqueID in (@keys)", new { keys = keys })); - } - else - { - return PerformGetAll(objectTypeId); - } + return keys.Any() + ? PerformGetAll(objectTypeId, sql1 => sql1.Where(" umbracoNode.uniqueID in (@keys)", new { /*keys =*/ keys })) + : PerformGetAll(objectTypeId); } private IEnumerable PerformGetAll(Guid objectTypeId, Action filter = null) { - bool isContent = objectTypeId == new Guid(Constants.ObjectTypes.Document); - bool isMedia = objectTypeId == new Guid(Constants.ObjectTypes.Media); + var isContent = objectTypeId == new Guid(Constants.ObjectTypes.Document); + var isMedia = objectTypeId == new Guid(Constants.ObjectTypes.Media); var sql = GetFullSqlForEntityType(isContent, isMedia, objectTypeId, filter); var factory = new UmbracoEntityFactory(); @@ -184,23 +153,14 @@ namespace Umbraco.Core.Persistence.Repositories { //for now treat media differently //TODO: We should really use this methodology for Content/Members too!! since it includes properties and ALL of the dynamic db fields - var entities = _work.Database.Fetch( - new UmbracoEntityRelator().Map, sql); - foreach (var entity in entities) - { - yield return entity; - } + return UnitOfWork.Database + .Fetch(sql) + .Transform(new UmbracoEntityRelator().MapAll); } - else - { - var dtos = _work.Database.Fetch(sql); - foreach (var entity in dtos.Select(dto => factory.BuildEntityFromDynamic(dto))) - { - yield return entity; - } - } - } + var dtos = UnitOfWork.Database.Fetch(sql); + return dtos.Select(dto => (UmbracoEntity) factory.BuildEntityFromDynamic(dto)); + } public virtual IEnumerable GetByQuery(IQuery query) { @@ -208,7 +168,7 @@ namespace Umbraco.Core.Persistence.Repositories var translator = new SqlTranslator(sqlClause, query); var sql = translator.Translate().Append(GetGroupBy(false, false)); - var dtos = _work.Database.Fetch(sql); + var dtos = UnitOfWork.Database.Fetch(sql); var factory = new UmbracoEntityFactory(); var list = dtos.Select(factory.BuildEntityFromDynamic).Cast().ToList(); @@ -218,12 +178,11 @@ namespace Umbraco.Core.Persistence.Repositories public virtual IEnumerable GetByQuery(IQuery query, Guid objectTypeId) { - - bool isContent = objectTypeId == new Guid(Constants.ObjectTypes.Document); - bool isMedia = objectTypeId == new Guid(Constants.ObjectTypes.Media); + var isContent = objectTypeId == new Guid(Constants.ObjectTypes.Document); + var isMedia = objectTypeId == new Guid(Constants.ObjectTypes.Media); var sqlClause = GetBaseWhere(GetBase, isContent, isMedia, null, objectTypeId); - + var translator = new SqlTranslator(sqlClause, query); var entitySql = translator.Translate(); @@ -242,82 +201,80 @@ namespace Umbraco.Core.Persistence.Repositories } }); - //treat media differently for now + //treat media differently for now //TODO: We should really use this methodology for Content/Members too!! since it includes properties and ALL of the dynamic db fields - var entities = _work.Database.Fetch( - new UmbracoEntityRelator().Map, mediaSql); - return entities; - } - else - { - //use dynamic so that we can get ALL properties from the SQL so we can chuck that data into our AdditionalData - var finalSql = entitySql.Append(GetGroupBy(isContent, false)); - var dtos = _work.Database.Fetch(finalSql); - return dtos.Select(factory.BuildEntityFromDynamic).Cast().ToList(); + return UnitOfWork.Database + .Fetch(mediaSql) + .Transform(new UmbracoEntityRelator().MapAll); } + + //use dynamic so that we can get ALL properties from the SQL so we can chuck that data into our AdditionalData + var finalSql = entitySql.Append(GetGroupBy(isContent, false)); + var dtos = UnitOfWork.Database.Fetch(finalSql); + return dtos.Select(factory.BuildEntityFromDynamic).Cast().ToList(); } public UmbracoObjectTypes GetObjectType(int id) { - var sql = new Sql().Select("nodeObjectType").From(_sqlSyntax).Where(_sqlSyntax, x => x.NodeId == id); - var nodeObjectTypeId = _work.Database.ExecuteScalar(sql); + var sql = Sql().Select("nodeObjectType").From().Where(x => x.NodeId == id); + var nodeObjectTypeId = UnitOfWork.Database.ExecuteScalar(sql); var objectTypeId = nodeObjectTypeId; return UmbracoObjectTypesExtensions.GetUmbracoObjectType(objectTypeId); } public UmbracoObjectTypes GetObjectType(Guid key) { - var sql = new Sql().Select("nodeObjectType").From(_sqlSyntax).Where(_sqlSyntax, x => x.UniqueId == key); - var nodeObjectTypeId = _work.Database.ExecuteScalar(sql); + var sql = Sql().Select("nodeObjectType").From().Where(x => x.UniqueId == key); + var nodeObjectTypeId = UnitOfWork.Database.ExecuteScalar(sql); var objectTypeId = nodeObjectTypeId; return UmbracoObjectTypesExtensions.GetUmbracoObjectType(objectTypeId); } #endregion - + #region Sql Statements - protected Sql GetFullSqlForEntityType(Guid key, bool isContent, bool isMedia, Guid objectTypeId) + protected Sql GetFullSqlForEntityType(Guid key, bool isContent, bool isMedia, Guid objectTypeId) { var entitySql = GetBaseWhere(GetBase, isContent, isMedia, objectTypeId, key); - if (isMedia == false) return entitySql.Append(GetGroupBy(isContent, false)); - - return GetFullSqlForMedia(entitySql.Append(GetGroupBy(isContent, true, false))); + return isMedia + ? GetFullSqlForMedia(entitySql.Append(GetGroupBy(isContent, true, false))) + : entitySql.Append(GetGroupBy(isContent, false)); } - protected Sql GetFullSqlForEntityType(int id, bool isContent, bool isMedia, Guid objectTypeId) + protected Sql GetFullSqlForEntityType(int id, bool isContent, bool isMedia, Guid objectTypeId) { var entitySql = GetBaseWhere(GetBase, isContent, isMedia, objectTypeId, id); - if (isMedia == false) return entitySql.Append(GetGroupBy(isContent, false)); - - return GetFullSqlForMedia(entitySql.Append(GetGroupBy(isContent, true, false))); + return isMedia + ? GetFullSqlForMedia(entitySql.Append(GetGroupBy(isContent, true, false))) + : entitySql.Append(GetGroupBy(isContent, false)); } - protected Sql GetFullSqlForEntityType(bool isContent, bool isMedia, Guid objectTypeId, Action filter) + protected Sql GetFullSqlForEntityType(bool isContent, bool isMedia, Guid objectTypeId, Action> filter) { var entitySql = GetBaseWhere(GetBase, isContent, isMedia, filter, objectTypeId); - if (isMedia == false) return entitySql.Append(GetGroupBy(isContent, false)); - - return GetFullSqlForMedia(entitySql.Append(GetGroupBy(isContent, true, false)), filter); + return isMedia + ? GetFullSqlForMedia(entitySql.Append(GetGroupBy(isContent, true, false)), filter) + : entitySql.Append(GetGroupBy(isContent, false)); } - private Sql GetFullSqlForMedia(Sql entitySql, Action filter = null) + private Sql GetFullSqlForMedia(Sql entitySql, Action> filter = null) { //this will add any dataNvarchar property to the output which can be added to the additional properties - var joinSql = new Sql() + var joinSql = Sql() .Select("contentNodeId, versionId, dataNvarchar, dataNtext, propertyEditorAlias, alias as propertyTypeAlias") - .From(_sqlSyntax) - .InnerJoin(_sqlSyntax) - .On(_sqlSyntax, dto => dto.NodeId, dto => dto.NodeId) - .InnerJoin(_sqlSyntax) - .On(_sqlSyntax, dto => dto.Id, dto => dto.PropertyTypeId) - .InnerJoin(_sqlSyntax) - .On(_sqlSyntax, dto => dto.DataTypeId, dto => dto.DataTypeId) + .From() + .InnerJoin() + .On(dto => dto.NodeId, dto => dto.NodeId) + .InnerJoin() + .On(dto => dto.Id, dto => dto.PropertyTypeId) + .InnerJoin() + .On(dto => dto.DataTypeId, dto => dto.DataTypeId) .Where("umbracoNode.nodeObjectType = @nodeObjectType", new {nodeObjectType = Constants.ObjectTypes.Media}); if (filter != null) @@ -325,21 +282,22 @@ namespace Umbraco.Core.Persistence.Repositories filter(joinSql); } - //We're going to create a query to query against the entity SQL + //We're going to create a query to query against the entity SQL // because we cannot group by nText columns and we have a COUNT in the entitySql we cannot simply left join // the entitySql query, we have to join the wrapped query to get the ntext in the result - - var wrappedSql = new Sql("SELECT * FROM (") + + var wrappedSql = Sql() + .Append("SELECT * FROM (") .Append(entitySql) - .Append(new Sql(") tmpTbl LEFT JOIN (")) + .Append(") tmpTbl LEFT JOIN (") .Append(joinSql) - .Append(new Sql(") as property ON id = property.contentNodeId")) + .Append(") as property ON id = property.contentNodeId") .OrderBy("sortOrder, id"); return wrappedSql; } - protected virtual Sql GetBase(bool isContent, bool isMedia, Action customFilter) + protected virtual Sql GetBase(bool isContent, bool isMedia, Action> customFilter) { var columns = new List { @@ -369,10 +327,10 @@ namespace Umbraco.Core.Persistence.Repositories //Creates an SQL query to return a single row for the entity - var entitySql = new Sql() + var entitySql = Sql() .Select(columns.ToArray()) .From("umbracoNode umbracoNode"); - + if (isContent || isMedia) { entitySql.InnerJoin("cmsContent content").On("content.nodeId = umbracoNode.id") @@ -395,14 +353,14 @@ namespace Umbraco.Core.Persistence.Repositories return entitySql; } - protected virtual Sql GetBaseWhere(Func, Sql> baseQuery, bool isContent, bool isMedia, Action filter, Guid nodeObjectType) + protected virtual Sql GetBaseWhere(Func>, Sql> baseQuery, bool isContent, bool isMedia, Action> filter, Guid nodeObjectType) { var sql = baseQuery(isContent, isMedia, filter) .Where("umbracoNode.nodeObjectType = @NodeObjectType", new { NodeObjectType = nodeObjectType }); return sql; } - protected virtual Sql GetBaseWhere(Func, Sql> baseQuery, bool isContent, bool isMedia, int id) + protected virtual Sql GetBaseWhere(Func>, Sql> baseQuery, bool isContent, bool isMedia, int id) { var sql = baseQuery(isContent, isMedia, null) .Where("umbracoNode.id = @Id", new { Id = id }) @@ -410,7 +368,7 @@ namespace Umbraco.Core.Persistence.Repositories return sql; } - protected virtual Sql GetBaseWhere(Func, Sql> baseQuery, bool isContent, bool isMedia, Guid key) + protected virtual Sql GetBaseWhere(Func>, Sql> baseQuery, bool isContent, bool isMedia, Guid key) { var sql = baseQuery(isContent, isMedia, null) .Where("umbracoNode.uniqueID = @UniqueID", new { UniqueID = key }) @@ -418,7 +376,7 @@ namespace Umbraco.Core.Persistence.Repositories return sql; } - protected virtual Sql GetBaseWhere(Func, Sql> baseQuery, bool isContent, bool isMedia, Guid nodeObjectType, int id) + protected virtual Sql GetBaseWhere(Func>, Sql> baseQuery, bool isContent, bool isMedia, Guid nodeObjectType, int id) { var sql = baseQuery(isContent, isMedia, null) .Where("umbracoNode.id = @Id AND umbracoNode.nodeObjectType = @NodeObjectType", @@ -426,7 +384,7 @@ namespace Umbraco.Core.Persistence.Repositories return sql; } - protected virtual Sql GetBaseWhere(Func, Sql> baseQuery, bool isContent, bool isMedia, Guid nodeObjectType, Guid key) + protected virtual Sql GetBaseWhere(Func>, Sql> baseQuery, bool isContent, bool isMedia, Guid nodeObjectType, Guid key) { var sql = baseQuery(isContent, isMedia, null) .Where("umbracoNode.uniqueID = @UniqueID AND umbracoNode.nodeObjectType = @NodeObjectType", @@ -434,7 +392,7 @@ namespace Umbraco.Core.Persistence.Repositories return sql; } - protected virtual Sql GetGroupBy(bool isContent, bool isMedia, bool includeSort = true) + protected virtual Sql GetGroupBy(bool isContent, bool isMedia, bool includeSort = true) { var columns = new List { @@ -460,9 +418,8 @@ namespace Umbraco.Core.Persistence.Repositories columns.Add("contenttype.thumbnail"); columns.Add("contenttype.isContainer"); } - - var sql = new Sql() - .GroupBy(columns.ToArray()); + + var sql = Sql().GroupBy(columns.ToArray()); if (includeSort) { @@ -471,7 +428,7 @@ namespace Umbraco.Core.Persistence.Repositories return sql; } - + #endregion /// @@ -512,7 +469,7 @@ namespace Umbraco.Core.Persistence.Repositories [ResultColumn] public List UmbracoPropertyDtos { get; set; } } - + [ExplicitColumns] internal class UmbracoPropertyDto { @@ -542,52 +499,73 @@ namespace Umbraco.Core.Persistence.Repositories internal UmbracoEntity Current; private readonly UmbracoEntityFactory _factory = new UmbracoEntityFactory(); - internal UmbracoEntity Map(dynamic a, UmbracoPropertyDto p) + public IEnumerable MapAll(IEnumerable input) + { + UmbracoEntity entity; + + foreach (var x in input) + { + entity = Map(x); + if (entity != null) yield return entity; + } + + entity = Map((dynamic) null); + if (entity != null) yield return entity; + } + + // must be called one last time with null in order to return the last one! + public UmbracoEntity Map(dynamic a) { // Terminating call. Since we can return null from this function - // we need to be ready for PetaPoco to callback later with null + // we need to be ready for NPoco to callback later with null // parameters if (a == null) return Current; + string pPropertyEditorAlias = a.propertyEditorAlias; + var pExists = pPropertyEditorAlias != null; + string pPropertyAlias = a.propertyTypeAlias; + string pNTextValue = a.dataNtext; + string pNVarcharValue = a.dataNvarchar; + // Is this the same UmbracoEntity as the current one we're processing if (Current != null && Current.Key == a.uniqueID) { - if (p != null && p.PropertyAlias.IsNullOrWhiteSpace() == false) + if (pExists && pPropertyAlias.IsNullOrWhiteSpace() == false) { // Add this UmbracoProperty to the current additional data - Current.AdditionalData[p.PropertyAlias] = new UmbracoEntity.EntityProperty + Current.AdditionalData[pPropertyAlias] = new UmbracoEntity.EntityProperty { - PropertyEditorAlias = p.PropertyEditorAlias, - Value = p.NTextValue.IsNullOrWhiteSpace() - ? p.NVarcharValue - : p.NTextValue.ConvertToJsonIfPossible() - }; + PropertyEditorAlias = pPropertyEditorAlias, + Value = pNTextValue.IsNullOrWhiteSpace() + ? pNVarcharValue + : pNTextValue.ConvertToJsonIfPossible() + }; } // Return null to indicate we're not done with this UmbracoEntity yet return null; } - // This is a different UmbracoEntity to the current one, or this is the + // This is a different UmbracoEntity to the current one, or this is the // first time through and we don't have a Tab yet // Save the current UmbracoEntityDto var prev = Current; // Setup the new current UmbracoEntity - + Current = _factory.BuildEntityFromDynamic(a); - if (p != null && p.PropertyAlias.IsNullOrWhiteSpace() == false) + if (pExists && pPropertyAlias.IsNullOrWhiteSpace() == false) { //add the property/create the prop list if null - Current.AdditionalData[p.PropertyAlias] = new UmbracoEntity.EntityProperty + Current.AdditionalData[pPropertyAlias] = new UmbracoEntity.EntityProperty { - PropertyEditorAlias = p.PropertyEditorAlias, - Value = p.NTextValue.IsNullOrWhiteSpace() - ? p.NVarcharValue - : p.NTextValue.ConvertToJsonIfPossible() + PropertyEditorAlias = pPropertyEditorAlias, + Value = pNTextValue.IsNullOrWhiteSpace() + ? pNVarcharValue + : pNTextValue.ConvertToJsonIfPossible() }; } diff --git a/src/Umbraco.Core/Persistence/Repositories/ExternalLoginRepository.cs b/src/Umbraco.Core/Persistence/Repositories/ExternalLoginRepository.cs index 249ecef23d..aa5340232d 100644 --- a/src/Umbraco.Core/Persistence/Repositories/ExternalLoginRepository.cs +++ b/src/Umbraco.Core/Persistence/Repositories/ExternalLoginRepository.cs @@ -2,6 +2,7 @@ using System; using System.Collections.Generic; using System.Linq; using Microsoft.AspNet.Identity; +using NPoco; using Umbraco.Core.Logging; using Umbraco.Core.Models.EntityBase; using Umbraco.Core.Models.Identity; @@ -14,7 +15,7 @@ using Umbraco.Core.Persistence.UnitOfWork; namespace Umbraco.Core.Persistence.Repositories { - internal class ExternalLoginRepository : PetaPocoRepositoryBase, IExternalLoginRepository + internal class ExternalLoginRepository : NPocoRepositoryBase, IExternalLoginRepository { public ExternalLoginRepository(IDatabaseUnitOfWork work, CacheHelper cache, ILogger logger, ISqlSyntaxProvider sqlSyntax, IMappingResolver mappingResolver) : base(work, cache, logger, sqlSyntax, mappingResolver) @@ -122,17 +123,14 @@ namespace Umbraco.Core.Persistence.Repositories } } - protected override Sql GetBaseQuery(bool isCount) + protected override Sql GetBaseQuery(bool isCount) { - var sql = new Sql(); + var sql = Sql(); if (isCount) - { - sql.Select("COUNT(*)").From(SqlSyntax); - } + sql.SelectCount(); else - { - sql.Select("*").From(SqlSyntax); - } + sql.SelectAll(); + sql.From(); return sql; } diff --git a/src/Umbraco.Core/Persistence/Repositories/Interfaces/IContentRepository.cs b/src/Umbraco.Core/Persistence/Repositories/Interfaces/IContentRepository.cs index 32961ccf7c..d0bc046055 100644 --- a/src/Umbraco.Core/Persistence/Repositories/Interfaces/IContentRepository.cs +++ b/src/Umbraco.Core/Persistence/Repositories/Interfaces/IContentRepository.cs @@ -84,10 +84,11 @@ namespace Umbraco.Core.Persistence.Repositories /// Total records query would return without paging /// Field to order by /// Direction to order by + /// Flag to indicate when ordering by system field /// Search text filter /// An Enumerable list of objects IEnumerable GetPagedResultsByQuery(IQuery query, long pageIndex, int pageSize, out long totalRecords, - string orderBy, Direction orderDirection, string filter = ""); + string orderBy, Direction orderDirection, bool orderBySystemField, string filter = ""); /// /// Returns the persisted content's preview XML structure diff --git a/src/Umbraco.Core/Persistence/Repositories/Interfaces/IMediaRepository.cs b/src/Umbraco.Core/Persistence/Repositories/Interfaces/IMediaRepository.cs index b712622e63..816cb12f44 100644 --- a/src/Umbraco.Core/Persistence/Repositories/Interfaces/IMediaRepository.cs +++ b/src/Umbraco.Core/Persistence/Repositories/Interfaces/IMediaRepository.cs @@ -34,9 +34,10 @@ namespace Umbraco.Core.Persistence.Repositories /// Total records query would return without paging /// Field to order by /// Direction to order by + /// Flag to indicate when ordering by system field /// Search text filter /// An Enumerable list of objects IEnumerable GetPagedResultsByQuery(IQuery query, long pageIndex, int pageSize, out long totalRecords, - string orderBy, Direction orderDirection, string filter = ""); + string orderBy, Direction orderDirection, bool orderBySystemField, string filter = ""); } } \ No newline at end of file diff --git a/src/Umbraco.Core/Persistence/Repositories/Interfaces/IMemberRepository.cs b/src/Umbraco.Core/Persistence/Repositories/Interfaces/IMemberRepository.cs index 9cb74d1806..a24116f0e2 100644 --- a/src/Umbraco.Core/Persistence/Repositories/Interfaces/IMemberRepository.cs +++ b/src/Umbraco.Core/Persistence/Repositories/Interfaces/IMemberRepository.cs @@ -44,16 +44,17 @@ namespace Umbraco.Core.Persistence.Repositories /// /// Gets paged member results /// - /// - /// - /// - /// - /// - /// - /// + /// The query. + /// Index of the page. + /// Size of the page. + /// The total records. + /// The order by column + /// The order direction. + /// Flag to indicate when ordering by system field + /// Search query /// IEnumerable GetPagedResultsByQuery(IQuery query, long pageIndex, int pageSize, out long totalRecords, - string orderBy, Direction orderDirection, string filter = ""); + string orderBy, Direction orderDirection, bool orderBySystemField, string filter = ""); //IEnumerable GetPagedResultsByQuery( // Sql sql, int pageIndex, int pageSize, out int totalRecords, diff --git a/src/Umbraco.Core/Persistence/Repositories/LanguageRepository.cs b/src/Umbraco.Core/Persistence/Repositories/LanguageRepository.cs index 8fbc122821..f0304ffa58 100644 --- a/src/Umbraco.Core/Persistence/Repositories/LanguageRepository.cs +++ b/src/Umbraco.Core/Persistence/Repositories/LanguageRepository.cs @@ -1,6 +1,7 @@ using System; using System.Collections.Generic; using System.Linq; +using NPoco; using Umbraco.Core.Cache; using Umbraco.Core.Logging; using Umbraco.Core.Models; @@ -18,11 +19,11 @@ namespace Umbraco.Core.Persistence.Repositories /// /// Represents a repository for doing CRUD operations for /// - internal class LanguageRepository : PetaPocoRepositoryBase, ILanguageRepository + internal class LanguageRepository : NPocoRepositoryBase, ILanguageRepository { public LanguageRepository(IDatabaseUnitOfWork work, CacheHelper cache, ILogger logger, ISqlSyntaxProvider sqlSyntax, IMappingResolver mappingResolver) : base(work, cache, logger, sqlSyntax, mappingResolver) - { + { } private FullDataSetRepositoryCachePolicyFactory _cachePolicyFactory; @@ -54,9 +55,9 @@ namespace Umbraco.Core.Persistence.Repositories //this needs to be sorted since that is the way legacy worked - default language is the first one!! //even though legacy didn't sort, it should be by id - sql.OrderBy(SqlSyntax, dto => dto.Id); + sql.OrderBy(dto => dto.Id); + - return Database.Fetch(sql).Select(ConvertFromDto); } @@ -70,13 +71,18 @@ namespace Umbraco.Core.Persistence.Repositories #endregion - #region Overrides of PetaPocoRepositoryBase + #region Overrides of NPocoRepositoryBase - protected override Sql GetBaseQuery(bool isCount) + protected override Sql GetBaseQuery(bool isCount) { - var sql = new Sql(); - sql.Select(isCount ? "COUNT(*)" : "*") - .From(SqlSyntax); + var sql = Sql(); + + sql = isCount + ? sql.SelectCount() + : sql.Select(); + + sql + .From(); return sql; } @@ -166,6 +172,6 @@ namespace Umbraco.Core.Persistence.Repositories return GetAll().FirstOrDefault(x => x.IsoCode.InvariantEquals(isoCode)); } - + } } \ No newline at end of file diff --git a/src/Umbraco.Core/Persistence/Repositories/MacroRepository.cs b/src/Umbraco.Core/Persistence/Repositories/MacroRepository.cs index 69274032a2..f3dbf6ec34 100644 --- a/src/Umbraco.Core/Persistence/Repositories/MacroRepository.cs +++ b/src/Umbraco.Core/Persistence/Repositories/MacroRepository.cs @@ -1,6 +1,7 @@ using System; using System.Collections.Generic; using System.Linq; +using NPoco; using Umbraco.Core.Logging; using Umbraco.Core.Models; using Umbraco.Core.Models.EntityBase; @@ -9,13 +10,12 @@ using Umbraco.Core.Models.Rdbms; using Umbraco.Core.Persistence.Factories; using Umbraco.Core.Persistence.Mappers; using Umbraco.Core.Persistence.Querying; -using Umbraco.Core.Persistence.Relators; using Umbraco.Core.Persistence.SqlSyntax; using Umbraco.Core.Persistence.UnitOfWork; namespace Umbraco.Core.Persistence.Repositories { - internal class MacroRepository : PetaPocoRepositoryBase, IMacroRepository + internal class MacroRepository : NPocoRepositoryBase, IMacroRepository { public MacroRepository(IDatabaseUnitOfWork work, CacheHelper cache, ILogger logger, ISqlSyntaxProvider sqlSyntax, IMappingResolver mappingResolver) @@ -28,7 +28,10 @@ namespace Umbraco.Core.Persistence.Repositories var sql = GetBaseQuery(false); sql.Where(GetBaseWhereClause(), new { Id = id }); - var macroDto = Database.Fetch(new MacroPropertyRelator().Map, sql).FirstOrDefault(); + var macroDto = Database + .FetchOneToMany(x => x.MacroPropertyDtos, sql) + .FirstOrDefault(); + if (macroDto == null) return null; @@ -51,8 +54,10 @@ namespace Umbraco.Core.Persistence.Repositories var sql = GetBaseQuery(false); - return ConvertFromDtos(Database.Fetch(new MacroPropertyRelator().Map, sql)) - .ToArray();// we don't want to re-iterate again! + return Database + .FetchOneToMany(x => x.MacroPropertyDtos, sql) + .Transform(ConvertFromDtos) + .ToArray(); // do it now and once } private IEnumerable PerformGetAllOnIds(params int[] ids) @@ -83,36 +88,23 @@ namespace Umbraco.Core.Persistence.Repositories var translator = new SqlTranslator(sqlClause, query); var sql = translator.Translate(); - var dtos = Database.Fetch(new MacroPropertyRelator().Map, sql); - - foreach (var dto in dtos) - { - yield return Get(dto.Id); - } + return Database + .FetchOneToMany(x => x.MacroPropertyDtos, sql) + .Select(x => Get(x.Id)); } - protected override Sql GetBaseQuery(bool isCount) + protected override Sql GetBaseQuery(bool isCount) { - var sql = new Sql(); - if (isCount) - { - sql.Select("COUNT(*)").From(SqlSyntax); - } - else - { - return GetBaseQuery(); - } - return sql; + return isCount ? Sql().SelectCount().From() : GetBaseQuery(); } - private Sql GetBaseQuery() + private Sql GetBaseQuery() { - var sql = new Sql(); - sql.Select("*") - .From(SqlSyntax) - .LeftJoin(SqlSyntax) - .On(SqlSyntax, left => left.Id, right => right.Macro); - return sql; + return Sql() + .SelectAll() + .From() + .LeftJoin() + .On(left => left.Id, right => right.Macro); } protected override string GetBaseWhereClause() @@ -125,7 +117,7 @@ namespace Umbraco.Core.Persistence.Repositories var list = new List { "DELETE FROM cmsMacroProperty WHERE macro = @Id", - "DELETE FROM cmsMacro WHERE id = @Id" + "DELETE FROM cmsMacro WHERE id = @Id" }; return list; } @@ -208,7 +200,7 @@ namespace Umbraco.Core.Persistence.Repositories } } - + } entity.ResetDirtyProperties(); @@ -230,7 +222,7 @@ namespace Umbraco.Core.Persistence.Repositories // { // return GetAll(new int[] {}); // } - + //} } } \ No newline at end of file diff --git a/src/Umbraco.Core/Persistence/Repositories/MediaRepository.cs b/src/Umbraco.Core/Persistence/Repositories/MediaRepository.cs index 2d1098164f..62257f08e2 100644 --- a/src/Umbraco.Core/Persistence/Repositories/MediaRepository.cs +++ b/src/Umbraco.Core/Persistence/Repositories/MediaRepository.cs @@ -5,6 +5,7 @@ using System.Linq; using System.Text; using System.Text.RegularExpressions; using System.Xml.Linq; +using NPoco; using Umbraco.Core.Configuration; using Umbraco.Core.Configuration.UmbracoSettings; using Umbraco.Core.Dynamics; @@ -54,9 +55,9 @@ namespace Umbraco.Core.Persistence.Repositories { var sql = GetBaseQuery(false); sql.Where(GetBaseWhereClause(), new { Id = id }); - sql.OrderByDescending(SqlSyntax, x => x.VersionDate); + sql.OrderByDescending(x => x.VersionDate); - var dto = Database.Fetch(sql).FirstOrDefault(); + var dto = Database.Fetch(sql).FirstOrDefault(); if (dto == null) return null; @@ -82,25 +83,33 @@ namespace Umbraco.Core.Persistence.Repositories var sqlClause = GetBaseQuery(false); var translator = new SqlTranslator(sqlClause, query); var sql = translator.Translate() - .OrderBy(SqlSyntax, x => x.SortOrder); + .OrderBy(x => x.SortOrder); return ProcessQuery(sql); } #endregion - #region Overrides of PetaPocoRepositoryBase + #region Overrides of NPocoRepositoryBase - protected override Sql GetBaseQuery(bool isCount) + protected override Sql GetBaseQuery(bool isCount) { - var sql = new Sql(); - sql.Select(isCount ? "COUNT(*)" : "*") - .From(SqlSyntax) - .InnerJoin(SqlSyntax) - .On(SqlSyntax, left => left.NodeId, right => right.NodeId) - .InnerJoin(SqlSyntax) - .On(SqlSyntax, left => left.NodeId, right => right.NodeId) - .Where(SqlSyntax, x => x.NodeObjectType == NodeObjectTypeId); + var sql = Sql(); + + sql = isCount + ? sql.SelectCount() + : sql.Select(r => + r.Select(rr => + rr.Select())); + + sql + .From() + .InnerJoin() + .On(left => left.NodeId, right => right.NodeId) + .InnerJoin() + .On(left => left.NodeId, right => right.NodeId) + .Where(x => x.NodeObjectType == NodeObjectTypeId); + return sql; } @@ -143,9 +152,9 @@ namespace Umbraco.Core.Persistence.Repositories { var sql = GetBaseQuery(false); sql.Where("cmsContentVersion.VersionId = @VersionId", new { VersionId = versionId }); - sql.OrderByDescending(SqlSyntax, x => x.VersionDate); + sql.OrderByDescending(x => x.VersionDate); - var dto = Database.Fetch(sql).FirstOrDefault(); + var dto = Database.Fetch(sql).FirstOrDefault(); if (dto == null) return null; @@ -155,7 +164,7 @@ namespace Umbraco.Core.Persistence.Repositories var factory = new MediaFactory(mediaType, NodeObjectTypeId, dto.NodeId); var media = factory.BuildEntity(dto); - var properties = GetPropertyCollection(sql, new[] { new DocumentDefinition(dto.NodeId, dto.VersionId, media.UpdateDate, media.CreateDate, mediaType) }); + var properties = GetPropertyCollection(new[] { new DocumentDefinition(dto.NodeId, dto.VersionId, media.UpdateDate, media.CreateDate, mediaType) }); media.Properties = properties[dto.NodeId]; @@ -175,12 +184,12 @@ namespace Umbraco.Core.Persistence.Repositories if (contentTypeIds == null) { var mediaObjectType = Guid.Parse(Constants.ObjectTypes.Media); - var subQuery = new Sql() + var subQuery = Sql() .Select("DISTINCT cmsContentXml.nodeId") - .From(SqlSyntax) - .InnerJoin(SqlSyntax) - .On(SqlSyntax, left => left.NodeId, right => right.NodeId) - .Where(SqlSyntax, dto => dto.NodeObjectType == mediaObjectType); + .From() + .InnerJoin() + .On(left => left.NodeId, right => right.NodeId) + .Where(dto => dto.NodeObjectType == mediaObjectType); var deleteSql = SqlSyntax.GetDeleteSubquery("cmsContentXml", "nodeId", subQuery); Database.Execute(deleteSql); @@ -191,15 +200,15 @@ namespace Umbraco.Core.Persistence.Repositories { var id1 = id; var mediaObjectType = Guid.Parse(Constants.ObjectTypes.Media); - var subQuery = new Sql() + var subQuery = Sql() .Select("DISTINCT cmsContentXml.nodeId") - .From(SqlSyntax) - .InnerJoin(SqlSyntax) - .On(SqlSyntax, left => left.NodeId, right => right.NodeId) - .InnerJoin(SqlSyntax) - .On(SqlSyntax, left => left.NodeId, right => right.NodeId) - .Where(SqlSyntax, dto => dto.NodeObjectType == mediaObjectType) - .Where(SqlSyntax, dto => dto.ContentTypeId == id1); + .From() + .InnerJoin() + .On(left => left.NodeId, right => right.NodeId) + .InnerJoin() + .On(left => left.NodeId, right => right.NodeId) + .Where(dto => dto.NodeObjectType == mediaObjectType) + .Where(dto => dto.ContentTypeId == id1); var deleteSql = SqlSyntax.GetDeleteSubquery("cmsContentXml", "nodeId", subQuery); Database.Execute(deleteSql); @@ -226,14 +235,14 @@ namespace Umbraco.Core.Persistence.Repositories } } - private void RebuildXmlStructuresProcessQuery(Func serializer, IQuery query, Transaction tr, int pageSize) + private void RebuildXmlStructuresProcessQuery(Func serializer, IQuery query, ITransaction tr, int pageSize) { var pageIndex = 0; var total = long.MinValue; var processed = 0; do { - var descendants = GetPagedResultsByQuery(query, pageIndex, pageSize, out total, "Path", Direction.Ascending); + var descendants = GetPagedResultsByQuery(query, pageIndex, pageSize, out total, "Path", Direction.Ascending, true); var xmlItems = (from descendant in descendants let xml = serializer(descendant) @@ -262,23 +271,23 @@ namespace Umbraco.Core.Persistence.Repositories umbracoFileValue = string.Concat(mediaPath.Substring(0, underscoreIndex), mediaPath.Substring(dotIndex)); } - Func createSql = url => new Sql().Select("*") - .From(SqlSyntax) - .InnerJoin(SqlSyntax) - .On(SqlSyntax, left => left.PropertyTypeId, right => right.Id) - .Where(SqlSyntax, x => x.Alias == "umbracoFile") - .Where(SqlSyntax, x => x.VarChar == url); + Func createSql = url => Sql().SelectAll() + .From() + .InnerJoin() + .On(left => left.PropertyTypeId, right => right.Id) + .Where(x => x.Alias == "umbracoFile") + .Where(x => x.VarChar == url); var sql = createSql(umbracoFileValue); - var propertyDataDto = Database.Fetch(sql).FirstOrDefault(); + var propertyDataDto = Database.Fetch(sql).FirstOrDefault(); - // If the stripped-down url returns null, we try again with the original url. + // If the stripped-down url returns null, we try again with the original url. // Previously, the function would fail on e.g. "my_x_image.jpg" if (propertyDataDto == null) { sql = createSql(mediaPath); - propertyDataDto = Database.Fetch(sql).FirstOrDefault(); + propertyDataDto = Database.Fetch(sql).FirstOrDefault(); } return propertyDataDto == null ? null : Get(propertyDataDto.NodeId); @@ -332,7 +341,7 @@ namespace Umbraco.Core.Persistence.Repositories nodeDto.Path = parent.Path; nodeDto.Level = short.Parse(level.ToString(CultureInfo.InvariantCulture)); nodeDto.SortOrder = sortOrder; - var o = Database.IsNew(nodeDto) ? Convert.ToInt32(Database.Insert(nodeDto)) : Database.Update(nodeDto); + var o = Database.IsNew(nodeDto) ? Convert.ToInt32(Database.Insert(nodeDto)) : Database.Update(nodeDto); //Update with new correct path nodeDto.Path = string.Concat(parent.Path, ",", nodeDto.NodeId); @@ -479,33 +488,30 @@ namespace Umbraco.Core.Persistence.Repositories /// Total records query would return without paging /// Field to order by /// Direction to order by + /// Flag to indicate when ordering by system field /// Search text filter /// An Enumerable list of objects public IEnumerable GetPagedResultsByQuery(IQuery query, long pageIndex, int pageSize, out long totalRecords, - string orderBy, Direction orderDirection, string filter = "") + string orderBy, Direction orderDirection, bool orderBySystemField, string filter = "") { - var args = new List(); - var sbWhere = new StringBuilder(); - Func> filterCallback = null; - if (filter.IsNullOrWhiteSpace() == false) - { - sbWhere.Append("AND (umbracoNode." + SqlSyntax.GetQuotedColumnName("text") + " LIKE @" + args.Count + ")"); - args.Add("%" + filter + "%"); - filterCallback = () => new Tuple(sbWhere.ToString().Trim(), args.ToArray()); - } - - return GetPagedResultsByQuery(query, pageIndex, pageSize, out totalRecords, - new Tuple("cmsContentVersion", "contentId"), - ProcessQuery, orderBy, orderDirection, - filterCallback); + var filterSql = filter.IsNullOrWhiteSpace() + ? null + : Sql().Append("AND (umbracoNode." + SqlSyntax.GetQuotedColumnName("text") + " LIKE @0)", "%" + filter + "%"); + return GetPagedResultsByQuery(query, pageIndex, pageSize, out totalRecords, + MapQueryDtos, orderBy, orderDirection, orderBySystemField, + filterSql); } private IEnumerable ProcessQuery(Sql sql) { //NOTE: This doesn't allow properties to be part of the query - var dtos = Database.Fetch(sql); - + var dtos = Database.Fetch(sql); + return MapQueryDtos(dtos); + } + + private IEnumerable MapQueryDtos(List dtos) + { var ids = dtos.Select(x => x.ContentDto.ContentTypeId).ToArray(); //content types @@ -527,7 +533,7 @@ namespace Umbraco.Core.Persistence.Repositories d.contentType)) .ToArray(); - var propertyData = GetPropertyCollection(sql, docDefs); + var propertyData = GetPropertyCollection(docDefs); return dtosWithContentTypes.Select(d => CreateMediaFromDto( d.dto, @@ -573,7 +579,7 @@ namespace Umbraco.Core.Persistence.Repositories var docDef = new DocumentDefinition(dto.NodeId, versionId, media.UpdateDate, media.CreateDate, contentType); - var properties = GetPropertyCollection(docSql, new[] { docDef }); + var properties = GetPropertyCollection(new[] { docDef }); media.Properties = properties[dto.NodeId]; @@ -588,10 +594,10 @@ namespace Umbraco.Core.Persistence.Repositories if (EnsureUniqueNaming == false) return nodeName; - var sql = new Sql(); - sql.Select("*") - .From(SqlSyntax) - .Where(SqlSyntax, x => x.NodeObjectType == NodeObjectTypeId && x.ParentId == parentId && x.Text.StartsWith(nodeName)); + var sql = Sql() + .SelectAll() + .From() + .Where(x => x.NodeObjectType == NodeObjectTypeId && x.ParentId == parentId && x.Text.StartsWith(nodeName)); int uniqueNumber = 1; var currentName = nodeName; diff --git a/src/Umbraco.Core/Persistence/Repositories/MediaTypeRepository.cs b/src/Umbraco.Core/Persistence/Repositories/MediaTypeRepository.cs index 4e1654c2ad..3d7eedd246 100644 --- a/src/Umbraco.Core/Persistence/Repositories/MediaTypeRepository.cs +++ b/src/Umbraco.Core/Persistence/Repositories/MediaTypeRepository.cs @@ -1,6 +1,7 @@ using System; using System.Collections.Generic; using System.Linq; +using NPoco; using Umbraco.Core.Cache; using Umbraco.Core.Events; using Umbraco.Core.Exceptions; @@ -66,7 +67,7 @@ namespace Umbraco.Core.Persistence.Repositories var translator = new SqlTranslator(sqlClause, query); var sql = translator.Translate(); - var dtos = Database.Fetch(sql); + var dtos = Database.Fetch(sql); return //This returns a lookup from the GetAll cached looup @@ -90,14 +91,21 @@ namespace Umbraco.Core.Persistence.Repositories : Enumerable.Empty(); } - protected override Sql GetBaseQuery(bool isCount) + protected override Sql GetBaseQuery(bool isCount) { - var sql = new Sql(); - sql.Select(isCount ? "COUNT(*)" : "*") - .From(SqlSyntax) - .InnerJoin(SqlSyntax) - .On(SqlSyntax, left => left.NodeId, right => right.NodeId) - .Where(SqlSyntax, x => x.NodeObjectType == NodeObjectTypeId); + var sql = Sql(); + + sql = isCount + ? sql.SelectCount() + : sql.Select(r => + r.Select()); + + sql + .From() + .InnerJoin() + .On( left => left.NodeId, right => right.NodeId) + .Where(x => x.NodeObjectType == NodeObjectTypeId); + return sql; } diff --git a/src/Umbraco.Core/Persistence/Repositories/MemberGroupRepository.cs b/src/Umbraco.Core/Persistence/Repositories/MemberGroupRepository.cs index 291454d9d3..1ff51447ec 100644 --- a/src/Umbraco.Core/Persistence/Repositories/MemberGroupRepository.cs +++ b/src/Umbraco.Core/Persistence/Repositories/MemberGroupRepository.cs @@ -1,6 +1,7 @@ using System; using System.Collections.Generic; using System.Linq; +using NPoco; using Umbraco.Core.Events; using Umbraco.Core.Logging; using Umbraco.Core.Models; @@ -19,7 +20,7 @@ namespace Umbraco.Core.Persistence.Repositories { - internal class MemberGroupRepository : PetaPocoRepositoryBase, IMemberGroupRepository + internal class MemberGroupRepository : NPocoRepositoryBase, IMemberGroupRepository { public MemberGroupRepository(IDatabaseUnitOfWork work, CacheHelper cache, ILogger logger, ISqlSyntaxProvider sqlSyntax, IMappingResolver mappingResolver) : base(work, cache, logger, sqlSyntax, mappingResolver) @@ -40,24 +41,15 @@ namespace Umbraco.Core.Persistence.Repositories protected override IEnumerable PerformGetAll(params int[] ids) { + var sql = Sql() + .SelectAll() + .From() + .Where(dto => dto.NodeObjectType == NodeObjectTypeId); + if (ids.Any()) - { - var sql = new Sql() - .Select("*") - .From(SqlSyntax) - .Where(SqlSyntax, dto => dto.NodeObjectType == NodeObjectTypeId) - .Where("umbracoNode.id in (@ids)", new { ids = ids }); - return Database.Fetch(sql) - .Select(x => _modelFactory.BuildEntity(x)); - } - else - { - var sql = new Sql() - .From(SqlSyntax) - .Where(SqlSyntax, dto => dto.NodeObjectType == NodeObjectTypeId); - return Database.Fetch(sql) - .Select(x => _modelFactory.BuildEntity(x)); - } + sql.Where("umbracoNode.id in (@ids)", new { /*ids =*/ ids }); + + return Database.Fetch(sql).Select(x => _modelFactory.BuildEntity(x)); } protected override IEnumerable PerformGetByQuery(IQuery query) @@ -66,16 +58,21 @@ namespace Umbraco.Core.Persistence.Repositories var translator = new SqlTranslator(sqlClause, query); var sql = translator.Translate(); - return Database.Fetch(sql) - .Select(x => _modelFactory.BuildEntity(x)); + return Database.Fetch(sql).Select(x => _modelFactory.BuildEntity(x)); } - protected override Sql GetBaseQuery(bool isCount) + protected override Sql GetBaseQuery(bool isCount) { - var sql = new Sql(); - sql.Select(isCount ? "COUNT(*)" : "*") - .From(SqlSyntax) - .Where(SqlSyntax, x => x.NodeObjectType == NodeObjectTypeId); + var sql = Sql(); + + sql = isCount + ? sql.SelectCount() + : sql.Select(); + + sql + .From() + .Where(x => x.NodeObjectType == NodeObjectTypeId); + return sql; } @@ -110,7 +107,7 @@ namespace Umbraco.Core.Persistence.Repositories var group = (MemberGroup)entity; group.AddingEntity(); var dto = _modelFactory.BuildDto(group); - var o = Database.IsNew(dto) ? Convert.ToInt32(Database.Insert(dto)) : Database.Update(dto); + var o = Database.IsNew(dto) ? Convert.ToInt32(Database.Insert(dto)) : Database.Update(dto); group.Id = dto.NodeId; //Set Id on entity to ensure an Id is set //Update with new correct path and id @@ -176,13 +173,13 @@ namespace Umbraco.Core.Persistence.Repositories public IEnumerable GetMemberGroupsForMember(int memberId) { - var sql = new Sql(); - sql.Select("umbracoNode.*") - .From(SqlSyntax) - .InnerJoin(SqlSyntax) - .On(SqlSyntax, dto => dto.NodeId, dto => dto.MemberGroup) - .Where(SqlSyntax, x => x.NodeObjectType == NodeObjectTypeId) - .Where(SqlSyntax, x => x.Member == memberId); + var sql = Sql() + .Select("umbracoNode.*") + .From() + .InnerJoin() + .On( dto => dto.NodeId, dto => dto.MemberGroup) + .Where(x => x.NodeObjectType == NodeObjectTypeId) + .Where(x => x.Member == memberId); return Database.Fetch(sql) .DistinctBy(dto => dto.NodeId) @@ -192,28 +189,28 @@ namespace Umbraco.Core.Persistence.Repositories public IEnumerable GetMemberGroupsForMember(string username) { //find the member by username - var memberSql = new Sql(); var memberObjectType = new Guid(Constants.ObjectTypes.Member); - - memberSql.Select("umbracoNode.id") - .From(SqlSyntax) - .InnerJoin(SqlSyntax) - .On(SqlSyntax, dto => dto.NodeId, dto => dto.NodeId) - .Where(SqlSyntax, x => x.NodeObjectType == memberObjectType) - .Where(SqlSyntax, x => x.LoginName == username); + + var memberSql = Sql() + .Select("umbracoNode.id") + .From() + .InnerJoin() + .On(dto => dto.NodeId, dto => dto.NodeId) + .Where( x => x.NodeObjectType == memberObjectType) + .Where(x => x.LoginName == username); var memberIdUsername = Database.Fetch(memberSql).FirstOrDefault(); if (memberIdUsername.HasValue == false) { return Enumerable.Empty(); } - var sql = new Sql(); - sql.Select("umbracoNode.*") - .From(SqlSyntax) - .InnerJoin(SqlSyntax) - .On(SqlSyntax, dto => dto.NodeId, dto => dto.MemberGroup) - .Where(SqlSyntax, x => x.NodeObjectType == NodeObjectTypeId) - .Where(SqlSyntax, x => x.Member == memberIdUsername.Value); + var sql = Sql() + .Select("umbracoNode.*") + .From() + .InnerJoin() + .On( dto => dto.NodeId, dto => dto.MemberGroup) + .Where(x => x.NodeObjectType == NodeObjectTypeId) + .Where(x => x.Member == memberIdUsername.Value); return Database.Fetch(sql) .DistinctBy(dto => dto.NodeId) @@ -225,14 +222,15 @@ namespace Umbraco.Core.Persistence.Repositories using (var transaction = Database.GetTransaction()) { //first get the member ids based on the usernames - var memberSql = new Sql(); var memberObjectType = new Guid(Constants.ObjectTypes.Member); - memberSql.Select("umbracoNode.id") - .From(SqlSyntax) - .InnerJoin(SqlSyntax) - .On(SqlSyntax, dto => dto.NodeId, dto => dto.NodeId) - .Where(SqlSyntax, x => x.NodeObjectType == memberObjectType) - .Where("cmsMember.LoginName in (@usernames)", new { usernames = usernames }); + + var memberSql = Sql() + .Select("umbracoNode.id") + .From() + .InnerJoin() + .On(dto => dto.NodeId, dto => dto.NodeId) + .Where(x => x.NodeObjectType == memberObjectType) + .Where("cmsMember.LoginName in (@usernames)", new { /*usernames =*/ usernames }); var memberIds = Database.Fetch(memberSql).ToArray(); AssignRolesInternal(memberIds, roleNames); @@ -245,14 +243,15 @@ namespace Umbraco.Core.Persistence.Repositories using (var transaction = Database.GetTransaction()) { //first get the member ids based on the usernames - var memberSql = new Sql(); var memberObjectType = new Guid(Constants.ObjectTypes.Member); - memberSql.Select("umbracoNode.id") - .From(SqlSyntax) - .InnerJoin(SqlSyntax) - .On(SqlSyntax, dto => dto.NodeId, dto => dto.NodeId) - .Where(SqlSyntax, x => x.NodeObjectType == memberObjectType) - .Where("cmsMember.LoginName in (@usernames)", new { usernames = usernames }); + + var memberSql = Sql() + .Select("umbracoNode.id") + .From() + .InnerJoin() + .On(dto => dto.NodeId, dto => dto.NodeId) + .Where( x => x.NodeObjectType == memberObjectType) + .Where("cmsMember.LoginName in (@usernames)", new { /*usernames =*/ usernames }); var memberIds = Database.Fetch(memberSql).ToArray(); DissociateRolesInternal(memberIds, roleNames); @@ -276,10 +275,10 @@ namespace Umbraco.Core.Persistence.Repositories //create the missing roles first - var existingSql = new Sql() - .Select("*") - .From(SqlSyntax) - .Where(SqlSyntax, dto => dto.NodeObjectType == NodeObjectTypeId) + var existingSql = Sql() + .SelectAll() + .From() + .Where(dto => dto.NodeObjectType == NodeObjectTypeId) .Where("umbracoNode." + SqlSyntax.GetQuotedColumnName("text") + " in (@names)", new { names = roleNames }); var existingRoles = Database.Fetch(existingSql).Select(x => x.Text); var missingRoles = roleNames.Except(existingRoles); @@ -300,16 +299,16 @@ namespace Umbraco.Core.Persistence.Repositories //get the groups that are currently assigned to any of these members - var assignedSql = new Sql(); - assignedSql.Select(string.Format( + var assignedSql = Sql() + .Select(string.Format( "{0},{1},{2}", SqlSyntax.GetQuotedColumnName("text"), SqlSyntax.GetQuotedColumnName("Member"), SqlSyntax.GetQuotedColumnName("MemberGroup"))) - .From(SqlSyntax) - .InnerJoin(SqlSyntax) - .On(SqlSyntax, dto => dto.NodeId, dto => dto.MemberGroup) - .Where(SqlSyntax, x => x.NodeObjectType == NodeObjectTypeId) + .From() + .InnerJoin() + .On(dto => dto.NodeId, dto => dto.MemberGroup) + .Where(x => x.NodeObjectType == NodeObjectTypeId) .Where("cmsMember2MemberGroup.Member in (@ids)", new { ids = memberIds }); var currentlyAssigned = Database.Fetch(assignedSql).ToArray(); @@ -343,15 +342,15 @@ namespace Umbraco.Core.Persistence.Repositories private void DissociateRolesInternal(int[] memberIds, string[] roleNames) { - var existingSql = new Sql() - .Select("*") - .From(SqlSyntax) - .Where(SqlSyntax, dto => dto.NodeObjectType == NodeObjectTypeId) + var existingSql = Sql() + .SelectAll() + .From() + .Where(dto => dto.NodeObjectType == NodeObjectTypeId) .Where("umbracoNode." + SqlSyntax.GetQuotedColumnName("text") + " in (@names)", new { names = roleNames }); var existingRolesIds = Database.Fetch(existingSql).Select(x => x.NodeId).ToArray(); Database.Execute("DELETE FROM cmsMember2MemberGroup WHERE Member IN (@memberIds) AND MemberGroup IN (@memberGroups)", - new { memberIds = memberIds, memberGroups = existingRolesIds }); + new { /*memberIds =*/ memberIds, memberGroups = existingRolesIds }); } private class AssignedRolesDto diff --git a/src/Umbraco.Core/Persistence/Repositories/MemberRepository.cs b/src/Umbraco.Core/Persistence/Repositories/MemberRepository.cs index e1b2b877e3..51fac1149c 100644 --- a/src/Umbraco.Core/Persistence/Repositories/MemberRepository.cs +++ b/src/Umbraco.Core/Persistence/Repositories/MemberRepository.cs @@ -5,6 +5,7 @@ using System.Linq; using System.Linq.Expressions; using System.Text; using System.Xml.Linq; +using NPoco; using Umbraco.Core.Configuration; using Umbraco.Core.Configuration.UmbracoSettings; using Umbraco.Core.IO; @@ -16,7 +17,6 @@ using Umbraco.Core.Models.Rdbms; using Umbraco.Core.Persistence.DatabaseModelDefinitions; using Umbraco.Core.Persistence.Factories; using Umbraco.Core.Persistence.Querying; -using Umbraco.Core.Persistence.Relators; using Umbraco.Core.Persistence.SqlSyntax; using Umbraco.Core.Persistence.UnitOfWork; using Umbraco.Core.Dynamics; @@ -53,9 +53,9 @@ namespace Umbraco.Core.Persistence.Repositories { var sql = GetBaseQuery(false); sql.Where(GetBaseWhereClause(), new { Id = id }); - sql.OrderByDescending(SqlSyntax, x => x.VersionDate); + sql.OrderByDescending(x => x.VersionDate); - var dto = Database.Fetch(sql).FirstOrDefault(); + var dto = Database.Fetch(sql).FirstOrDefault(); if (dto == null) return null; @@ -74,8 +74,8 @@ namespace Umbraco.Core.Persistence.Repositories sql.Where("umbracoNode.id in (@ids)", new { ids = ids }); } - return ProcessQuery(sql); - + return MapQueryDtos(Database.Fetch(sql)); + } protected override IEnumerable PerformGetByQuery(IQuery query) @@ -93,42 +93,51 @@ namespace Umbraco.Core.Persistence.Repositories var translator = new SqlTranslator(sqlWithProps, query); var sql = translator.Translate(); - baseQuery.Append(new Sql("WHERE umbracoNode.id IN (" + sql.SQL + ")", sql.Arguments)) - .OrderBy(SqlSyntax, x => x.SortOrder); + baseQuery.Append("WHERE umbracoNode.id IN (" + sql.SQL + ")", sql.Arguments) + .OrderBy(x => x.SortOrder); - return ProcessQuery(baseQuery); + return MapQueryDtos(Database.Fetch(baseQuery)); } else { var translator = new SqlTranslator(baseQuery, query); var sql = translator.Translate() - .OrderBy(SqlSyntax, x => x.SortOrder); + .OrderBy(x => x.SortOrder); - return ProcessQuery(sql); + return MapQueryDtos(Database.Fetch(sql)); } } #endregion - #region Overrides of PetaPocoRepositoryBase + #region Overrides of NPocoRepositoryBase - protected override Sql GetBaseQuery(bool isCount) + protected override Sql GetBaseQuery(bool isCount) { - var sql = new Sql(); - sql.Select(isCount ? "COUNT(*)" : "*") - .From(SqlSyntax) - .InnerJoin(SqlSyntax) - .On(SqlSyntax, left => left.NodeId, right => right.NodeId) - .InnerJoin(SqlSyntax) - .On(SqlSyntax, left => left.NodeId, right => right.NodeId) + var sql = Sql(); + + sql = isCount + ? sql.SelectCount() + : sql.Select(r => + r.Select(rr => + rr.Select(rrr => + rrr.Select()))); + + sql + .From() + .InnerJoin() + .On(left => left.NodeId, right => right.NodeId) + .InnerJoin() + .On(left => left.NodeId, right => right.NodeId) //We're joining the type so we can do a query against the member type - not sure if this adds much overhead or not? // the execution plan says it doesn't so we'll go with that and in that case, it might be worth joining the content // types by default on the document and media repo's so we can query by content type there too. - .InnerJoin(SqlSyntax).On(SqlSyntax, left => left.NodeId, right => right.ContentTypeId) - .InnerJoin(SqlSyntax) - .On(SqlSyntax, left => left.NodeId, right => right.NodeId) - .Where(SqlSyntax, x => x.NodeObjectType == NodeObjectTypeId); + .InnerJoin().On(left => left.NodeId, right => right.ContentTypeId) + .InnerJoin() + .On(left => left.NodeId, right => right.NodeId) + .Where(x => x.NodeObjectType == NodeObjectTypeId); + return sql; } @@ -138,21 +147,20 @@ namespace Umbraco.Core.Persistence.Repositories return "umbracoNode.id = @Id"; } - protected Sql GetNodeIdQueryWithPropertyData() + protected Sql GetNodeIdQueryWithPropertyData() { - var sql = new Sql(); - sql.Select("DISTINCT(umbracoNode.id)") - .From(SqlSyntax) - .InnerJoin(SqlSyntax).On(SqlSyntax, left => left.NodeId, right => right.NodeId) - .InnerJoin(SqlSyntax).On(SqlSyntax, left => left.NodeId, right => right.ContentTypeId) - .InnerJoin(SqlSyntax).On(SqlSyntax, left => left.NodeId, right => right.NodeId) - .InnerJoin(SqlSyntax).On(SqlSyntax, left => left.NodeId, right => right.NodeId) - .LeftJoin(SqlSyntax).On(SqlSyntax, left => left.ContentTypeId, right => right.ContentTypeId) - .LeftJoin(SqlSyntax).On(SqlSyntax, left => left.DataTypeId, right => right.DataTypeId) - .LeftJoin(SqlSyntax).On(SqlSyntax, left => left.PropertyTypeId, right => right.Id) + return Sql() + .Select("DISTINCT(umbracoNode.id)") + .From() + .InnerJoin().On(left => left.NodeId, right => right.NodeId) + .InnerJoin().On(left => left.NodeId, right => right.ContentTypeId) + .InnerJoin().On(left => left.NodeId, right => right.NodeId) + .InnerJoin().On(left => left.NodeId, right => right.NodeId) + .LeftJoin().On(left => left.ContentTypeId, right => right.ContentTypeId) + .LeftJoin().On(left => left.DataTypeId, right => right.DataTypeId) + .LeftJoin().On(left => left.PropertyTypeId, right => right.Id) .Append("AND cmsPropertyData.versionId = cmsContentVersion.VersionId") - .Where(SqlSyntax, x => x.NodeObjectType == NodeObjectTypeId); - return sql; + .Where(x => x.NodeObjectType == NodeObjectTypeId); } protected override IEnumerable GetDeleteClauses() @@ -208,7 +216,7 @@ namespace Umbraco.Core.Persistence.Repositories nodeDto.Path = parent.Path; nodeDto.Level = short.Parse(level.ToString(CultureInfo.InvariantCulture)); nodeDto.SortOrder = sortOrder; - var o = Database.IsNew(nodeDto) ? Convert.ToInt32(Database.Insert(nodeDto)) : Database.Update(nodeDto); + var o = Database.IsNew(nodeDto) ? Convert.ToInt32(Database.Insert(nodeDto)) : Database.Update(nodeDto); //Update with new correct path nodeDto.Path = string.Concat(parent.Path, ",", nodeDto.NodeId); @@ -239,7 +247,7 @@ namespace Umbraco.Core.Persistence.Repositories //Add Properties // - don't try to save the property if it doesn't exist (or doesn't have an ID) on the content type // - this can occur if the member type doesn't contain the built-in properties that the - // - member object contains. + // - member object contains. var propsToPersist = entity.Properties.Where(x => x.PropertyType.HasIdentity).ToArray(); var propertyDataDtos = propertyFactory.BuildDto(propsToPersist); var keyDictionary = new Dictionary(); @@ -270,7 +278,7 @@ namespace Umbraco.Core.Persistence.Repositories //Ensure that strings don't contain characters that are invalid in XML entity.SanitizeEntityPropertiesForXmlStorage(); - var dirtyEntity = (ICanBeDirty) entity; + var dirtyEntity = (ICanBeDirty)entity; //Look up parent to get and set the correct Path and update SortOrder if ParentId has changed if (dirtyEntity.IsPropertyDirty("ParentId")) @@ -309,9 +317,9 @@ namespace Umbraco.Core.Persistence.Repositories //Updates the current version - cmsContentVersion //Assumes a Version guid exists and Version date (modified date) has been set/updated Database.Update(dto.ContentVersionDto); - + //Updates the cmsMember entry if it has changed - + //NOTE: these cols are the REAL column names in the db var changedCols = new List(); @@ -331,19 +339,19 @@ namespace Umbraco.Core.Persistence.Repositories //only update the changed cols if (changedCols.Count > 0) { - Database.Update(dto, changedCols); + Database.Update(dto, changedCols); } //TODO ContentType for the Member entity //Create the PropertyData for this version - cmsPropertyData - var propertyFactory = new PropertyFactory(entity.ContentType.CompositionPropertyTypes.ToArray(), entity.Version, entity.Id); + var propertyFactory = new PropertyFactory(entity.ContentType.CompositionPropertyTypes.ToArray(), entity.Version, entity.Id); var keyDictionary = new Dictionary(); //Add Properties // - don't try to save the property if it doesn't exist (or doesn't have an ID) on the content type // - this can occur if the member type doesn't contain the built-in properties that the - // - member object contains. + // - member object contains. var propsToPersist = entity.Properties.Where(x => x.PropertyType.HasIdentity).ToArray(); var propertyDataDtos = propertyFactory.BuildDto(propsToPersist); @@ -389,12 +397,12 @@ namespace Umbraco.Core.Persistence.Repositories if (contentTypeIds == null) { var memberObjectType = Guid.Parse(Constants.ObjectTypes.Member); - var subQuery = new Sql() + var subQuery = Sql() .Select("DISTINCT cmsContentXml.nodeId") - .From(SqlSyntax) - .InnerJoin(SqlSyntax) - .On(SqlSyntax, left => left.NodeId, right => right.NodeId) - .Where(SqlSyntax, dto => dto.NodeObjectType == memberObjectType); + .From() + .InnerJoin() + .On(left => left.NodeId, right => right.NodeId) + .Where(dto => dto.NodeObjectType == memberObjectType); var deleteSql = SqlSyntax.GetDeleteSubquery("cmsContentXml", "nodeId", subQuery); Database.Execute(deleteSql); @@ -405,15 +413,15 @@ namespace Umbraco.Core.Persistence.Repositories { var id1 = id; var memberObjectType = Guid.Parse(Constants.ObjectTypes.Member); - var subQuery = new Sql() + var subQuery = Sql() .Select("DISTINCT cmsContentXml.nodeId") - .From(SqlSyntax) - .InnerJoin(SqlSyntax) - .On(SqlSyntax, left => left.NodeId, right => right.NodeId) - .InnerJoin(SqlSyntax) - .On(SqlSyntax, left => left.NodeId, right => right.NodeId) - .Where(SqlSyntax, dto => dto.NodeObjectType == memberObjectType) - .Where(SqlSyntax, dto => dto.ContentTypeId == id1); + .From() + .InnerJoin() + .On(left => left.NodeId, right => right.NodeId) + .InnerJoin() + .On(left => left.NodeId, right => right.NodeId) + .Where(dto => dto.NodeObjectType == memberObjectType) + .Where( dto => dto.ContentTypeId == id1); var deleteSql = SqlSyntax.GetDeleteSubquery("cmsContentXml", "nodeId", subQuery); Database.Execute(deleteSql); @@ -441,14 +449,14 @@ namespace Umbraco.Core.Persistence.Repositories } } - private void RebuildXmlStructuresProcessQuery(Func serializer, IQuery query, Transaction tr, int pageSize) + private void RebuildXmlStructuresProcessQuery(Func serializer, IQuery query, ITransaction tr, int pageSize) { var pageIndex = 0; var total = long.MinValue; var processed = 0; do { - var descendants = GetPagedResultsByQuery(query, pageIndex, pageSize, out total, "Path", Direction.Ascending); + var descendants = GetPagedResultsByQuery(query, pageIndex, pageSize, out total, "Path", Direction.Ascending, true); var xmlItems = (from descendant in descendants let xml = serializer(descendant) @@ -467,9 +475,9 @@ namespace Umbraco.Core.Persistence.Repositories { var sql = GetBaseQuery(false); sql.Where("cmsContentVersion.VersionId = @VersionId", new { VersionId = versionId }); - sql.OrderByDescending(SqlSyntax, x => x.VersionDate); + sql.OrderByDescending(x => x.VersionDate); - var dto = Database.Fetch(sql).FirstOrDefault(); + var dto = Database.Fetch(sql).FirstOrDefault(); if (dto == null) return null; @@ -479,7 +487,7 @@ namespace Umbraco.Core.Persistence.Repositories var factory = new MemberFactory(memberType, NodeObjectTypeId, dto.NodeId); var media = factory.BuildEntity(dto); - var properties = GetPropertyCollection(sql, new[] { new DocumentDefinition(dto.NodeId, dto.ContentVersionDto.VersionId, media.UpdateDate, media.CreateDate, memberType) }); + var properties = GetPropertyCollection(new[] { new DocumentDefinition(dto.NodeId, dto.ContentVersionDto.VersionId, media.UpdateDate, media.CreateDate, memberType) }); media.Properties = properties[dto.NodeId]; @@ -537,8 +545,8 @@ namespace Umbraco.Core.Persistence.Repositories foreach (var batch in inGroups) { var memberIdBatch = batch.Select(x => x.Id); - var sql = new Sql().Select("*").From(SqlSyntax) - .Where(SqlSyntax, dto => dto.MemberGroup == memberGroup.Id) + var sql = Sql().SelectAll().From() + .Where(dto => dto.MemberGroup == memberGroup.Id) .Where("Member IN (@memberIds)", new { memberIds = memberIdBatch }); var memberIdsInGroup = Database.Fetch(sql) .Select(x => x.Member).ToArray(); @@ -560,27 +568,26 @@ namespace Umbraco.Core.Persistence.Repositories var grpQry = QueryFactory.Create().Where(group => group.Name.Equals(groupName)); var memberGroup = _memberGroupRepository.GetByQuery(grpQry).FirstOrDefault(); if (memberGroup == null) return Enumerable.Empty(); - - var subQuery = new Sql().Select("Member").From(SqlSyntax).Where(SqlSyntax, dto => dto.MemberGroup == memberGroup.Id); + + var subQuery = Sql().Select("Member").From().Where(dto => dto.MemberGroup == memberGroup.Id); var sql = GetBaseQuery(false) //TODO: An inner join would be better, though I've read that the query optimizer will always turn a // subquery with an IN clause into an inner join anyways. - .Append(new Sql("WHERE umbracoNode.id IN (" + subQuery.SQL + ")", subQuery.Arguments)) - .OrderByDescending(SqlSyntax, x => x.VersionDate) - .OrderBy(SqlSyntax, x => x.SortOrder); - - return ProcessQuery(sql); + .Append("WHERE umbracoNode.id IN (" + subQuery.SQL + ")", subQuery.Arguments) + .OrderByDescending(x => x.VersionDate) + .OrderBy(x => x.SortOrder); + + return MapQueryDtos(Database.Fetch(sql)); } public bool Exists(string username) { - var sql = new Sql(); - - sql.Select("COUNT(*)") - .From(SqlSyntax) - .Where(SqlSyntax, x => x.LoginName == username); + var sql = Sql() + .SelectCount() + .From() + .Where(x => x.LoginName == username); return Database.ExecuteScalar(sql) > 0; } @@ -594,7 +601,7 @@ namespace Umbraco.Core.Persistence.Repositories //get the COUNT base query var fullSql = GetBaseQuery(true) .Append(new Sql("WHERE umbracoNode.id IN (" + sql.SQL + ")", sql.Arguments)); - + return Database.ExecuteScalar(fullSql); } @@ -604,36 +611,30 @@ namespace Umbraco.Core.Persistence.Repositories /// /// The where clause, if this is null all records are queried /// - /// - /// - /// - /// - /// - /// + /// Index of the page. + /// Size of the page. + /// The total records. + /// The order by column + /// The order direction. + /// Flag to indicate when ordering by system field + /// Search query /// /// - /// The query supplied will ONLY work with data specifically on the cmsMember table because we are using PetaPoco paging (SQL paging) + /// The query supplied will ONLY work with data specifically on the cmsMember table because we are using NPoco paging (SQL paging) /// public IEnumerable GetPagedResultsByQuery(IQuery query, long pageIndex, int pageSize, out long totalRecords, - string orderBy, Direction orderDirection, string filter = "") + string orderBy, Direction orderDirection, bool orderBySystemField, string filter = "") { - var args = new List(); - var sbWhere = new StringBuilder(); - Func> filterCallback = null; - if (filter.IsNullOrWhiteSpace() == false) - { - sbWhere.Append("AND ((umbracoNode. " + SqlSyntax.GetQuotedColumnName("text") + " LIKE @" + args.Count + ") " + - "OR (cmsMember.LoginName LIKE @0" + args.Count + "))"); - args.Add("%" + filter + "%"); - filterCallback = () => new Tuple(sbWhere.ToString().Trim(), args.ToArray()); - } + var filterSql = filter.IsNullOrWhiteSpace() + ? null + : Sql().Append("AND ((umbracoNode. " + SqlSyntax.GetQuotedColumnName("text") + " LIKE @0) " + + "OR (cmsMember.LoginName LIKE @0))", "%" + filter + "%"); - return GetPagedResultsByQuery(query, pageIndex, pageSize, out totalRecords, - new Tuple("cmsMember", "nodeId"), - ProcessQuery, orderBy, orderDirection, - filterCallback); + return GetPagedResultsByQuery(query, pageIndex, pageSize, out totalRecords, + MapQueryDtos, orderBy, orderDirection, orderBySystemField, + filterSql); } - + public void AddOrUpdateContentXml(IMember content, Func xml) { _contentXmlRepository.AddOrUpdate(new ContentXmlEntity(content, xml)); @@ -658,23 +659,8 @@ namespace Umbraco.Core.Persistence.Repositories return base.GetDatabaseFieldNameForOrderBy(orderBy); } - protected override string GetEntityPropertyNameForOrderBy(string orderBy) + private IEnumerable MapQueryDtos(List dtos) { - //Some custom ones - switch (orderBy.ToUpperInvariant()) - { - case "LOGINNAME": - return "Username"; - } - - return base.GetEntityPropertyNameForOrderBy(orderBy); - } - - private IEnumerable ProcessQuery(Sql sql) - { - //NOTE: This doesn't allow properties to be part of the query - var dtos = Database.Fetch(sql); - var ids = dtos.Select(x => x.ContentVersionDto.ContentDto.ContentTypeId).ToArray(); //content types @@ -683,7 +669,7 @@ namespace Umbraco.Core.Persistence.Repositories var dtosWithContentTypes = dtos //This select into and null check are required because we don't have a foreign damn key on the contentType column // http://issues.umbraco.org/issue/U4-5503 - .Select(x => new {dto = x, contentType = contentTypes.FirstOrDefault(ct => ct.Id == x.ContentVersionDto.ContentDto.ContentTypeId)}) + .Select(x => new { dto = x, contentType = contentTypes.FirstOrDefault(ct => ct.Id == x.ContentVersionDto.ContentDto.ContentTypeId) }) .Where(x => x.contentType != null) .ToArray(); @@ -695,12 +681,12 @@ namespace Umbraco.Core.Persistence.Repositories d.dto.ContentVersionDto.ContentDto.NodeDto.CreateDate, d.contentType)); - var propertyData = GetPropertyCollection(sql, docDefs); + var propertyData = GetPropertyCollection(docDefs.ToArray()); return dtosWithContentTypes.Select(d => CreateMemberFromDto( d.dto, contentTypes.First(ct => ct.Id == d.dto.ContentVersionDto.ContentDto.ContentTypeId), - propertyData[d.dto.NodeId])); + propertyData[d.dto.NodeId])); } /// @@ -741,7 +727,7 @@ namespace Umbraco.Core.Persistence.Repositories var docDef = new DocumentDefinition(dto.ContentVersionDto.NodeId, versionId, member.UpdateDate, member.CreateDate, memberType); - var properties = GetPropertyCollection(docSql, new[] { docDef }); + var properties = GetPropertyCollection(new[] { docDef }); member.Properties = properties[dto.ContentVersionDto.NodeId]; diff --git a/src/Umbraco.Core/Persistence/Repositories/MemberTypeRepository.cs b/src/Umbraco.Core/Persistence/Repositories/MemberTypeRepository.cs index 172d2f8296..21f46eb800 100644 --- a/src/Umbraco.Core/Persistence/Repositories/MemberTypeRepository.cs +++ b/src/Umbraco.Core/Persistence/Repositories/MemberTypeRepository.cs @@ -2,6 +2,7 @@ using System.Collections.Generic; using System.Linq; using log4net; +using NPoco; using Umbraco.Core.Cache; using Umbraco.Core.Logging; using Umbraco.Core.Models.EntityBase; @@ -11,7 +12,6 @@ using Umbraco.Core.Models.Rdbms; using Umbraco.Core.Persistence.Factories; using Umbraco.Core.Persistence.Mappers; using Umbraco.Core.Persistence.Querying; -using Umbraco.Core.Persistence.Relators; using Umbraco.Core.Persistence.SqlSyntax; using Umbraco.Core.Persistence.UnitOfWork; @@ -40,7 +40,7 @@ namespace Umbraco.Core.Persistence.Repositories expires: true)); } } - + protected override IMemberType PerformGet(int id) { //use the underlying GetAll which will force cache all content types @@ -56,11 +56,12 @@ namespace Umbraco.Core.Persistence.Repositories var statement = string.Join(" OR ", ids.Select(x => string.Format("umbracoNode.id='{0}'", x))); sql.Where(statement); } - sql.OrderByDescending(SqlSyntax, x => x.NodeId); + sql.OrderByDescending(x => x.NodeId); - var dtos = - Database.Fetch( - new PropertyTypePropertyGroupRelator().Map, sql); + var dtos = Database + .Fetch(sql) // cannot use FetchOneToMany because we have 2 collections! + .Transform(MapOneToManies) + .ToList(); return BuildFromDtos(dtos); } @@ -71,57 +72,89 @@ namespace Umbraco.Core.Persistence.Repositories var translator = new SqlTranslator(sqlSubquery, query); var subquery = translator.Translate(); var sql = GetBaseQuery(false) - .Append(new Sql("WHERE umbracoNode.id IN (" + subquery.SQL + ")", subquery.Arguments)) - .OrderBy(SqlSyntax, x => x.SortOrder); + .Append("WHERE umbracoNode.id IN (" + subquery.SQL + ")", subquery.Arguments) + .OrderBy(x => x.SortOrder); - var dtos = - Database.Fetch( - new PropertyTypePropertyGroupRelator().Map, sql); + var dtos = Database + .Fetch(sql) // cannot use FetchOneToMany because we have 2 collections! + .Transform(MapOneToManies) + .ToList(); return BuildFromDtos(dtos); } - - protected override Sql GetBaseQuery(bool isCount) - { - var sql = new Sql(); - if (isCount) + private IEnumerable MapOneToManies(IEnumerable dtos) + { + MemberTypeReadOnlyDto acc = null; + foreach (var dto in dtos) { - sql.Select("COUNT(*)") - .From(SqlSyntax) - .InnerJoin(SqlSyntax).On(SqlSyntax, left => left.NodeId, right => right.NodeId) - .Where(SqlSyntax, x => x.NodeObjectType == NodeObjectTypeId); - return sql; + if (acc == null) + { + acc = dto; + } + else if (acc.UniqueId == dto.UniqueId) + { + var prop = dto.PropertyTypes.SingleOrDefault(); + var group = dto.PropertyTypeGroups.SingleOrDefault(); + + if (prop != null && prop.Id.HasValue && acc.PropertyTypes.Any(x => x.Id == prop.Id.Value) == false) + acc.PropertyTypes.Add(prop); + + if (group != null && group.Id.HasValue && acc.PropertyTypeGroups.Any(x => x.Id == group.Id.Value) == false) + acc.PropertyTypeGroups.Add(group); + } + else + { + yield return acc; + acc = dto; + } } - sql.Select("umbracoNode.*", "cmsContentType.*", "cmsPropertyType.id AS PropertyTypeId", "cmsPropertyType.Alias", - "cmsPropertyType.Name", "cmsPropertyType.Description", "cmsPropertyType.mandatory", - "cmsPropertyType.validationRegExp", "cmsPropertyType.dataTypeId", "cmsPropertyType.sortOrder AS PropertyTypeSortOrder", - "cmsPropertyType.propertyTypeGroupId AS PropertyTypesGroupId", "cmsMemberType.memberCanEdit", "cmsMemberType.viewOnProfile", - "cmsDataType.propertyEditorAlias", "cmsDataType.dbType", "cmsPropertyTypeGroup.id AS PropertyTypeGroupId", - "cmsPropertyTypeGroup.text AS PropertyGroupName", - "cmsPropertyTypeGroup.sortorder AS PropertyGroupSortOrder", "cmsPropertyTypeGroup.contenttypeNodeId") - .From(SqlSyntax) - .InnerJoin(SqlSyntax).On(SqlSyntax, left => left.NodeId, right => right.NodeId) - .LeftJoin(SqlSyntax).On(SqlSyntax, left => left.ContentTypeId, right => right.NodeId) - .LeftJoin(SqlSyntax).On(SqlSyntax, left => left.PropertyTypeId, right => right.Id) - .LeftJoin(SqlSyntax).On(SqlSyntax, left => left.DataTypeId, right => right.DataTypeId) - .LeftJoin(SqlSyntax).On(SqlSyntax, left => left.ContentTypeNodeId, right => right.NodeId) - .Where(SqlSyntax, x => x.NodeObjectType == NodeObjectTypeId); + if (acc != null) + yield return acc; + } + + protected override Sql GetBaseQuery(bool isCount) + { + if (isCount) + { + return Sql() + .SelectCount() + .From() + .InnerJoin().On(left => left.NodeId, right => right.NodeId) + .Where(x => x.NodeObjectType == NodeObjectTypeId); + } + + var sql = Sql() + .Select("umbracoNode.*", "cmsContentType.*", "cmsPropertyType.id AS PropertyTypeId", "cmsPropertyType.Alias", + "cmsPropertyType.Name", "cmsPropertyType.Description", "cmsPropertyType.mandatory", + "cmsPropertyType.validationRegExp", "cmsPropertyType.dataTypeId", "cmsPropertyType.sortOrder AS PropertyTypeSortOrder", + "cmsPropertyType.propertyTypeGroupId AS PropertyTypesGroupId", "cmsMemberType.memberCanEdit", "cmsMemberType.viewOnProfile", + "cmsDataType.propertyEditorAlias", "cmsDataType.dbType", "cmsPropertyTypeGroup.id AS PropertyTypeGroupId", + "cmsPropertyTypeGroup.text AS PropertyGroupName", + "cmsPropertyTypeGroup.sortorder AS PropertyGroupSortOrder", "cmsPropertyTypeGroup.contenttypeNodeId") + .From() + .InnerJoin().On(left => left.NodeId, right => right.NodeId) + .LeftJoin().On(left => left.ContentTypeId, right => right.NodeId) + .LeftJoin().On(left => left.PropertyTypeId, right => right.Id) + .LeftJoin().On(left => left.DataTypeId, right => right.DataTypeId) + .LeftJoin().On(left => left.ContentTypeNodeId, right => right.NodeId) + .Where(x => x.NodeObjectType == NodeObjectTypeId); + return sql; } - protected Sql GetSubquery() + protected Sql GetSubquery() { - var sql = new Sql() + var sql = Sql() .Select("DISTINCT(umbracoNode.id)") - .From(SqlSyntax) - .InnerJoin(SqlSyntax).On(SqlSyntax, left => left.NodeId, right => right.NodeId) - .LeftJoin(SqlSyntax).On(SqlSyntax, left => left.ContentTypeId, right => right.NodeId) - .LeftJoin(SqlSyntax).On(SqlSyntax, left => left.PropertyTypeId, right => right.Id) - .LeftJoin(SqlSyntax).On(SqlSyntax, left => left.DataTypeId, right => right.DataTypeId) - .LeftJoin(SqlSyntax).On(SqlSyntax, left => left.ContentTypeNodeId, right => right.NodeId) - .Where(SqlSyntax, x => x.NodeObjectType == NodeObjectTypeId); + .From() + .InnerJoin().On(left => left.NodeId, right => right.NodeId) + .LeftJoin().On(left => left.ContentTypeId, right => right.NodeId) + .LeftJoin().On(left => left.PropertyTypeId, right => right.Id) + .LeftJoin().On(left => left.DataTypeId, right => right.DataTypeId) + .LeftJoin().On(left => left.ContentTypeNodeId, right => right.NodeId) + .Where(x => x.NodeObjectType == NodeObjectTypeId); return sql; } @@ -154,13 +187,13 @@ namespace Umbraco.Core.Persistence.Repositories { get { return new Guid(Constants.ObjectTypes.MemberType); } } - + protected override void PersistNewItem(IMemberType entity) { ValidateAlias(entity); ((MemberType)entity).AddingEntity(); - + //set a default icon if one is not specified if (entity.Icon.IsNullOrWhiteSpace()) { @@ -225,7 +258,7 @@ namespace Umbraco.Core.Persistence.Repositories entity.ResetDirtyProperties(); } - + /// /// Override so we can specify explicit db type's on any property types that are built-in. /// @@ -311,7 +344,7 @@ namespace Umbraco.Core.Persistence.Repositories } /// - /// If this is one of our internal properties - we will manually assign the data type since they must + /// If this is one of our internal properties - we will manually assign the data type since they must /// always correspond to the correct db type no matter what the backing data type is assigned. /// /// @@ -338,7 +371,7 @@ namespace Umbraco.Core.Persistence.Repositories } /// - /// + /// /// /// /// diff --git a/src/Umbraco.Core/Persistence/Repositories/MigrationEntryRepository.cs b/src/Umbraco.Core/Persistence/Repositories/MigrationEntryRepository.cs index c10e9169a4..1749ae8be3 100644 --- a/src/Umbraco.Core/Persistence/Repositories/MigrationEntryRepository.cs +++ b/src/Umbraco.Core/Persistence/Repositories/MigrationEntryRepository.cs @@ -1,6 +1,7 @@ using System; using System.Collections.Generic; using System.Linq; +using NPoco; using Semver; using Umbraco.Core.Logging; using Umbraco.Core.Models; @@ -13,7 +14,7 @@ using Umbraco.Core.Persistence.UnitOfWork; namespace Umbraco.Core.Persistence.Repositories { - internal class MigrationEntryRepository : PetaPocoRepositoryBase, IMigrationEntryRepository + internal class MigrationEntryRepository : NPocoRepositoryBase, IMigrationEntryRepository { public MigrationEntryRepository(IDatabaseUnitOfWork work, CacheHelper cache, ILogger logger, ISqlSyntaxProvider sqlSyntax, IMappingResolver mappingResolver) : base(work, cache, logger, sqlSyntax, mappingResolver) @@ -63,11 +64,17 @@ namespace Umbraco.Core.Persistence.Repositories return Database.Fetch(sql).Select(x => factory.BuildEntity(x)); } - protected override Sql GetBaseQuery(bool isCount) + protected override Sql GetBaseQuery(bool isCount) { - var sql = new Sql(); - sql.Select(isCount ? "COUNT(*)" : "*") - .From(SqlSyntax); + var sql = Sql(); + + sql = isCount + ? sql.SelectCount() + : sql.Select(); + + sql + .From(); + return sql; } @@ -119,9 +126,9 @@ namespace Umbraco.Core.Persistence.Repositories { var versionString = version.ToString(); - var sql = new Sql().Select("*") - .From(SqlSyntax) - .Where(SqlSyntax, x => x.Name.InvariantEquals(migrationName) && x.Version == versionString); + var sql = Sql().SelectAll() + .From() + .Where(x => x.Name.InvariantEquals(migrationName) && x.Version == versionString); var result = Database.FirstOrDefault(sql); diff --git a/src/Umbraco.Core/Persistence/Repositories/PetaPocoRepositoryBase.cs b/src/Umbraco.Core/Persistence/Repositories/NPocoRepositoryBase.cs similarity index 65% rename from src/Umbraco.Core/Persistence/Repositories/PetaPocoRepositoryBase.cs rename to src/Umbraco.Core/Persistence/Repositories/NPocoRepositoryBase.cs index 569865e688..24eeb93fd9 100644 --- a/src/Umbraco.Core/Persistence/Repositories/PetaPocoRepositoryBase.cs +++ b/src/Umbraco.Core/Persistence/Repositories/NPocoRepositoryBase.cs @@ -1,6 +1,7 @@ using System; using System.Collections.Generic; using System.Data.SqlServerCe; +using NPoco; using Umbraco.Core.Logging; using Umbraco.Core.Models.EntityBase; using Umbraco.Core.Persistence.Mappers; @@ -11,57 +12,49 @@ using Umbraco.Core.Persistence.UnitOfWork; namespace Umbraco.Core.Persistence.Repositories { /// - /// Represent an abstract Repository for PetaPoco based repositories + /// Represent an abstract Repository for NPoco based repositories /// /// /// - internal abstract class PetaPocoRepositoryBase : RepositoryBase + internal abstract class NPocoRepositoryBase : RepositoryBase where TEntity : class, IAggregateRoot { - public ISqlSyntaxProvider SqlSyntax { get; private set; } + public ISqlSyntaxProvider SqlSyntax { get; } - private readonly QueryFactory _queryFactory; /// /// Returns the Query factory /// - public override QueryFactory QueryFactory - { - get { return _queryFactory; } - } + public override QueryFactory QueryFactory { get; } /// /// Used to create a new query instance /// /// - public override Query Query - { - get { return QueryFactory.Create(); } - } + public override Query Query => QueryFactory.Create(); - protected PetaPocoRepositoryBase(IDatabaseUnitOfWork work, CacheHelper cache, ILogger logger, ISqlSyntaxProvider sqlSyntax, IMappingResolver mappingResolver) + protected NPocoRepositoryBase(IUnitOfWork work, CacheHelper cache, ILogger logger, ISqlSyntaxProvider sqlSyntax, IMappingResolver mappingResolver) : base(work, cache, logger) { - if (sqlSyntax == null) throw new ArgumentNullException("sqlSyntax"); + if (sqlSyntax == null) throw new ArgumentNullException(nameof(sqlSyntax)); SqlSyntax = sqlSyntax; - _queryFactory = new QueryFactory(SqlSyntax, mappingResolver); + QueryFactory = new QueryFactory(SqlSyntax, mappingResolver); } /// /// Returns the database Unit of Work added to the repository /// - protected internal new IDatabaseUnitOfWork UnitOfWork - { - get { return (IDatabaseUnitOfWork)base.UnitOfWork; } - } + protected internal new IDatabaseUnitOfWork UnitOfWork => (IDatabaseUnitOfWork) base.UnitOfWork; - protected UmbracoDatabase Database + protected UmbracoDatabase Database => UnitOfWork.Database; + + protected Sql Sql() { - get { return UnitOfWork.Database; } + return NPoco.Sql.BuilderFor(new SqlContext(SqlSyntax, Database)); } #region Abstract Methods - - protected abstract Sql GetBaseQuery(bool isCount); + + protected abstract Sql GetBaseQuery(bool isCount); protected abstract string GetBaseWhereClause(); protected abstract IEnumerable GetDeleteClauses(); protected abstract Guid NodeObjectTypeId { get; } @@ -96,7 +89,7 @@ namespace Umbraco.Core.Persistence.Repositories } } - protected virtual TId GetEntityId(TEntity entity) + protected virtual new TId GetEntityId(TEntity entity) { return (TId)(object)entity.Id; } diff --git a/src/Umbraco.Core/Persistence/Repositories/NotificationsRepository.cs b/src/Umbraco.Core/Persistence/Repositories/NotificationsRepository.cs index 668fdf4b5b..67b36caa86 100644 --- a/src/Umbraco.Core/Persistence/Repositories/NotificationsRepository.cs +++ b/src/Umbraco.Core/Persistence/Repositories/NotificationsRepository.cs @@ -1,6 +1,7 @@ using System; using System.Collections.Generic; using System.Linq; +using NPoco; using Umbraco.Core.Models; using Umbraco.Core.Models.EntityBase; using Umbraco.Core.Models.Membership; @@ -23,13 +24,13 @@ namespace Umbraco.Core.Persistence.Repositories public IEnumerable GetUserNotifications(IUser user) { - var sql = new Sql() + var sql = NPoco.Sql.BuilderFor(new SqlContext(_sqlSyntax, _unitOfWork.Database)) .Select("DISTINCT umbracoNode.id, umbracoUser2NodeNotify.userId, umbracoNode.nodeObjectType, umbracoUser2NodeNotify.action") - .From(_sqlSyntax) - .InnerJoin(_sqlSyntax) - .On(_sqlSyntax, dto => dto.NodeId, dto => dto.NodeId) - .Where(_sqlSyntax, dto => dto.UserId == (int)user.Id) - .OrderBy(_sqlSyntax, dto => dto.NodeId); + .From() + .InnerJoin() + .On(dto => dto.NodeId, dto => dto.NodeId) + .Where(dto => dto.UserId == (int)user.Id) + .OrderBy(dto => dto.NodeId); var dtos = _unitOfWork.Database.Fetch(sql); //need to map the results @@ -50,13 +51,13 @@ namespace Umbraco.Core.Persistence.Repositories public IEnumerable GetEntityNotifications(IEntity entity) { - var sql = new Sql() + var sql = NPoco.Sql.BuilderFor(new SqlContext(_sqlSyntax, _unitOfWork.Database)) .Select("DISTINCT umbracoNode.id, umbracoUser2NodeNotify.userId, umbracoNode.nodeObjectType, umbracoUser2NodeNotify.action") - .From(_sqlSyntax) - .InnerJoin(_sqlSyntax) - .On(_sqlSyntax, dto => dto.NodeId, dto => dto.NodeId) - .Where(_sqlSyntax, dto => dto.NodeId == entity.Id) - .OrderBy(_sqlSyntax, dto => dto.NodeId); + .From() + .InnerJoin() + .On(dto => dto.NodeId, dto => dto.NodeId) + .Where(dto => dto.NodeId == entity.Id) + .OrderBy(dto => dto.NodeId); var dtos = _unitOfWork.Database.Fetch(sql); //need to map the results @@ -81,10 +82,10 @@ namespace Umbraco.Core.Persistence.Repositories public Notification CreateNotification(IUser user, IEntity entity, string action) { - var sql = new Sql() + var sql = NPoco.Sql.BuilderFor(new SqlContext(_sqlSyntax, _unitOfWork.Database)) .Select("DISTINCT nodeObjectType") - .From(_sqlSyntax) - .Where(_sqlSyntax, nodeDto => nodeDto.NodeId == entity.Id); + .From() + .Where(nodeDto => nodeDto.NodeId == entity.Id); var nodeType = _unitOfWork.Database.ExecuteScalar(sql); var dto = new User2NodeNotifyDto() diff --git a/src/Umbraco.Core/Persistence/Repositories/PermissionRepository.cs b/src/Umbraco.Core/Persistence/Repositories/PermissionRepository.cs index 8be1dc1b6d..8b37a2b6f1 100644 --- a/src/Umbraco.Core/Persistence/Repositories/PermissionRepository.cs +++ b/src/Umbraco.Core/Persistence/Repositories/PermissionRepository.cs @@ -4,8 +4,10 @@ using System.Collections.Generic; using System.Dynamic; using System.Globalization; using System.Linq; +using System.Runtime.InteropServices; using System.Text; using System.Web.Caching; +using NPoco; using Umbraco.Core.Events; using Umbraco.Core.Models.EntityBase; using Umbraco.Core.Models.Membership; @@ -78,9 +80,9 @@ namespace Umbraco.Core.Persistence.Repositories whereBuilder.Append(")"); } - var sql = new Sql(); - sql.Select("*") - .From(_sqlSyntax) + var sql = NPoco.Sql.BuilderFor(new SqlContext(_sqlSyntax, _unitOfWork.Database)) + .SelectAll() + .From() .Where(whereBuilder.ToString()); //ToArray() to ensure it's all fetched from the db once. @@ -103,11 +105,11 @@ namespace Umbraco.Core.Persistence.Repositories /// public IEnumerable GetPermissionsForEntity(int entityId) { - var sql = new Sql(); - sql.Select("*") - .From(_sqlSyntax) - .Where(_sqlSyntax, dto => dto.NodeId == entityId) - .OrderBy(_sqlSyntax, dto => dto.NodeId); + var sql = NPoco.Sql.BuilderFor(new SqlContext(_sqlSyntax, _unitOfWork.Database)) + .SelectAll() + .From() + .Where(dto => dto.NodeId == entityId) + .OrderBy(dto => dto.NodeId); //ToArray() to ensure it's all fetched from the db once. var result = _unitOfWork.Database.Fetch(sql).ToArray(); diff --git a/src/Umbraco.Core/Persistence/Repositories/PublicAccessRepository.cs b/src/Umbraco.Core/Persistence/Repositories/PublicAccessRepository.cs index 3b3538b220..c389bce2f7 100644 --- a/src/Umbraco.Core/Persistence/Repositories/PublicAccessRepository.cs +++ b/src/Umbraco.Core/Persistence/Repositories/PublicAccessRepository.cs @@ -1,6 +1,7 @@ using System; using System.Collections.Generic; using System.Linq; +using NPoco; using Umbraco.Core.Cache; using Umbraco.Core.Logging; using Umbraco.Core.Models; @@ -8,13 +9,12 @@ using Umbraco.Core.Models.Rdbms; using Umbraco.Core.Persistence.Factories; using Umbraco.Core.Persistence.Mappers; using Umbraco.Core.Persistence.Querying; -using Umbraco.Core.Persistence.Relators; using Umbraco.Core.Persistence.SqlSyntax; using Umbraco.Core.Persistence.UnitOfWork; namespace Umbraco.Core.Persistence.Repositories { - internal class PublicAccessRepository : PetaPocoRepositoryBase, IPublicAccessRepository + internal class PublicAccessRepository : NPocoRepositoryBase, IPublicAccessRepository { public PublicAccessRepository(IDatabaseUnitOfWork work, CacheHelper cache, ILogger logger, ISqlSyntaxProvider sqlSyntax, IMappingResolver mappingResolver) : base(work, cache, logger, sqlSyntax, mappingResolver) @@ -48,7 +48,7 @@ namespace Umbraco.Core.Persistence.Repositories } var factory = new PublicAccessEntryFactory(); - var dtos = Database.Fetch(new AccessRulesRelator().Map, sql); + var dtos = Database.FetchOneToMany(x => x.Rules, sql); return dtos.Select(factory.BuildEntity); } @@ -59,19 +59,17 @@ namespace Umbraco.Core.Persistence.Repositories var sql = translator.Translate(); var factory = new PublicAccessEntryFactory(); - var dtos = Database.Fetch(new AccessRulesRelator().Map, sql); + var dtos = Database.FetchOneToMany(x => x.Rules, sql); return dtos.Select(factory.BuildEntity); } - protected override Sql GetBaseQuery(bool isCount) + protected override Sql GetBaseQuery(bool isCount) { - var sql = new Sql(); - sql.Select("*") - .From(SqlSyntax) - .LeftJoin(SqlSyntax) - .On(SqlSyntax, left => left.Id, right => right.AccessId); - - return sql; + return Sql() + .SelectAll() + .From() + .LeftJoin() + .On(left => left.Id, right => right.AccessId); } protected override string GetBaseWhereClause() @@ -164,6 +162,6 @@ namespace Umbraco.Core.Persistence.Repositories return entity.Key; } - + } } \ No newline at end of file diff --git a/src/Umbraco.Core/Persistence/Repositories/RecycleBinRepository.cs b/src/Umbraco.Core/Persistence/Repositories/RecycleBinRepository.cs index e7b2d664b9..5f6be8eca7 100644 --- a/src/Umbraco.Core/Persistence/Repositories/RecycleBinRepository.cs +++ b/src/Umbraco.Core/Persistence/Repositories/RecycleBinRepository.cs @@ -2,6 +2,7 @@ using System; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; +using NPoco; using Umbraco.Core.Configuration; using Umbraco.Core.Configuration.UmbracoSettings; using Umbraco.Core.IO; @@ -109,21 +110,19 @@ namespace Umbraco.Core.Persistence.Repositories /// internal List GetFilesInRecycleBinForUploadField() { - var db = this.Database; - //Issue query to get all trashed content or media that has the Upload field as a property //The value for each field is stored in a list: FilesToDelete() //Alias: Constants.Conventions.Media.File and PropertyEditorAlias: Constants.PropertyEditors.UploadField - var sql = new Sql(); - sql.Select("DISTINCT(dataNvarchar)") - .From(SqlSyntax) - .InnerJoin(SqlSyntax).On(SqlSyntax, left => left.NodeId, right => right.NodeId) - .InnerJoin(SqlSyntax).On(SqlSyntax, left => left.PropertyTypeId, right => right.Id) - .InnerJoin(SqlSyntax).On(SqlSyntax, left => left.DataTypeId, right => right.DataTypeId) + var sql = Sql() + .Select("DISTINCT(dataNvarchar)") + .From() + .InnerJoin().On(left => left.NodeId, right => right.NodeId) + .InnerJoin().On(left => left.PropertyTypeId, right => right.Id) + .InnerJoin().On(left => left.DataTypeId, right => right.DataTypeId) .Where("umbracoNode.trashed = '1' AND umbracoNode.nodeObjectType = @NodeObjectType AND dataNvarchar IS NOT NULL AND (cmsPropertyType.Alias = @FileAlias OR cmsDataType.propertyEditorAlias = @PropertyEditorAlias)", new { FileAlias = Constants.Conventions.Media.File, NodeObjectType = NodeObjectTypeId, PropertyEditorAlias = Constants.PropertyEditors.UploadFieldAlias }); - var files = db.Fetch(sql); + var files = Database.Fetch(sql); return files; } } diff --git a/src/Umbraco.Core/Persistence/Repositories/RelationRepository.cs b/src/Umbraco.Core/Persistence/Repositories/RelationRepository.cs index b6c312e4da..a021aca520 100644 --- a/src/Umbraco.Core/Persistence/Repositories/RelationRepository.cs +++ b/src/Umbraco.Core/Persistence/Repositories/RelationRepository.cs @@ -1,6 +1,7 @@ using System; using System.Collections.Generic; using System.Linq; +using NPoco; using Umbraco.Core.Logging; using Umbraco.Core.Models; using Umbraco.Core.Models.EntityBase; @@ -17,7 +18,7 @@ namespace Umbraco.Core.Persistence.Repositories /// /// Represents a repository for doing CRUD operations for /// - internal class RelationRepository : PetaPocoRepositoryBase, IRelationRepository + internal class RelationRepository : NPocoRepositoryBase, IRelationRepository { private readonly IRelationTypeRepository _relationTypeRepository; @@ -89,13 +90,19 @@ namespace Umbraco.Core.Persistence.Repositories #endregion - #region Overrides of PetaPocoRepositoryBase + #region Overrides of NPocoRepositoryBase - protected override Sql GetBaseQuery(bool isCount) + protected override Sql GetBaseQuery(bool isCount) { - var sql = new Sql(); - sql.Select(isCount ? "COUNT(*)" : "*") - .From(SqlSyntax); + var sql = Sql(); + + sql = isCount + ? sql.SelectCount() + : sql.Select(); + + sql + .From(); + return sql; } diff --git a/src/Umbraco.Core/Persistence/Repositories/RelationTypeRepository.cs b/src/Umbraco.Core/Persistence/Repositories/RelationTypeRepository.cs index b3ce9fa14d..db3bf84620 100644 --- a/src/Umbraco.Core/Persistence/Repositories/RelationTypeRepository.cs +++ b/src/Umbraco.Core/Persistence/Repositories/RelationTypeRepository.cs @@ -1,6 +1,7 @@ using System; using System.Collections.Generic; using System.Linq; +using NPoco; using Umbraco.Core.Logging; using Umbraco.Core.Models; using Umbraco.Core.Models.EntityBase; @@ -17,7 +18,7 @@ namespace Umbraco.Core.Persistence.Repositories /// /// Represents a repository for doing CRUD operations for /// - internal class RelationTypeRepository : PetaPocoRepositoryBase, IRelationTypeRepository + internal class RelationTypeRepository : NPocoRepositoryBase, IRelationTypeRepository { public RelationTypeRepository(IDatabaseUnitOfWork work, CacheHelper cache, ILogger logger, ISqlSyntaxProvider sqlSyntax, IMappingResolver mappingResolver) @@ -81,13 +82,19 @@ namespace Umbraco.Core.Persistence.Repositories #endregion - #region Overrides of PetaPocoRepositoryBase + #region Overrides of NPocoRepositoryBase - protected override Sql GetBaseQuery(bool isCount) + protected override Sql GetBaseQuery(bool isCount) { - var sql = new Sql(); - sql.Select(isCount ? "COUNT(*)" : "*") - .From(SqlSyntax); + var sql = Sql(); + + sql = isCount + ? sql.SelectCount() + : sql.Select(); + + sql + .From(); + return sql; } diff --git a/src/Umbraco.Core/Persistence/Repositories/ServerRegistrationRepository.cs b/src/Umbraco.Core/Persistence/Repositories/ServerRegistrationRepository.cs index 2926525f48..dd576ce899 100644 --- a/src/Umbraco.Core/Persistence/Repositories/ServerRegistrationRepository.cs +++ b/src/Umbraco.Core/Persistence/Repositories/ServerRegistrationRepository.cs @@ -1,6 +1,7 @@ using System; using System.Collections.Generic; using System.Linq; +using NPoco; using Umbraco.Core.Cache; using Umbraco.Core.Logging; using Umbraco.Core.Models; @@ -14,7 +15,7 @@ using Umbraco.Core.Persistence.UnitOfWork; namespace Umbraco.Core.Persistence.Repositories { - internal class ServerRegistrationRepository : PetaPocoRepositoryBase, IServerRegistrationRepository + internal class ServerRegistrationRepository : NPocoRepositoryBase, IServerRegistrationRepository { private readonly ICacheProvider _staticCache; @@ -59,11 +60,17 @@ namespace Umbraco.Core.Persistence.Repositories throw new NotSupportedException("This repository does not support this method"); } - protected override Sql GetBaseQuery(bool isCount) + protected override Sql GetBaseQuery(bool isCount) { - var sql = new Sql(); - sql.Select(isCount ? "COUNT(*)" : "*") - .From(SqlSyntax); + var sql = Sql(); + + sql = isCount + ? sql.SelectCount() + : sql.Select(); + + sql + .From(); + return sql; } diff --git a/src/Umbraco.Core/Persistence/Repositories/SimpleGetRepository.cs b/src/Umbraco.Core/Persistence/Repositories/SimpleGetRepository.cs index 2f0a2321d6..e5d941ba4b 100644 --- a/src/Umbraco.Core/Persistence/Repositories/SimpleGetRepository.cs +++ b/src/Umbraco.Core/Persistence/Repositories/SimpleGetRepository.cs @@ -1,6 +1,7 @@ using System; using System.Collections.Generic; using System.Linq; +using NPoco; using Umbraco.Core.Logging; using Umbraco.Core.Models.EntityBase; using Umbraco.Core.Persistence.Mappers; @@ -13,7 +14,7 @@ namespace Umbraco.Core.Persistence.Repositories /// /// Simple abstract ReadOnly repository used to simply have PerformGet and PeformGetAll with an underlying cache /// - internal abstract class SimpleGetRepository : PetaPocoRepositoryBase + internal abstract class SimpleGetRepository : NPocoRepositoryBase where TEntity : class, IAggregateRoot where TDto: class { @@ -56,11 +57,11 @@ namespace Umbraco.Core.Persistence.Repositories protected override IEnumerable PerformGetAll(params TId[] ids) { - var sql = new Sql().From(SqlSyntax); + var sql = Sql().From(); if (ids.Any()) { - sql.Where(GetWhereInClauseForGetAll(), new { ids = ids }); + sql.Where(GetWhereInClauseForGetAll(), new { /*ids =*/ ids }); } return Database.Fetch(sql).Select(ConvertToEntity); diff --git a/src/Umbraco.Core/Persistence/Repositories/TagRepository.cs b/src/Umbraco.Core/Persistence/Repositories/TagRepository.cs index add3f21729..df5cc4883f 100644 --- a/src/Umbraco.Core/Persistence/Repositories/TagRepository.cs +++ b/src/Umbraco.Core/Persistence/Repositories/TagRepository.cs @@ -2,6 +2,7 @@ using System.Collections.Generic; using System.Linq; using System.Text; +using NPoco; using Umbraco.Core.Logging; using Umbraco.Core.Models; using Umbraco.Core.Models.EntityBase; @@ -15,7 +16,7 @@ using Umbraco.Core.Persistence.UnitOfWork; namespace Umbraco.Core.Persistence.Repositories { - internal class TagRepository : PetaPocoRepositoryBase, ITagRepository + internal class TagRepository : NPocoRepositoryBase, ITagRepository { public TagRepository(IDatabaseUnitOfWork work, CacheHelper cache, ILogger logger, ISqlSyntaxProvider sqlSyntax, IMappingResolver mappingResolver) : base(work, cache, logger, sqlSyntax, mappingResolver) @@ -92,25 +93,14 @@ namespace Umbraco.Core.Persistence.Repositories } - protected override Sql GetBaseQuery(bool isCount) + protected override Sql GetBaseQuery(bool isCount) { - var sql = new Sql(); - if (isCount) - { - sql.Select("COUNT(*)").From(SqlSyntax); - } - else - { - return GetBaseQuery(); - } - return sql; + return isCount ? Sql().SelectCount().From() : GetBaseQuery(); } - private Sql GetBaseQuery() + private Sql GetBaseQuery() { - var sql = new Sql(); - sql.Select("*").From(SqlSyntax); - return sql; + return Sql().SelectAll().From(); } protected override string GetBaseWhereClause() @@ -165,60 +155,60 @@ namespace Umbraco.Core.Persistence.Repositories public TaggedEntity GetTaggedEntityByKey(Guid key) { - var sql = new Sql() + var sql = Sql() .Select("cmsTagRelationship.nodeId, cmsPropertyType.Alias, cmsPropertyType.id as propertyTypeId, cmsTags.tag, cmsTags.id as tagId, cmsTags." + SqlSyntax.GetQuotedColumnName("group")) - .From(SqlSyntax) - .InnerJoin(SqlSyntax) - .On(SqlSyntax, left => left.TagId, right => right.Id) - .InnerJoin(SqlSyntax) - .On(SqlSyntax, left => left.NodeId, right => right.NodeId) - .InnerJoin(SqlSyntax) - .On(SqlSyntax, left => left.Id, right => right.PropertyTypeId) - .InnerJoin(SqlSyntax) - .On(SqlSyntax, left => left.NodeId, right => right.NodeId) - .Where(SqlSyntax, dto => dto.UniqueId == key); + .From() + .InnerJoin() + .On(left => left.TagId, right => right.Id) + .InnerJoin() + .On(left => left.NodeId, right => right.NodeId) + .InnerJoin() + .On(left => left.Id, right => right.PropertyTypeId) + .InnerJoin() + .On(left => left.NodeId, right => right.NodeId) + .Where(dto => dto.UniqueId == key); return CreateTaggedEntityCollection(Database.Fetch(sql)).FirstOrDefault(); } public TaggedEntity GetTaggedEntityById(int id) { - var sql = new Sql() + var sql = Sql() .Select("cmsTagRelationship.nodeId, cmsPropertyType.Alias, cmsPropertyType.id as propertyTypeId, cmsTags.tag, cmsTags.id as tagId, cmsTags." + SqlSyntax.GetQuotedColumnName("group")) - .From(SqlSyntax) - .InnerJoin(SqlSyntax) - .On(SqlSyntax, left => left.TagId, right => right.Id) - .InnerJoin(SqlSyntax) - .On(SqlSyntax, left => left.NodeId, right => right.NodeId) - .InnerJoin(SqlSyntax) - .On(SqlSyntax, left => left.Id, right => right.PropertyTypeId) - .InnerJoin(SqlSyntax) - .On(SqlSyntax, left => left.NodeId, right => right.NodeId) - .Where(SqlSyntax, dto => dto.NodeId == id); + .From() + .InnerJoin() + .On(left => left.TagId, right => right.Id) + .InnerJoin() + .On(left => left.NodeId, right => right.NodeId) + .InnerJoin() + .On(left => left.Id, right => right.PropertyTypeId) + .InnerJoin() + .On(left => left.NodeId, right => right.NodeId) + .Where(dto => dto.NodeId == id); return CreateTaggedEntityCollection(Database.Fetch(sql)).FirstOrDefault(); } public IEnumerable GetTaggedEntitiesByTagGroup(TaggableObjectTypes objectType, string tagGroup) { - var sql = new Sql() + var sql = Sql() .Select("cmsTagRelationship.nodeId, cmsPropertyType.Alias, cmsPropertyType.id as propertyTypeId, cmsTags.tag, cmsTags.id as tagId, cmsTags." + SqlSyntax.GetQuotedColumnName("group")) - .From(SqlSyntax) - .InnerJoin(SqlSyntax) - .On(SqlSyntax, left => left.TagId, right => right.Id) - .InnerJoin(SqlSyntax) - .On(SqlSyntax, left => left.NodeId, right => right.NodeId) - .InnerJoin(SqlSyntax) - .On(SqlSyntax, left => left.Id, right => right.PropertyTypeId) - .InnerJoin(SqlSyntax) - .On(SqlSyntax, left => left.NodeId, right => right.NodeId) - .Where(SqlSyntax, dto => dto.Group == tagGroup); + .From() + .InnerJoin() + .On(left => left.TagId, right => right.Id) + .InnerJoin() + .On(left => left.NodeId, right => right.NodeId) + .InnerJoin() + .On(left => left.Id, right => right.PropertyTypeId) + .InnerJoin() + .On(left => left.NodeId, right => right.NodeId) + .Where(dto => dto.Group == tagGroup); if (objectType != TaggableObjectTypes.All) { var nodeObjectType = GetNodeObjectType(objectType); sql = sql - .Where(SqlSyntax, dto => dto.NodeObjectType == nodeObjectType); + .Where(dto => dto.NodeObjectType == nodeObjectType); } return CreateTaggedEntityCollection( @@ -227,29 +217,29 @@ namespace Umbraco.Core.Persistence.Repositories public IEnumerable GetTaggedEntitiesByTag(TaggableObjectTypes objectType, string tag, string tagGroup = null) { - var sql = new Sql() + var sql = Sql() .Select("cmsTagRelationship.nodeId, cmsPropertyType.Alias, cmsPropertyType.id as propertyTypeId, cmsTags.tag, cmsTags.id as tagId, cmsTags." + SqlSyntax.GetQuotedColumnName("group")) - .From(SqlSyntax) - .InnerJoin(SqlSyntax) - .On(SqlSyntax, left => left.TagId, right => right.Id) - .InnerJoin(SqlSyntax) - .On(SqlSyntax, left => left.NodeId, right => right.NodeId) - .InnerJoin(SqlSyntax) - .On(SqlSyntax, left => left.Id, right => right.PropertyTypeId) - .InnerJoin(SqlSyntax) - .On(SqlSyntax, left => left.NodeId, right => right.NodeId) - .Where(SqlSyntax, dto => dto.Tag == tag); + .From() + .InnerJoin() + .On(left => left.TagId, right => right.Id) + .InnerJoin() + .On(left => left.NodeId, right => right.NodeId) + .InnerJoin() + .On(left => left.Id, right => right.PropertyTypeId) + .InnerJoin() + .On(left => left.NodeId, right => right.NodeId) + .Where(dto => dto.Tag == tag); if (objectType != TaggableObjectTypes.All) { var nodeObjectType = GetNodeObjectType(objectType); sql = sql - .Where(SqlSyntax, dto => dto.NodeObjectType == nodeObjectType); + .Where(dto => dto.NodeObjectType == nodeObjectType); } if (tagGroup.IsNullOrWhiteSpace() == false) { - sql = sql.Where(SqlSyntax, dto => dto.Group == tagGroup); + sql = sql.Where(dto => dto.Group == tagGroup); } return CreateTaggedEntityCollection( @@ -275,12 +265,12 @@ namespace Umbraco.Core.Persistence.Repositories var sql = GetTagsQuerySelect(true); sql = ApplyRelationshipJoinToTagsQuery(sql); - + if (objectType != TaggableObjectTypes.All) { var nodeObjectType = GetNodeObjectType(objectType); sql = sql - .Where(SqlSyntax, dto => dto.NodeObjectType == nodeObjectType); + .Where(dto => dto.NodeObjectType == nodeObjectType); } sql = ApplyGroupFilterToTagsQuery(sql, group); @@ -297,7 +287,7 @@ namespace Umbraco.Core.Persistence.Repositories sql = ApplyRelationshipJoinToTagsQuery(sql); sql = sql - .Where(SqlSyntax, dto => dto.NodeId == contentId); + .Where(dto => dto.NodeId == contentId); sql = ApplyGroupFilterToTagsQuery(sql, group); @@ -311,7 +301,7 @@ namespace Umbraco.Core.Persistence.Repositories sql = ApplyRelationshipJoinToTagsQuery(sql); sql = sql - .Where(SqlSyntax, dto => dto.UniqueId == contentId); + .Where(dto => dto.UniqueId == contentId); sql = ApplyGroupFilterToTagsQuery(sql, group); @@ -325,10 +315,10 @@ namespace Umbraco.Core.Persistence.Repositories sql = ApplyRelationshipJoinToTagsQuery(sql); sql = sql - .InnerJoin(SqlSyntax) - .On(SqlSyntax, left => left.Id, right => right.PropertyTypeId) - .Where(SqlSyntax, dto => dto.NodeId == contentId) - .Where(SqlSyntax, dto => dto.Alias == propertyTypeAlias); + .InnerJoin() + .On(left => left.Id, right => right.PropertyTypeId) + .Where(dto => dto.NodeId == contentId) + .Where(dto => dto.Alias == propertyTypeAlias); sql = ApplyGroupFilterToTagsQuery(sql, group); @@ -342,19 +332,19 @@ namespace Umbraco.Core.Persistence.Repositories sql = ApplyRelationshipJoinToTagsQuery(sql); sql = sql - .InnerJoin(SqlSyntax) - .On(SqlSyntax, left => left.Id, right => right.PropertyTypeId) - .Where(SqlSyntax, dto => dto.UniqueId == contentId) - .Where(SqlSyntax, dto => dto.Alias == propertyTypeAlias); + .InnerJoin() + .On(left => left.Id, right => right.PropertyTypeId) + .Where(dto => dto.UniqueId == contentId) + .Where(dto => dto.Alias == propertyTypeAlias); sql = ApplyGroupFilterToTagsQuery(sql, group); return ExecuteTagsQuery(sql); } - private Sql GetTagsQuerySelect(bool withGrouping = false) + private Sql GetTagsQuerySelect(bool withGrouping = false) { - var sql = new Sql(); + var sql = Sql(); if (withGrouping) { @@ -368,31 +358,31 @@ namespace Umbraco.Core.Persistence.Repositories return sql; } - private Sql ApplyRelationshipJoinToTagsQuery(Sql sql) + private Sql ApplyRelationshipJoinToTagsQuery(Sql sql) { return sql - .From(SqlSyntax) - .InnerJoin(SqlSyntax) - .On(SqlSyntax, left => left.TagId, right => right.Id) - .InnerJoin(SqlSyntax) - .On(SqlSyntax, left => left.NodeId, right => right.NodeId) - .InnerJoin(SqlSyntax) - .On(SqlSyntax, left => left.NodeId, right => right.NodeId); + .From() + .InnerJoin() + .On(left => left.TagId, right => right.Id) + .InnerJoin() + .On(left => left.NodeId, right => right.NodeId) + .InnerJoin() + .On(left => left.NodeId, right => right.NodeId); } - private Sql ApplyGroupFilterToTagsQuery(Sql sql, string group) + private Sql ApplyGroupFilterToTagsQuery(Sql sql, string group) { - if (@group.IsNullOrWhiteSpace() == false) + if (group.IsNullOrWhiteSpace() == false) { - sql = sql.Where(SqlSyntax, dto => dto.Group == group); + sql = sql.Where(dto => dto.Group == group); } return sql; } - private Sql ApplyGroupByToTagsQuery(Sql sql) + private Sql ApplyGroupByToTagsQuery(Sql sql) { - return sql.GroupBy(new string[] { "cmsTags.id", "cmsTags.tag", "cmsTags." + SqlSyntax.GetQuotedColumnName("group") + @"" }); + return sql.GroupBy("cmsTags.id", "cmsTags.tag", "cmsTags." + SqlSyntax.GetQuotedColumnName("group") + @""); } private IEnumerable ExecuteTagsQuery(Sql sql) @@ -409,7 +399,7 @@ namespace Umbraco.Core.Persistence.Repositories /// /// The tags to assign /// - /// If set to true, this will replace all tags with the given tags, + /// If set to true, this will replace all tags with the given tags, /// if false this will append the tags that already exist for the content item /// /// @@ -436,8 +426,8 @@ namespace Umbraco.Core.Persistence.Repositories } //ok so now we're actually assigning tags... - //NOTE: There's some very clever logic in the umbraco.cms.businesslogic.Tags.Tag to insert tags where they don't exist, - // and assign where they don't exist which we've borrowed here. The queries are pretty zany but work, otherwise we'll end up + //NOTE: There's some very clever logic in the umbraco.cms.businesslogic.Tags.Tag to insert tags where they don't exist, + // and assign where they don't exist which we've borrowed here. The queries are pretty zany but work, otherwise we'll end up // with quite a few additional queries. //do all this in one transaction @@ -522,7 +512,7 @@ namespace Umbraco.Core.Persistence.Repositories public void ClearTagsFromProperty(int contentId, int propertyTypeId) { - Database.Execute("DELETE FROM cmsTagRelationship WHERE nodeId = @nodeId AND propertyTypeId = @propertyTypeId", + Database.Execute("DELETE FROM cmsTagRelationship WHERE nodeId = @nodeId AND propertyTypeId = @propertyTypeId", new { nodeId = contentId, propertyTypeId = propertyTypeId }); } @@ -549,18 +539,19 @@ namespace Umbraco.Core.Persistence.Repositories /// /// This is a clever way to produce an SQL statement like this: - /// - /// (select 'Spacesdd' as Tag, 'default' as [Group] - /// union + /// + /// (select 'Spacesdd' as Tag, 'default' as [Group] + /// union /// select 'Cool' as Tag, 'default' as [Group] /// ) as TagSet - /// - /// This allows us to use the tags to be inserted as a temporary in memory table. + /// + /// This allows us to use the tags to be inserted as a temporary in memory table. /// /// /// private string GetTagSet(IEnumerable tagsToInsert) { + // fixme.npoco //TODO: Fix this query, since this is going to be basically a unique query each time, this will cause some mem usage in peta poco, // and surely there's a nicer way! //TODO: When we fix, be sure to remove the @ symbol escape @@ -568,7 +559,7 @@ namespace Umbraco.Core.Persistence.Repositories var array = tagsToInsert .Select(tag => string.Format("select '{0}' as Tag, '{1}' as " + SqlSyntax.GetQuotedColumnName("group") + @"", - PetaPocoExtensions.EscapeAtSymbols(tag.Text.Replace("'", "''")), tag.Group)) + NPocoDatabaseExtensions.EscapeAtSymbols(tag.Text.Replace("'", "''")), tag.Group)) .ToArray(); return "(" + string.Join(" union ", array).Replace(" ", " ") + ") as TagSet"; } diff --git a/src/Umbraco.Core/Persistence/Repositories/TaskRepository.cs b/src/Umbraco.Core/Persistence/Repositories/TaskRepository.cs index c2793dcc1b..f87dacc911 100644 --- a/src/Umbraco.Core/Persistence/Repositories/TaskRepository.cs +++ b/src/Umbraco.Core/Persistence/Repositories/TaskRepository.cs @@ -2,6 +2,7 @@ using System; using System.Collections.Generic; using System.Linq; using AutoMapper; +using NPoco; using Umbraco.Core.Logging; using Umbraco.Core.Models; using Umbraco.Core.Models.EntityBase; @@ -14,7 +15,7 @@ using Umbraco.Core.Persistence.UnitOfWork; namespace Umbraco.Core.Persistence.Repositories { - internal class TaskRepository : PetaPocoRepositoryBase, ITaskRepository + internal class TaskRepository : NPocoRepositoryBase, ITaskRepository { public TaskRepository(IDatabaseUnitOfWork work, CacheHelper cache, ILogger logger, ISqlSyntaxProvider sqlSyntax, IMappingResolver mappingResolver) : base(work, cache, logger, sqlSyntax, mappingResolver) @@ -26,7 +27,7 @@ namespace Umbraco.Core.Persistence.Repositories var sql = GetBaseQuery(false); sql.Where(GetBaseWhereClause(), new { Id = id }); - var taskDto = Database.Fetch(sql).FirstOrDefault(); + var taskDto = Database.Fetch(sql).FirstOrDefault(); if (taskDto == null) return null; @@ -45,7 +46,7 @@ namespace Umbraco.Core.Persistence.Repositories } var factory = new TaskFactory(); - var dtos = Database.Fetch(sql); + var dtos = Database.Fetch(sql); return dtos.Select(factory.BuildEntity); } @@ -56,34 +57,24 @@ namespace Umbraco.Core.Persistence.Repositories var sql = translator.Translate(); var factory = new TaskFactory(); - var dtos = Database.Fetch(sql); + var dtos = Database.Fetch(sql); return dtos.Select(factory.BuildEntity); } - protected override Sql GetBaseQuery(bool isCount) + protected override Sql GetBaseQuery(bool isCount) { - var sql = new Sql(); - if (isCount) - { - sql.Select("COUNT(*)").From(SqlSyntax); - } - else - { - return GetBaseQuery(); - } - return sql; + return isCount ? Sql().SelectCount().From() : GetBaseQuery(); } - private Sql GetBaseQuery() + private Sql GetBaseQuery() { - var sql = new Sql(); - sql.Select("cmsTask.closed,cmsTask.id,cmsTask.taskTypeId,cmsTask.nodeId,cmsTask.parentUserId,cmsTask.userId,cmsTask." + SqlSyntax.GetQuotedColumnName("DateTime") + ",cmsTask.Comment,cmsTaskType.id, cmsTaskType.alias") - .From(SqlSyntax) - .InnerJoin(SqlSyntax) - .On(SqlSyntax, left => left.TaskTypeId, right => right.Id) - .InnerJoin(SqlSyntax) - .On(SqlSyntax, left => left.NodeId, right => right.NodeId); - return sql; + return Sql() + .Select("cmsTask.closed,cmsTask.id,cmsTask.taskTypeId,cmsTask.nodeId,cmsTask.parentUserId,cmsTask.userId,cmsTask." + SqlSyntax.GetQuotedColumnName("DateTime") + ",cmsTask.Comment,cmsTaskType.id, cmsTaskType.alias") + .From() + .InnerJoin() + .On(left => left.TaskTypeId, right => right.Id) + .InnerJoin() + .On(left => left.NodeId, right => right.NodeId); } protected override string GetBaseWhereClause() @@ -95,7 +86,7 @@ namespace Umbraco.Core.Persistence.Repositories { var list = new List { - "DELETE FROM cmsTask WHERE id = @Id" + "DELETE FROM cmsTask WHERE id = @Id" }; return list; } @@ -147,21 +138,21 @@ namespace Umbraco.Core.Persistence.Repositories var sql = GetGetTasksQuery(assignedUser, ownerUser, taskTypeAlias, includeClosed); if (itemId.HasValue) { - sql.Where(SqlSyntax, dto => dto.NodeId == itemId.Value); + sql.Where(dto => dto.NodeId == itemId.Value); } - var dtos = Database.Fetch(sql); + var dtos = Database.Fetch(sql); var factory = new TaskFactory(); return dtos.Select(factory.BuildEntity); } - private Sql GetGetTasksQuery(int? assignedUser = null, int? ownerUser = null, string taskTypeAlias = null, bool includeClosed = false) + private Sql GetGetTasksQuery(int? assignedUser = null, int? ownerUser = null, string taskTypeAlias = null, bool includeClosed = false) { var sql = GetBaseQuery(false); if (includeClosed == false) { - sql.Where(SqlSyntax, dto => dto.Closed == false); + sql.Where(dto => dto.Closed == false); } if (taskTypeAlias.IsNullOrWhiteSpace() == false) { @@ -169,11 +160,11 @@ namespace Umbraco.Core.Persistence.Repositories } if (ownerUser.HasValue) { - sql.Where(SqlSyntax, dto => dto.ParentUserId == ownerUser.Value); + sql.Where(dto => dto.ParentUserId == ownerUser.Value); } if (assignedUser.HasValue) { - sql.Where(SqlSyntax, dto => dto.UserId == assignedUser.Value); + sql.Where(dto => dto.UserId == assignedUser.Value); } return sql; } diff --git a/src/Umbraco.Core/Persistence/Repositories/TaskTypeRepository.cs b/src/Umbraco.Core/Persistence/Repositories/TaskTypeRepository.cs index aef8debd1f..cc26450962 100644 --- a/src/Umbraco.Core/Persistence/Repositories/TaskTypeRepository.cs +++ b/src/Umbraco.Core/Persistence/Repositories/TaskTypeRepository.cs @@ -1,6 +1,7 @@ using System; using System.Collections.Generic; using System.Linq; +using NPoco; using Umbraco.Core.Logging; using Umbraco.Core.Models; using Umbraco.Core.Models.Rdbms; @@ -12,7 +13,7 @@ using Umbraco.Core.Persistence.UnitOfWork; namespace Umbraco.Core.Persistence.Repositories { - internal class TaskTypeRepository : PetaPocoRepositoryBase, ITaskTypeRepository + internal class TaskTypeRepository : NPocoRepositoryBase, ITaskTypeRepository { public TaskTypeRepository(IDatabaseUnitOfWork work, CacheHelper cache, ILogger logger, ISqlSyntaxProvider sqlSyntax, IMappingResolver mappingResolver) : base(work, cache, logger, sqlSyntax, mappingResolver) @@ -58,11 +59,9 @@ namespace Umbraco.Core.Persistence.Repositories return dtos.Select(factory.BuildEntity); } - protected override Sql GetBaseQuery(bool isCount) + protected override Sql GetBaseQuery(bool isCount) { - var sql = new Sql(); - sql.Select("*").From(SqlSyntax); - return sql; + return Sql().SelectAll().From(); } protected override string GetBaseWhereClause() diff --git a/src/Umbraco.Core/Persistence/Repositories/TemplateRepository.cs b/src/Umbraco.Core/Persistence/Repositories/TemplateRepository.cs index 32f5f63d98..e4379119c2 100644 --- a/src/Umbraco.Core/Persistence/Repositories/TemplateRepository.cs +++ b/src/Umbraco.Core/Persistence/Repositories/TemplateRepository.cs @@ -4,6 +4,7 @@ using System.Globalization; using System.IO; using System.Linq; using System.Text; +using NPoco; using Umbraco.Core.Cache; using Umbraco.Core.Configuration; using Umbraco.Core.Configuration.UmbracoSettings; @@ -27,7 +28,7 @@ namespace Umbraco.Core.Persistence.Repositories /// /// Represents the Template Repository /// - internal class TemplateRepository : PetaPocoRepositoryBase, ITemplateRepository + internal class TemplateRepository : NPocoRepositoryBase, ITemplateRepository { private readonly IFileSystem _masterpagesFileSystem; private readonly IFileSystem _viewsFileSystem; @@ -75,14 +76,14 @@ namespace Umbraco.Core.Persistence.Repositories } else { - sql.Where(SqlSyntax, x => x.NodeObjectType == NodeObjectTypeId); + sql.Where(x => x.NodeObjectType == NodeObjectTypeId); } - var dtos = Database.Fetch(sql); + var dtos = Database.Fetch(sql); if (dtos.Count == 0) return Enumerable.Empty(); - //look up the simple template definitions that have a master template assigned, this is used + //look up the simple template definitions that have a master template assigned, this is used // later to populate the template item's properties var childIds = (ids.Any() ? GetAxisDefinitions(dtos.ToArray()) @@ -92,7 +93,7 @@ namespace Umbraco.Core.Persistence.Repositories ParentId = x.NodeDto.ParentId, Name = x.Alias })).ToArray(); - + return dtos.Select(d => MapFromDto(d, childIds)); } @@ -102,11 +103,11 @@ namespace Umbraco.Core.Persistence.Repositories var translator = new SqlTranslator(sqlClause, query); var sql = translator.Translate(); - var dtos = Database.Fetch(sql); + var dtos = Database.Fetch(sql); if (dtos.Count == 0) return Enumerable.Empty(); - //look up the simple template definitions that have a master template assigned, this is used + //look up the simple template definitions that have a master template assigned, this is used // later to populate the template item's properties var childIds = GetAxisDefinitions(dtos.ToArray()).ToArray(); @@ -115,16 +116,23 @@ namespace Umbraco.Core.Persistence.Repositories #endregion - #region Overrides of PetaPocoRepositoryBase + #region Overrides of NPocoRepositoryBase - protected override Sql GetBaseQuery(bool isCount) + protected override Sql GetBaseQuery(bool isCount) { - var sql = new Sql(); - sql.Select(isCount ? "COUNT(*)" : "*") - .From(SqlSyntax) - .InnerJoin(SqlSyntax) - .On(SqlSyntax, left => left.NodeId, right => right.NodeId) - .Where(SqlSyntax, x => x.NodeObjectType == NodeObjectTypeId); + var sql = Sql(); + + sql = isCount + ? sql.SelectCount() + : sql.Select(r => + r.Select()); + + sql + .From() + .InnerJoin() + .On(left => left.NodeId, right => right.NodeId) + .Where(x => x.NodeObjectType == NodeObjectTypeId); + return sql; } @@ -166,7 +174,7 @@ namespace Umbraco.Core.Persistence.Repositories //Create the (base) node data - umbracoNode var nodeDto = dto.NodeDto; nodeDto.Path = "-1," + dto.NodeDto.NodeId; - var o = Database.IsNew(nodeDto) ? Convert.ToInt32(Database.Insert(nodeDto)) : Database.Update(nodeDto); + var o = Database.IsNew(nodeDto) ? Convert.ToInt32(Database.Insert(nodeDto)) : Database.Update(nodeDto); //Update with new correct path var parent = Get(template.MasterTemplateId.Value); @@ -325,23 +333,23 @@ namespace Umbraco.Core.Persistence.Repositories { var masterpageName = string.Concat(entity.Alias, ".master"); _masterpagesFileSystem.DeleteFile(masterpageName); - } + } } #endregion private IEnumerable GetAxisDefinitions(params TemplateDto[] templates) { - //look up the simple template definitions that have a master template assigned, this is used + //look up the simple template definitions that have a master template assigned, this is used // later to populate the template item's properties - var childIdsSql = new Sql() + var childIdsSql = Sql() .Select("nodeId,alias,parentID") - .From(SqlSyntax) - .InnerJoin(SqlSyntax) - .On(SqlSyntax, dto => dto.NodeId, dto => dto.NodeId) + .From() + .InnerJoin() + .On(dto => dto.NodeId, dto => dto.NodeId) //lookup axis's .Where("umbracoNode." + SqlSyntax.GetQuotedColumnName("id") + " IN (@parentIds) OR umbracoNode.parentID IN (@childIds)", - new {parentIds = templates.Select(x => x.NodeDto.ParentId), childIds = templates.Select(x => x.NodeId)}); + new {parentIds = templates.Select(x => x.NodeDto.ParentId), childIds = templates.Select(x => x.NodeId)}); var childIds = Database.Fetch(childIdsSql) .Select(x => new UmbracoEntity @@ -571,7 +579,7 @@ namespace Umbraco.Core.Persistence.Repositories /// [Obsolete("Use GetDescendants instead")] public TemplateNode GetTemplateNode(string alias) - { + { //first get all template objects var allTemplates = base.GetAll().ToArray(); @@ -580,7 +588,7 @@ namespace Umbraco.Core.Persistence.Repositories { return null; } - + var top = selfTemplate; while (top.MasterTemplateAlias.IsNullOrWhiteSpace() == false) { @@ -631,16 +639,16 @@ namespace Umbraco.Core.Persistence.Repositories } /// - /// This checks what the default rendering engine is set in config but then also ensures that there isn't already - /// a template that exists in the opposite rendering engine's template folder, then returns the appropriate + /// This checks what the default rendering engine is set in config but then also ensures that there isn't already + /// a template that exists in the opposite rendering engine's template folder, then returns the appropriate /// rendering engine to use. - /// + /// /// /// /// The reason this is required is because for example, if you have a master page file already existing under ~/masterpages/Blah.aspx - /// and then you go to create a template in the tree called Blah and the default rendering engine is MVC, it will create a Blah.cshtml - /// empty template in ~/Views. This means every page that is using Blah will go to MVC and render an empty page. - /// This is mostly related to installing packages since packages install file templates to the file system and then create the + /// and then you go to create a template in the tree called Blah and the default rendering engine is MVC, it will create a Blah.cshtml + /// empty template in ~/Views. This means every page that is using Blah will go to MVC and render an empty page. + /// This is mostly related to installing packages since packages install file templates to the file system and then create the /// templates in business logic. Without this, it could cause the wrong rendering engine to be used for a package. /// public RenderingEngine DetermineTemplateRenderingEngine(ITemplate template) @@ -748,7 +756,7 @@ namespace Umbraco.Core.Persistence.Repositories /// private void EnsureValidAlias(ITemplate template) { - //ensure unique alias + //ensure unique alias template.Alias = template.Alias.ToCleanString(CleanStringType.UnderscoreAlias); if (template.Alias.Length > 100) @@ -762,7 +770,7 @@ namespace Umbraco.Core.Persistence.Repositories private bool AliasAlreadExists(ITemplate template) { - var sql = GetBaseQuery(true).Where(SqlSyntax, x => x.Alias.InvariantEquals(template.Alias) && x.NodeId != template.Id); + var sql = GetBaseQuery(true).Where(x => x.Alias.InvariantEquals(template.Alias) && x.NodeId != template.Id); var count = Database.ExecuteScalar(sql); return count > 0; } diff --git a/src/Umbraco.Core/Persistence/Repositories/TupleExtensions.cs b/src/Umbraco.Core/Persistence/Repositories/TupleExtensions.cs new file mode 100644 index 0000000000..a944e9e497 --- /dev/null +++ b/src/Umbraco.Core/Persistence/Repositories/TupleExtensions.cs @@ -0,0 +1,19 @@ +using System; +using System.Collections.Generic; +using System.Linq; + +namespace Umbraco.Core.Persistence.Repositories +{ + static class TupleExtensions + { + public static IEnumerable Map(this Tuple, List> t, Func relator) + { + return t.Item1.Zip(t.Item2, relator); + } + + public static IEnumerable Map(this Tuple, List, List> t, Func relator) + { + return t.Item1.Zip(t.Item2, t.Item3, relator); + } + } +} diff --git a/src/Umbraco.Core/Persistence/Repositories/UserRepository.cs b/src/Umbraco.Core/Persistence/Repositories/UserRepository.cs index e7d310e550..72333289c7 100644 --- a/src/Umbraco.Core/Persistence/Repositories/UserRepository.cs +++ b/src/Umbraco.Core/Persistence/Repositories/UserRepository.cs @@ -2,6 +2,7 @@ using System; using System.Collections.Generic; using System.Linq; using System.Linq.Expressions; +using NPoco; using Umbraco.Core; using Umbraco.Core.Logging; using Umbraco.Core.Models; @@ -12,7 +13,6 @@ using Umbraco.Core.Models.Rdbms; using Umbraco.Core.Persistence.Factories; using Umbraco.Core.Persistence.Mappers; using Umbraco.Core.Persistence.Querying; -using Umbraco.Core.Persistence.Relators; using Umbraco.Core.Persistence.SqlSyntax; using Umbraco.Core.Persistence.UnitOfWork; @@ -21,7 +21,7 @@ namespace Umbraco.Core.Persistence.Repositories /// /// Represents the UserRepository for doing CRUD operations for /// - internal class UserRepository : PetaPocoRepositoryBase, IUserRepository + internal class UserRepository : NPocoRepositoryBase, IUserRepository { private readonly IUserTypeRepository _userTypeRepository; private readonly CacheHelper _cacheHelper; @@ -40,8 +40,10 @@ namespace Umbraco.Core.Persistence.Repositories var sql = GetBaseQuery(false); sql.Where(GetBaseWhereClause(), new { Id = id }); - var dto = Database.Fetch(new UserSectionRelator().Map, sql).FirstOrDefault(); - + var dto = Database + .FetchOneToMany(x => x.User2AppDtos, sql) + .FirstOrDefault(); + if (dto == null) return null; @@ -60,50 +62,49 @@ namespace Umbraco.Core.Persistence.Repositories { sql.Where("umbracoUser.id in (@ids)", new {ids = ids}); } - - return ConvertFromDtos(Database.Fetch(new UserSectionRelator().Map, sql)) - .ToArray(); // important so we don't iterate twice, if we don't do this we can end up with null values in cache if we were caching. + + var dtos = Database + .FetchOneToMany(x => x.User2AppDtos, sql); + + return ConvertFromDtos(dtos).ToArray(); // do it now and do it once, else can end up with nulls in cache } - + protected override IEnumerable PerformGetByQuery(IQuery query) { var sqlClause = GetBaseQuery(false); var translator = new SqlTranslator(sqlClause, query); var sql = translator.Translate(); - var dtos = Database.Fetch(new UserSectionRelator().Map, sql) + var dtos = Database + .FetchOneToMany(x => x.User2AppDtos, sql) .DistinctBy(x => x.Id); - return ConvertFromDtos(dtos) - .ToArray(); // important so we don't iterate twice, if we don't do this we can end up with null values in cache if we were caching. + return ConvertFromDtos(dtos).ToArray(); // do it now and do it once, else can end up with nulls in cache } - + #endregion - #region Overrides of PetaPocoRepositoryBase - - protected override Sql GetBaseQuery(bool isCount) + #region Overrides of NPocoRepositoryBase + + protected override Sql GetBaseQuery(bool isCount) { - var sql = new Sql(); if (isCount) - { - sql.Select("COUNT(*)").From(SqlSyntax); - } - else - { - return GetBaseQuery("*"); - } - return sql; + return Sql().SelectCount().From(); + + return Sql() + .Select(r => r.Select(referenceName: "User2AppDtos")) + .From() + .LeftJoin() + .On(left => left.Id, right => right.UserId); } - private Sql GetBaseQuery(string columns) + private Sql GetBaseQuery(string columns) { - var sql = new Sql(); - sql.Select(columns) - .From(SqlSyntax) - .LeftJoin(SqlSyntax) - .On(SqlSyntax, left => left.Id, right => right.UserId); - return sql; + return Sql() + .Select(columns) + .From() + .LeftJoin() + .On(left => left.Id, right => right.UserId); } @@ -113,7 +114,7 @@ namespace Umbraco.Core.Persistence.Repositories } protected override IEnumerable GetDeleteClauses() - { + { var list = new List { "DELETE FROM cmsTask WHERE userId = @Id", @@ -131,7 +132,7 @@ namespace Umbraco.Core.Persistence.Repositories { get { throw new NotImplementedException(); } } - + protected override void PersistNewItem(IUser entity) { var userFactory = new UserFactory(entity.UserType); @@ -141,7 +142,7 @@ namespace Umbraco.Core.Persistence.Repositories { entity.SecurityStamp = Guid.NewGuid().ToString(); } - + var userDto = userFactory.BuildDto(entity); var id = Convert.ToInt32(Database.Insert(userDto)); @@ -181,8 +182,8 @@ namespace Umbraco.Core.Persistence.Repositories {"startStructureID", "StartContentId"}, {"startMediaID", "StartMediaId"}, {"userName", "Name"}, - {"userLogin", "Username"}, - {"userEmail", "Email"}, + {"userLogin", "Username"}, + {"userEmail", "Email"}, {"userLanguage", "Language"}, {"securityStampToken", "SecurityStamp"}, {"lastLockoutDate", "LastLockoutDate"}, @@ -217,7 +218,7 @@ namespace Umbraco.Core.Persistence.Repositories { Database.Update(userDto, changedCols); } - + //update the sections if they've changed var user = (User)entity; if (user.IsPropertyDirty("AllowedSections")) @@ -237,7 +238,7 @@ namespace Umbraco.Core.Persistence.Repositories //if something has been added then insert it if (user.AddedSections.Contains(sectionDto.AppAlias)) { - //we need to insert since this was added + //we need to insert since this was added Database.Insert(sectionDto); } else @@ -248,7 +249,7 @@ namespace Umbraco.Core.Persistence.Repositories } } - + } entity.ResetDirtyProperties(); @@ -272,11 +273,10 @@ namespace Umbraco.Core.Persistence.Repositories public bool Exists(string username) { - var sql = new Sql(); - - sql.Select("COUNT(*)") - .From(SqlSyntax) - .Where(SqlSyntax, x => x.UserName == username); + var sql = Sql() + .SelectCount() + .From() + .Where(x => x.UserName == username); return Database.ExecuteScalar(sql) > 0; } @@ -301,7 +301,10 @@ namespace Umbraco.Core.Persistence.Repositories innerSql.Where("umbracoUser2app.app = " + SqlSyntax.GetQuotedValue(sectionAlias)); sql.Where(string.Format("umbracoUser.id IN ({0})", innerSql.SQL)); - return ConvertFromDtos(Database.Fetch(new UserSectionRelator().Map, sql)); + var dtos = Database + .FetchOneToMany(x => x.User2AppDtos, sql); + + return ConvertFromDtos(dtos); } /// @@ -316,14 +319,15 @@ namespace Umbraco.Core.Persistence.Repositories /// /// /// - /// The query supplied will ONLY work with data specifically on the umbracoUser table because we are using PetaPoco paging (SQL paging) + /// The query supplied will ONLY work with data specifically on the umbracoUser table because we are using NPoco paging (SQL paging) /// public IEnumerable GetPagedResultsByQuery(IQuery query, int pageIndex, int pageSize, out int totalRecords, Expression> orderBy) { - if (orderBy == null) throw new ArgumentNullException("orderBy"); + if (orderBy == null) throw new ArgumentNullException(nameof(orderBy)); - var sql = new Sql(); - sql.Select("*").From(SqlSyntax); + var sql = Sql() + .SelectAll() + .From(); Sql resultQuery; if (query != null) @@ -364,13 +368,13 @@ namespace Umbraco.Core.Persistence.Repositories //now we need to ensure this result is also ordered by the same order by clause return result.OrderBy(orderBy.Compile()); } - + /// /// Returns permissions for a given user for any number of nodes /// /// /// - /// + /// public IEnumerable GetUserPermissionsForEntities(int userId, params int[] entityIds) { var repo = new PermissionRepository(UnitOfWork, _cacheHelper, SqlSyntax); @@ -410,7 +414,7 @@ namespace Umbraco.Core.Persistence.Repositories var allUserTypes = userTypeIds.Length == 0 ? Enumerable.Empty() : _userTypeRepository.GetAll(userTypeIds); return dtos.Select(dto => - { + { var userType = allUserTypes.Single(x => x.Id == dto.Type); var userFactory = new UserFactory(userType); diff --git a/src/Umbraco.Core/Persistence/Repositories/UserTypeRepository.cs b/src/Umbraco.Core/Persistence/Repositories/UserTypeRepository.cs index df3ab9f669..497eef779b 100644 --- a/src/Umbraco.Core/Persistence/Repositories/UserTypeRepository.cs +++ b/src/Umbraco.Core/Persistence/Repositories/UserTypeRepository.cs @@ -1,6 +1,7 @@ using System; using System.Collections.Generic; using System.Linq; +using NPoco; using Umbraco.Core.Logging; using Umbraco.Core.Models.Membership; using Umbraco.Core.Models.Rdbms; @@ -16,7 +17,7 @@ namespace Umbraco.Core.Persistence.Repositories /// /// Represents the UserTypeRepository for doing CRUD operations for /// - internal class UserTypeRepository : PetaPocoRepositoryBase, IUserTypeRepository + internal class UserTypeRepository : NPocoRepositoryBase, IUserTypeRepository { public UserTypeRepository(IDatabaseUnitOfWork work, CacheHelper cache, ILogger logger, ISqlSyntaxProvider sqlSyntax, IMappingResolver mappingResolver) : base(work, cache, logger, sqlSyntax, mappingResolver) @@ -35,14 +36,14 @@ namespace Umbraco.Core.Persistence.Repositories var userTypeFactory = new UserTypeFactory(); var sql = GetBaseQuery(false); - + if (ids.Any()) { sql.Where("umbracoUserType.id in (@ids)", new { ids = ids }); } else { - sql.Where(SqlSyntax, x => x.Id >= 0); + sql.Where(x => x.Id >= 0); } var dtos = Database.Fetch(sql); @@ -63,13 +64,19 @@ namespace Umbraco.Core.Persistence.Repositories #endregion - #region Overrides of PetaPocoRepositoryBase + #region Overrides of NPocoRepositoryBase - protected override Sql GetBaseQuery(bool isCount) + protected override Sql GetBaseQuery(bool isCount) { - var sql = new Sql(); - sql.Select(isCount ? "COUNT(*)" : "*") - .From(SqlSyntax); + var sql = Sql(); + + sql = isCount + ? sql.SelectCount() + : sql.Select(); + + sql + .From(); + return sql; } diff --git a/src/Umbraco.Core/Persistence/Repositories/VersionableRepositoryBase.cs b/src/Umbraco.Core/Persistence/Repositories/VersionableRepositoryBase.cs index 86de4d7052..62d7259065 100644 --- a/src/Umbraco.Core/Persistence/Repositories/VersionableRepositoryBase.cs +++ b/src/Umbraco.Core/Persistence/Repositories/VersionableRepositoryBase.cs @@ -5,6 +5,7 @@ using System.Linq; using System.Text; using System.Text.RegularExpressions; using System.Threading.Tasks; +using NPoco; using Umbraco.Core.Configuration; using Umbraco.Core.Configuration.UmbracoSettings; using Umbraco.Core.Logging; @@ -26,7 +27,27 @@ using Umbraco.Core.Persistence.Mappers; namespace Umbraco.Core.Persistence.Repositories { - internal abstract class VersionableRepositoryBase : PetaPocoRepositoryBase + // this cannot be inside VersionableRepositoryBase because that class is static + internal static class VersionableRepositoryBaseAliasRegex + { + private readonly static Dictionary Regexes = new Dictionary(); + + public static Regex For(ISqlSyntaxProvider sqlSyntax) + { + var type = sqlSyntax.GetType(); + Regex aliasRegex; + if (Regexes.TryGetValue(type, out aliasRegex)) + return aliasRegex; + + var col = Regex.Escape(sqlSyntax.GetQuotedColumnName("column")).Replace("column", @"\w+"); + var fld = Regex.Escape(sqlSyntax.GetQuotedTableName("table") + ".").Replace("table", @"\w+") + col; + aliasRegex = new Regex("(" + fld + @")\s+AS\s+(" + col + ")", RegexOptions.Multiline | RegexOptions.Singleline | RegexOptions.IgnoreCase); + Regexes[type] = aliasRegex; + return aliasRegex; + } + } + + internal abstract class VersionableRepositoryBase : NPocoRepositoryBase where TEntity : class, IAggregateRoot { private readonly IContentSection _contentSection; @@ -41,22 +62,19 @@ namespace Umbraco.Core.Persistence.Repositories public virtual IEnumerable GetAllVersions(int id) { - var sql = new Sql(); - sql.Select("*") - .From(SqlSyntax) - .InnerJoin(SqlSyntax) - .On(SqlSyntax, left => left.NodeId, right => right.NodeId) - .InnerJoin(SqlSyntax) - .On(SqlSyntax, left => left.NodeId, right => right.NodeId) - .Where(SqlSyntax, x => x.NodeObjectType == NodeObjectTypeId) - .Where(SqlSyntax, x => x.NodeId == id) - .OrderByDescending(SqlSyntax, x => x.VersionDate); + var sql = Sql() + .SelectAll() + .From() + .InnerJoin() + .On(left => left.NodeId, right => right.NodeId) + .InnerJoin() + .On(left => left.NodeId, right => right.NodeId) + .Where(x => x.NodeObjectType == NodeObjectTypeId) + .Where(x => x.NodeId == id) + .OrderByDescending(x => x.VersionDate); - var dtos = Database.Fetch(sql); - foreach (var dto in dtos) - { - yield return GetByVersion(dto.VersionId); - } + var dtos = Database.Fetch(sql); + return dtos.Select(x => GetByVersion(x.VersionId)); } public virtual void DeleteVersion(Guid versionId) @@ -114,25 +132,27 @@ namespace Umbraco.Core.Persistence.Repositories var pathMatch = parentId == -1 ? "-1," : "," + parentId + ","; - var sql = new Sql(); + + var sql = Sql() + .SelectCount() + .From(); + if (contentTypeAlias.IsNullOrWhiteSpace()) { - sql.Select("COUNT(*)") - .From(SqlSyntax) - .Where(SqlSyntax, x => x.NodeObjectType == NodeObjectTypeId) - .Where(SqlSyntax, x => x.Path.Contains(pathMatch)); + sql + .Where(x => x.NodeObjectType == NodeObjectTypeId) + .Where(x => x.Path.Contains(pathMatch)); } else { - sql.Select("COUNT(*)") - .From(SqlSyntax) - .InnerJoin(SqlSyntax) - .On(SqlSyntax, left => left.NodeId, right => right.NodeId) - .InnerJoin(SqlSyntax) - .On(SqlSyntax, left => left.NodeId, right => right.ContentTypeId) - .Where(SqlSyntax, x => x.NodeObjectType == NodeObjectTypeId) - .Where(SqlSyntax, x => x.Path.Contains(pathMatch)) - .Where(SqlSyntax, x => x.Alias == contentTypeAlias); + sql + .InnerJoin() + .On(left => left.NodeId, right => right.NodeId) + .InnerJoin() + .On(left => left.NodeId, right => right.ContentTypeId) + .Where(x => x.NodeObjectType == NodeObjectTypeId) + .Where(x => x.Path.Contains(pathMatch)) + .Where(x => x.Alias == contentTypeAlias); } return Database.ExecuteScalar(sql); @@ -140,25 +160,26 @@ namespace Umbraco.Core.Persistence.Repositories public int CountChildren(int parentId, string contentTypeAlias = null) { - var sql = new Sql(); + var sql = Sql() + .SelectCount() + .From(); + if (contentTypeAlias.IsNullOrWhiteSpace()) { - sql.Select("COUNT(*)") - .From(SqlSyntax) - .Where(SqlSyntax, x => x.NodeObjectType == NodeObjectTypeId) - .Where(SqlSyntax, x => x.ParentId == parentId); + sql + .Where(x => x.NodeObjectType == NodeObjectTypeId) + .Where(x => x.ParentId == parentId); } else { - sql.Select("COUNT(*)") - .From(SqlSyntax) - .InnerJoin(SqlSyntax) - .On(SqlSyntax, left => left.NodeId, right => right.NodeId) - .InnerJoin(SqlSyntax) - .On(SqlSyntax, left => left.NodeId, right => right.ContentTypeId) - .Where(SqlSyntax, x => x.NodeObjectType == NodeObjectTypeId) - .Where(SqlSyntax, x => x.ParentId == parentId) - .Where(SqlSyntax, x => x.Alias == contentTypeAlias); + sql + .InnerJoin() + .On(left => left.NodeId, right => right.NodeId) + .InnerJoin() + .On(left => left.NodeId, right => right.ContentTypeId) + .Where(x => x.NodeObjectType == NodeObjectTypeId) + .Where(x => x.ParentId == parentId) + .Where(x => x.Alias == contentTypeAlias); } return Database.ExecuteScalar(sql); @@ -171,23 +192,24 @@ namespace Umbraco.Core.Persistence.Repositories /// public int Count(string contentTypeAlias = null) { - var sql = new Sql(); + var sql = Sql() + .SelectCount() + .From(); + if (contentTypeAlias.IsNullOrWhiteSpace()) { - sql.Select("COUNT(*)") - .From(SqlSyntax) - .Where(SqlSyntax, x => x.NodeObjectType == NodeObjectTypeId); + sql + .Where(x => x.NodeObjectType == NodeObjectTypeId); } else { - sql.Select("COUNT(*)") - .From(SqlSyntax) - .InnerJoin(SqlSyntax) - .On(SqlSyntax, left => left.NodeId, right => right.NodeId) - .InnerJoin(SqlSyntax) - .On(SqlSyntax, left => left.NodeId, right => right.ContentTypeId) - .Where(SqlSyntax, x => x.NodeObjectType == NodeObjectTypeId) - .Where(SqlSyntax, x => x.Alias == contentTypeAlias); + sql + .InnerJoin() + .On(left => left.NodeId, right => right.NodeId) + .InnerJoin() + .On(left => left.NodeId, right => right.ContentTypeId) + .Where(x => x.NodeObjectType == NodeObjectTypeId) + .Where(x => x.Alias == contentTypeAlias); } return Database.ExecuteScalar(sql); @@ -232,197 +254,161 @@ namespace Umbraco.Core.Persistence.Repositories } } - private Sql GetFilteredSqlForPagedResults(Sql sql, Func> defaultFilter = null) - { - //copy to var so that the original isn't changed - var filteredSql = new Sql(sql.SQL, sql.Arguments); - // Apply filter - if (defaultFilter != null) - { - var filterResult = defaultFilter(); - filteredSql.Append(filterResult.Item1, filterResult.Item2); - } - return filteredSql; - } - private Sql GetSortedSqlForPagedResults(Sql sql, Direction orderDirection, string orderBy) + private Sql PrepareSqlForPagedResults(Sql sql, Sql filterSql, string orderBy, Direction orderDirection, bool orderBySystemField) { - //copy to var so that the original isn't changed - var sortedSql = new Sql(sql.SQL, sql.Arguments); - // Apply order according to parameters + if (filterSql == null && string.IsNullOrEmpty(orderBy)) return sql; + + // preserve original + var psql = new Sql(sql.SqlContext, sql.SQL, sql.Arguments); + + // apply filter + if (filterSql != null) + { + psql.Append(filterSql); + } + + // apply sort if (string.IsNullOrEmpty(orderBy) == false) { - var orderByParams = new[] { GetDatabaseFieldNameForOrderBy(orderBy) }; - if (orderDirection == Direction.Ascending) + if (orderBySystemField) { - sortedSql.OrderBy(orderByParams); + // get the database field eg "[table].[column]" + var dbfield = GetDatabaseFieldNameForOrderBy(orderBy); + + // for SqlServer pagination to work, the "order by" field needs to be the alias eg if + // the select statement has "umbracoNode.text AS NodeDto__Text" then the order field needs + // to be "NodeDto__Text" and NOT "umbracoNode.text". + // not sure about SqlCE nor MySql, so better do it too. initially thought about patching + // NPoco but that would be expensive and not 100% possible, so better give NPoco proper + // queries to begin with. + // thought about maintaining a map of columns-to-aliases in the sql context but that would + // be expensive and most of the time, useless. so instead we parse the SQL looking for the + // alias. somewhat expensive too but nothing's free. + + var matches = VersionableRepositoryBaseAliasRegex.For(SqlSyntax).Matches(sql.SQL); + var match = matches.Cast().FirstOrDefault(m => m.Groups[1].Value == dbfield); + if (match != null) + dbfield = match.Groups[2].Value; + + var orderByParams = new object[] {dbfield}; + if (orderDirection == Direction.Ascending) + psql.OrderBy(orderByParams); + else + psql.OrderByDescending(orderByParams); } else { - sortedSql.OrderByDescending(orderByParams); + // Sorting by a custom field, so set-up sub-query for ORDER BY clause to pull through valie + // from most recent content version for the given order by field + var sortedInt = string.Format(SqlSyntax.ConvertIntegerToOrderableString, "dataInt"); + var sortedDate = string.Format(SqlSyntax.ConvertDateToOrderableString, "dataDate"); + var sortedString = string.Format("COALESCE({0},'')", "dataNvarchar"); + var sortedDecimal = string.Format(SqlSyntax.ConvertDecimalToOrderableString, "dataDecimal"); + + var innerJoinTempTable = string.Format(@"INNER JOIN ( + SELECT CASE + WHEN dataInt Is Not Null THEN {0} + WHEN dataDecimal Is Not Null THEN {1} + WHEN dataDate Is Not Null THEN {2} + ELSE {3} + END AS CustomPropVal, + cd.nodeId AS CustomPropValContentId + FROM cmsDocument cd + INNER JOIN cmsPropertyData cpd ON cpd.contentNodeId = cd.nodeId AND cpd.versionId = cd.versionId + INNER JOIN cmsPropertyType cpt ON cpt.Id = cpd.propertytypeId + WHERE cpt.Alias = @2 AND cd.newest = 1) AS CustomPropData + ON CustomPropData.CustomPropValContentId = umbracoNode.id +", sortedInt, sortedDecimal, sortedDate, sortedString); + + //insert this just above the LEFT OUTER JOIN + var newSql = psql.SQL.Insert(psql.SQL.IndexOf("LEFT OUTER JOIN"), innerJoinTempTable); + var newArgs = psql.Arguments.ToList(); + newArgs.Add(orderBy); + + psql = new Sql(psql.SqlContext, newSql, newArgs.ToArray()); + + psql.OrderBy("CustomPropData.CustomPropVal"); + //psql.Append(innerJoinTempTable, orderBy); + if (orderDirection == Direction.Descending) + { + psql.Append(" DESC"); + } } - return sortedSql; } - return sortedSql; + + return psql; } - /// - /// A helper method for inheritors to get the paged results by query in a way that minimizes queries - /// - /// The type of the d. - /// The 'true' entity type (i.e. Content, Member, etc...) - /// The query. - /// Index of the page. - /// Size of the page. - /// The total records. - /// The tablename + column name for the SELECT statement fragment to return the node id from the query - /// A callback to create the default filter to be applied if there is one - /// A callback to process the query result - /// The order by column - /// The order direction. - /// - /// orderBy - protected IEnumerable GetPagedResultsByQuery(IQuery query, long pageIndex, int pageSize, out long totalRecords, - Tuple nodeIdSelect, - Func> processQuery, - string orderBy, - Direction orderDirection, - Func> defaultFilter = null) - where TContentBase : class, IAggregateRoot, TEntity + protected IEnumerable GetPagedResultsByQuery(IQuery query, long pageIndex, int pageSize, out long totalRecords, + Func, IEnumerable> mapper, + string orderBy, Direction orderDirection, bool orderBySystemField, + Sql filterSql = null) { - if (orderBy == null) throw new ArgumentNullException("orderBy"); + if (orderBy == null) throw new ArgumentNullException(nameof(orderBy)); - // Get base query + // start with base query, and apply the supplied IQuery var sqlBase = GetBaseQuery(false); - if (query == null) query = Query; var translator = new SqlTranslator(sqlBase, query); - var sqlQuery = translator.Translate(); - - // Note we can't do multi-page for several DTOs like we can multi-fetch and are doing in PerformGetByQuery, - // but actually given we are doing a Get on each one (again as in PerformGetByQuery), we only need the node Id. - // So we'll modify the SQL. - var sqlNodeIds = new Sql( - sqlQuery.SQL.Replace("SELECT *", string.Format("SELECT {0}.{1}",nodeIdSelect.Item1, nodeIdSelect.Item2)), - sqlQuery.Arguments); - - //get sorted and filtered sql - var sqlNodeIdsWithSort = GetSortedSqlForPagedResults( - GetFilteredSqlForPagedResults(sqlNodeIds, defaultFilter), - orderDirection, orderBy); + var sqlNodeIds = translator.Translate(); - // Get page of results and total count - IEnumerable result; - var pagedResult = Database.Page(pageIndex + 1, pageSize, sqlNodeIdsWithSort); + // sort and filter + sqlNodeIds = PrepareSqlForPagedResults(sqlNodeIds, filterSql, orderBy, orderDirection, orderBySystemField); + + // get a page of DTOs and the total count + var pagedResult = Database.Page(pageIndex + 1, pageSize, sqlNodeIds); totalRecords = Convert.ToInt32(pagedResult.TotalItems); - //NOTE: We need to check the actual items returned, not the 'totalRecords', that is because if you request a page number - // that doesn't actually have any data on it, the totalRecords will still indicate there are records but there are none in - // the pageResult, then the GetAll will actually return ALL records in the db. - if (pagedResult.Items.Any()) - { - //Crete the inner paged query that was used above to get the paged result, we'll use that as the inner sub query - var args = sqlNodeIdsWithSort.Arguments; - string sqlStringCount, sqlStringPage; - Database.BuildPageQueries(pageIndex * pageSize, pageSize, sqlNodeIdsWithSort.SQL, ref args, out sqlStringCount, out sqlStringPage); - - //if this is for sql server, the sqlPage will start with a SELECT * but we don't want that, we only want to return the nodeId - sqlStringPage = sqlStringPage - .Replace("SELECT *", - //This ensures we only take the field name of the node id select and not the table name - since the resulting select - // will ony work with the field name. - "SELECT " + nodeIdSelect.Item2); - - //We need to make this an inner join on the paged query - var splitQuery = sqlQuery.SQL.Split(new[] {"WHERE "}, StringSplitOptions.None); - var withInnerJoinSql = new Sql(splitQuery[0]) - .Append("INNER JOIN (") - //join the paged query with the paged query arguments - .Append(sqlStringPage, args) - .Append(") temp ") - .Append(string.Format("ON {0}.{1} = temp.{1}", nodeIdSelect.Item1, nodeIdSelect.Item2)) - //add the original where clause back with the original arguments - .Where(splitQuery[1], sqlQuery.Arguments); - - //get sorted and filtered sql - var fullQuery = GetSortedSqlForPagedResults( - GetFilteredSqlForPagedResults(withInnerJoinSql, defaultFilter), - orderDirection, orderBy); - - var content = processQuery(fullQuery) - .Cast() - .AsQueryable(); - - // Now we need to ensure this result is also ordered by the same order by clause - var orderByProperty = GetEntityPropertyNameForOrderBy(orderBy); - if (orderDirection == Direction.Ascending) - { - result = content.OrderBy(orderByProperty); - } - else - { - result = content.OrderByDescending(orderByProperty); - } - } - else - { - result = Enumerable.Empty(); - } - - return result; + // map the DTOs and return + return mapper(pagedResult.Items); } - protected IDictionary GetPropertyCollection( - Sql docSql, - IEnumerable documentDefs) + protected IDictionary GetPropertyCollection(DocumentDefinition[] ddefs) { - if (documentDefs.Any() == false) return new Dictionary(); + var versions = ddefs.Select(x => x.Version).ToArray(); + if (versions.Length == 0) return new Dictionary(); - //we need to parse the original SQL statement and reduce the columns to just cmsContent.nodeId, cmsContentVersion.VersionId so that we can use - // the statement to go get the property data for all of the items by using an inner join - var parsedOriginalSql = "SELECT {0} " + docSql.SQL.Substring(docSql.SQL.IndexOf("FROM", StringComparison.Ordinal)); - //now remove everything from an Orderby clause and beyond - if (parsedOriginalSql.InvariantContains("ORDER BY ")) + // fetch by version only, that should be enough, versions are guids and the same guid + // should not be reused for two different nodes -- then validate with a Where() just + // to be sure -- but we probably can get rid of the validation + var allPropertyData = Database.FetchByGroups(versions, 2000, batch => + Sql() + .Select(r => r.Select()) + .From() + .LeftJoin() + .On(left => left.PropertyTypeId, right => right.Id) + .WhereIn(x => x.VersionId, batch)) + .Where(x => ddefs.Any(y => y.Version == x.VersionId && y.Id == x.NodeId)) // so... probably redundant, but safe + .ToList(); + + // lazy access to prevalue for data types if any property requires tag support + var pre = new Lazy>(() => { - parsedOriginalSql = parsedOriginalSql.Substring(0, parsedOriginalSql.LastIndexOf("ORDER BY ", StringComparison.Ordinal)); - } + var allPropertyTypes = allPropertyData + .Select(x => x.PropertyTypeDto.Id) + .Distinct(); - var propSql = new Sql(@"SELECT cmsPropertyData.* -FROM cmsPropertyData -INNER JOIN cmsPropertyType -ON cmsPropertyData.propertytypeid = cmsPropertyType.id -INNER JOIN - (" + string.Format(parsedOriginalSql, "cmsContent.nodeId, cmsContentVersion.VersionId") + @") as docData -ON cmsPropertyData.versionId = docData.VersionId AND cmsPropertyData.contentNodeId = docData.nodeId -LEFT OUTER JOIN cmsDataTypePreValues -ON cmsPropertyType.dataTypeId = cmsDataTypePreValues.datatypeNodeId", docSql.Arguments); + var allDataTypePreValue = Database.FetchByGroups(allPropertyTypes, 2000, batch => + Sql() + .Select() + .From() + .LeftJoin().On(left => left.DataTypeNodeId, right => right.DataTypeId) + .WhereIn(x => x.Id, batch)); - var allPropertyData = Database.Fetch(propSql); - - //This is a lazy access call to get all prevalue data for the data types that make up all of these properties which we use - // below if any property requires tag support - var allPreValues = new Lazy>(() => - { - var preValsSql = new Sql(@"SELECT a.id, a.value, a.sortorder, a.alias, a.datatypeNodeId -FROM cmsDataTypePreValues a -WHERE EXISTS( - SELECT DISTINCT b.id as preValIdInner - FROM cmsDataTypePreValues b - INNER JOIN cmsPropertyType - ON b.datatypeNodeId = cmsPropertyType.dataTypeId - INNER JOIN - (" + string.Format(parsedOriginalSql, "DISTINCT cmsContent.contentType") + @") as docData - ON cmsPropertyType.contentTypeId = docData.contentType - WHERE a.id = b.id)", docSql.Arguments); - - return Database.Fetch(preValsSql); + return allDataTypePreValue; }); + return GetPropertyCollection(ddefs, allPropertyData, pre); + } + + protected IDictionary GetPropertyCollection(DocumentDefinition[] documentDefs, List allPropertyData, Lazy> allPreValues) + { var result = new Dictionary(); var propertiesWithTagSupport = new Dictionary(); - //iterate each definition grouped by it's content type - this will mean less property type iterations while building + //iterate each definition grouped by it's content type - this will mean less property type iterations while building // up the property collections foreach (var compositionGroup in documentDefs.GroupBy(x => x.Composition)) { @@ -433,8 +419,8 @@ WHERE EXISTS( var propertyDataDtos = allPropertyData.Where(x => x.NodeId == def.Id).Distinct(); var propertyFactory = new PropertyFactory(compositionProperties, def.Version, def.Id, def.CreateDate, def.VersionDate); - var properties = propertyFactory.BuildEntity(propertyDataDtos.ToArray()).ToArray(); - + var properties = propertyFactory.BuildEntity(propertyDataDtos.ToArray()).ToArray(); + var newProperties = properties.Where(x => x.HasIdentity == false && x.PropertyType.HasIdentity); foreach (var property in newProperties) @@ -482,7 +468,7 @@ WHERE EXISTS( Logger.Warn>("The query returned multiple property sets for document definition " + def.Id + ", " + def.Composition.Name); } result[def.Id] = new PropertyCollection(properties); - } + } } return result; @@ -511,37 +497,20 @@ WHERE EXISTS( protected virtual string GetDatabaseFieldNameForOrderBy(string orderBy) { - // Translate the passed order by field (which were originally defined for in-memory object sorting - // of ContentItemBasic instances) to the database field names. + // translate the supplied "order by" field, which were originally defined for in-memory + // object sorting of ContentItemBasic instance, to the actual database field names. + switch (orderBy.ToUpperInvariant()) { case "UPDATEDATE": - return "cmsContentVersion.VersionDate"; + return SqlSyntax.GetQuotedTableName("cmsContentVersion") + "." + SqlSyntax.GetQuotedColumnName("VersionDate"); case "NAME": - return "umbracoNode.text"; + return SqlSyntax.GetQuotedTableName("umbracoNode") + "." + SqlSyntax.GetQuotedColumnName("text"); case "OWNER": //TODO: This isn't going to work very nicely because it's going to order by ID, not by letter - return "umbracoNode.nodeUser"; - default: - //ensure invalid SQL cannot be submitted - return Regex.Replace(orderBy, @"[^\w\.,`\[\]@-]", ""); - } - } - - protected virtual string GetEntityPropertyNameForOrderBy(string orderBy) - { - // Translate the passed order by field (which were originally defined for in-memory object sorting - // of ContentItemBasic instances) to the IMedia property names. - switch (orderBy.ToUpperInvariant()) - { - case "OWNER": - //TODO: This isn't going to work very nicely because it's going to order by ID, not by letter - return "CreatorId"; - case "UPDATER": - //TODO: This isn't going to work very nicely because it's going to order by ID, not by letter - return "WriterId"; - case "VERSIONDATE": - return "UpdateDate"; + return SqlSyntax.GetQuotedTableName("umbracoNode") + "." + SqlSyntax.GetQuotedColumnName("nodeUser"); + case "PATH": + return SqlSyntax.GetQuotedTableName("umbracoNode") + "." + SqlSyntax.GetQuotedColumnName("path"); default: //ensure invalid SQL cannot be submitted return Regex.Replace(orderBy, @"[^\w\.,`\[\]@-]", ""); diff --git a/src/Umbraco.Core/Persistence/SqlContext.cs b/src/Umbraco.Core/Persistence/SqlContext.cs new file mode 100644 index 0000000000..927d6b469e --- /dev/null +++ b/src/Umbraco.Core/Persistence/SqlContext.cs @@ -0,0 +1,36 @@ +using System; +using NPoco; +using Umbraco.Core.Persistence.SqlSyntax; + +namespace Umbraco.Core.Persistence +{ + public class SqlContext + { + public SqlContext(ISqlSyntaxProvider sqlSyntax, IPocoDataFactory pocoDataFactory, DatabaseType databaseType) + { + if (sqlSyntax == null) throw new ArgumentNullException(nameof(sqlSyntax)); + if (pocoDataFactory == null) throw new ArgumentNullException(nameof(pocoDataFactory)); + if (databaseType == null) throw new ArgumentNullException(nameof(databaseType)); + + SqlSyntax = sqlSyntax; + PocoDataFactory = pocoDataFactory; + DatabaseType = databaseType; + } + + public SqlContext(ISqlSyntaxProvider sqlSyntax, IDatabaseConfig database) + { + if (sqlSyntax == null) throw new ArgumentNullException(nameof(sqlSyntax)); + if (database == null) throw new ArgumentNullException(nameof(database)); + + SqlSyntax = sqlSyntax; + PocoDataFactory = database.PocoDataFactory; + DatabaseType = database.DatabaseType; + } + + public ISqlSyntaxProvider SqlSyntax { get; } + + public IPocoDataFactory PocoDataFactory { get; } + + public DatabaseType DatabaseType { get; } + } +} diff --git a/src/Umbraco.Core/Persistence/SqlSyntax/ISqlSyntaxProvider.cs b/src/Umbraco.Core/Persistence/SqlSyntax/ISqlSyntaxProvider.cs index 056d9c1d9a..fc26bcd7c9 100644 --- a/src/Umbraco.Core/Persistence/SqlSyntax/ISqlSyntaxProvider.cs +++ b/src/Umbraco.Core/Persistence/SqlSyntax/ISqlSyntaxProvider.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using NPoco; using Umbraco.Core.Persistence.DatabaseAnnotations; using Umbraco.Core.Persistence.DatabaseModelDefinitions; using Umbraco.Core.Persistence.Querying; @@ -69,6 +70,10 @@ namespace Umbraco.Core.Persistence.SqlSyntax bool SupportsClustered(); bool SupportsIdentityInsert(); bool? SupportsCaseInsensitiveQueries(Database db); + + string ConvertIntegerToOrderableString { get; } + string ConvertDateToOrderableString { get; } + string ConvertDecimalToOrderableString { get; } IEnumerable GetTablesInSchema(Database db); IEnumerable GetColumnsInSchema(Database db); diff --git a/src/Umbraco.Core/Persistence/SqlSyntax/MySqlSyntaxProvider.cs b/src/Umbraco.Core/Persistence/SqlSyntax/MySqlSyntaxProvider.cs index c18a5f8477..462f601323 100644 --- a/src/Umbraco.Core/Persistence/SqlSyntax/MySqlSyntaxProvider.cs +++ b/src/Umbraco.Core/Persistence/SqlSyntax/MySqlSyntaxProvider.cs @@ -1,6 +1,7 @@ using System; using System.Collections.Generic; using System.Linq; +using NPoco; using Umbraco.Core.Logging; using Umbraco.Core.Persistence.DatabaseAnnotations; using Umbraco.Core.Persistence.DatabaseModelDefinitions; @@ -18,7 +19,7 @@ namespace Umbraco.Core.Persistence.SqlSyntax public MySqlSyntaxProvider(ILogger logger) { _logger = logger; - + AutoIncrementDefinition = "AUTO_INCREMENT"; IntColumnDefinition = "int(11)"; BoolColumnDefinition = "tinyint(1)"; @@ -26,7 +27,7 @@ namespace Umbraco.Core.Persistence.SqlSyntax TimeColumnDefinition = "time"; DecimalColumnDefinition = "decimal(38,6)"; GuidColumnDefinition = "char(36)"; - + DefaultValueFormat = "DEFAULT {0}"; InitColumnTypeMap(); @@ -326,13 +327,13 @@ ORDER BY TABLE_NAME, INDEX_NAME", { case SystemMethods.NewGuid: return null; // NOT SUPPORTED! - //return "NEWID()"; + //return "NEWID()"; case SystemMethods.CurrentDateTime: return "CURRENT_TIMESTAMP"; - //case SystemMethods.NewSequentialId: - // return "NEWSEQUENTIALID()"; - //case SystemMethods.CurrentUTCDateTime: - // return "GETUTCDATE()"; + //case SystemMethods.NewSequentialId: + // return "NEWSEQUENTIALID()"; + //case SystemMethods.CurrentUTCDateTime: + // return "GETUTCDATE()"; } return null; @@ -360,6 +361,9 @@ ORDER BY TABLE_NAME, INDEX_NAME", public override string DropIndex { get { return "DROP INDEX {0} ON {1}"; } } public override string RenameColumn { get { return "ALTER TABLE {0} CHANGE {1} {2}"; } } + public override string ConvertIntegerToOrderableString { get { return "LPAD(FORMAT({0}, 0), 8, '0')"; } } + public override string ConvertDateToOrderableString { get { return "DATE_FORMAT({0}, '%Y%m%d')"; } } + public override string ConvertDecimalToOrderableString { get { return "LPAD(FORMAT({0}, 9), 20, '0')"; } } public override bool? SupportsCaseInsensitiveQueries(Database db) { @@ -390,7 +394,7 @@ ORDER BY TABLE_NAME, INDEX_NAME", public override string EscapeString(string val) { - return PetaPocoExtensions.EscapeAtSymbols(MySql.Data.MySqlClient.MySqlHelper.EscapeString(val)); + return NPocoDatabaseExtensions.EscapeAtSymbols(MySql.Data.MySqlClient.MySqlHelper.EscapeString(val)); } } } \ No newline at end of file diff --git a/src/Umbraco.Core/Persistence/SqlSyntax/SqlCeSyntaxProvider.cs b/src/Umbraco.Core/Persistence/SqlSyntax/SqlCeSyntaxProvider.cs index 1c6e1bba52..4a3eb2e4a8 100644 --- a/src/Umbraco.Core/Persistence/SqlSyntax/SqlCeSyntaxProvider.cs +++ b/src/Umbraco.Core/Persistence/SqlSyntax/SqlCeSyntaxProvider.cs @@ -1,6 +1,7 @@ using System; using System.Collections.Generic; using System.Linq; +using NPoco; using Umbraco.Core.Persistence.DatabaseAnnotations; using Umbraco.Core.Persistence.DatabaseModelDefinitions; using Umbraco.Core.Persistence.Querying; @@ -208,7 +209,6 @@ ORDER BY TABLE_NAME, INDEX_NAME"); public override string DropIndex { get { return "DROP INDEX {1}.{0}"; } } - } } \ No newline at end of file diff --git a/src/Umbraco.Core/Persistence/SqlSyntax/SqlServerSyntaxProvider.cs b/src/Umbraco.Core/Persistence/SqlSyntax/SqlServerSyntaxProvider.cs index 9cb0ce327d..8ea169e997 100644 --- a/src/Umbraco.Core/Persistence/SqlSyntax/SqlServerSyntaxProvider.cs +++ b/src/Umbraco.Core/Persistence/SqlSyntax/SqlServerSyntaxProvider.cs @@ -1,6 +1,7 @@ using System; using System.Collections.Generic; using System.Linq; +using NPoco; using Umbraco.Core.Persistence.DatabaseModelDefinitions; namespace Umbraco.Core.Persistence.SqlSyntax diff --git a/src/Umbraco.Core/Persistence/SqlSyntax/SqlSyntaxProviderBase.cs b/src/Umbraco.Core/Persistence/SqlSyntax/SqlSyntaxProviderBase.cs index eb8a56faca..a992cdd231 100644 --- a/src/Umbraco.Core/Persistence/SqlSyntax/SqlSyntaxProviderBase.cs +++ b/src/Umbraco.Core/Persistence/SqlSyntax/SqlSyntaxProviderBase.cs @@ -4,6 +4,7 @@ using System.Data; using System.Globalization; using System.Linq; using System.Text; +using NPoco; using Umbraco.Core.Persistence.DatabaseAnnotations; using Umbraco.Core.Persistence.DatabaseModelDefinitions; using Umbraco.Core.Persistence.Querying; @@ -121,7 +122,7 @@ namespace Umbraco.Core.Persistence.SqlSyntax public virtual string EscapeString(string val) { - return PetaPocoExtensions.EscapeAtSymbols(val.Replace("'", "''")); + return NPocoDatabaseExtensions.EscapeAtSymbols(val.Replace("'", "''")); } public virtual string GetStringColumnEqualComparison(string column, int paramIndex, TextColumnType columnType) @@ -322,7 +323,7 @@ namespace Umbraco.Core.Persistence.SqlSyntax GetQuotedColumnName(foreignKey.ForeignColumns.First()), GetQuotedTableName(foreignKey.PrimaryTable), GetQuotedColumnName(foreignKey.PrimaryColumns.First()), - FormatCascade("DELETE", foreignKey.OnDelete), + FormatCascade("DELETE", foreignKey.OnDelete), FormatCascade("UPDATE", foreignKey.OnUpdate)); } @@ -331,7 +332,7 @@ namespace Umbraco.Core.Persistence.SqlSyntax var sb = new StringBuilder(); foreach (var column in columns) { - sb.Append(Format(column) +",\n"); + sb.Append(Format(column) + ",\n"); } return sb.ToString().TrimEnd(",\n"); } @@ -431,11 +432,11 @@ namespace Umbraco.Core.Persistence.SqlSyntax return GetSpecialDbType(column.DbType); } - Type type = column.Type.HasValue + Type type = column.Type.HasValue ? DbTypeMap.ColumnDbTypeMap.First(x => x.Value == column.Type.Value).Key : column.PropertyType; - if (type == typeof (string)) + if (type == typeof(string)) { var valueOrDefault = column.Size != default(int) ? column.Size : DefaultStringLength; return string.Format(StringLengthColumnDefinitionFormat, valueOrDefault); @@ -536,5 +537,9 @@ namespace Umbraco.Core.Persistence.SqlSyntax public virtual string CreateConstraint { get { return "ALTER TABLE {0} ADD CONSTRAINT {1} {2} ({3})"; } } public virtual string DeleteConstraint { get { return "ALTER TABLE {0} DROP CONSTRAINT {1}"; } } public virtual string CreateForeignKeyConstraint { get { return "ALTER TABLE {0} ADD CONSTRAINT {1} FOREIGN KEY ({2}) REFERENCES {3} ({4}){5}{6}"; } } + + public virtual string ConvertIntegerToOrderableString { get { return "REPLACE(STR({0}, 8), SPACE(1), '0')"; } } + public virtual string ConvertDateToOrderableString { get { return "CONVERT(nvarchar, {0}, 102)"; } } + public virtual string ConvertDecimalToOrderableString { get { return "REPLACE(STR({0}, 20, 9), SPACE(1), '0')"; } } } } \ No newline at end of file diff --git a/src/Umbraco.Core/Persistence/SqlSyntax/SqlSyntaxProviderExtensions.cs b/src/Umbraco.Core/Persistence/SqlSyntax/SqlSyntaxProviderExtensions.cs index af18d9c3d9..90f0a56696 100644 --- a/src/Umbraco.Core/Persistence/SqlSyntax/SqlSyntaxProviderExtensions.cs +++ b/src/Umbraco.Core/Persistence/SqlSyntax/SqlSyntaxProviderExtensions.cs @@ -1,4 +1,6 @@ -namespace Umbraco.Core.Persistence.SqlSyntax +using NPoco; + +namespace Umbraco.Core.Persistence.SqlSyntax { internal static class SqlSyntaxProviderExtensions { diff --git a/src/Umbraco.Core/Persistence/UmbracoDatabase.cs b/src/Umbraco.Core/Persistence/UmbracoDatabase.cs index 8125c183ff..451fbf36d7 100644 --- a/src/Umbraco.Core/Persistence/UmbracoDatabase.cs +++ b/src/Umbraco.Core/Persistence/UmbracoDatabase.cs @@ -3,23 +3,32 @@ using System.Collections.Generic; using System.Data; using System.Data.Common; using System.Linq; +using System.Text; +using NPoco; using StackExchange.Profiling; using Umbraco.Core.Logging; +using Umbraco.Core.Persistence.FaultHandling; +using Umbraco.Core.Persistence.Mappers; namespace Umbraco.Core.Persistence { /// - /// Represents the Umbraco implementation of the PetaPoco Database object + /// Extends NPoco Database for Umbraco. /// /// - /// Currently this object exists for 'future proofing' our implementation. By having our own inheritied implementation we - /// can then override any additional execution (such as additional loggging, functionality, etc...) that we need to without breaking compatibility since we'll always be exposing - /// this object instead of the base PetaPoco database object. + /// Is used everywhere in place of the original NPoco Database object, and provides additional features + /// such as profiling, retry policies, logging, etc. + /// Is never created directly but obtained from the . /// public class UmbracoDatabase : Database, IDisposeOnRequestEnd { + // Umbraco's default isolation level is RepeatableRead + private const IsolationLevel DefaultIsolationLevel = IsolationLevel.RepeatableRead; + private readonly ILogger _logger; private readonly Guid _instanceId = Guid.NewGuid(); + private readonly RetryPolicy _connectionRetryPolicy; + private readonly RetryPolicy _commandRetryPolicy; private bool _enableCount; /// @@ -57,67 +66,85 @@ namespace Umbraco.Core.Persistence /// internal int SqlCount { get; private set; } - public UmbracoDatabase(IDbConnection connection, ILogger logger) - : base(connection) + // used by DefaultDatabaseFactory + // creates one instance per request + // also used by DatabaseContext for creating DBs and upgrading + public UmbracoDatabase(string connectionString, string providerName, ILogger logger, RetryPolicy connectionRetryPolicy = null, RetryPolicy commandRetryPolicy = null) + : base(connectionString, providerName, DefaultIsolationLevel) { _logger = logger; + _connectionRetryPolicy = connectionRetryPolicy; + _commandRetryPolicy = commandRetryPolicy; EnableSqlTrace = false; } - public UmbracoDatabase(string connectionString, string providerName, ILogger logger) - : base(connectionString, providerName) + // used by DefaultDatabaseFactory + // creates one instance per request + public UmbracoDatabase(string connectionStringName, ILogger logger, RetryPolicy connectionRetryPolicy = null, RetryPolicy commandRetryPolicy = null) + : base(connectionStringName, DefaultIsolationLevel) { _logger = logger; + _connectionRetryPolicy = connectionRetryPolicy; + _commandRetryPolicy = commandRetryPolicy; EnableSqlTrace = false; } - public UmbracoDatabase(string connectionString, DbProviderFactory provider, ILogger logger) - : base(connectionString, provider) + protected override DbConnection OnConnectionOpened(DbConnection connection) { - _logger = logger; - EnableSqlTrace = false; - } - - public UmbracoDatabase(string connectionStringName, ILogger logger) - : base(connectionStringName) - { - _logger = logger; - EnableSqlTrace = false; - } - - public override IDbConnection OnConnectionOpened(IDbConnection connection) - { - // propagate timeout if none yet + if (connection == null) throw new ArgumentNullException("connection"); // wrap the connection with a profiling connection that tracks timings - return new StackExchange.Profiling.Data.ProfiledDbConnection(connection as DbConnection, MiniProfiler.Current); + connection = new StackExchange.Profiling.Data.ProfiledDbConnection(connection, MiniProfiler.Current); + + // wrap the connection with a retrying connection + if (_connectionRetryPolicy != null || _commandRetryPolicy != null) + connection = new RetryDbConnection(connection, _connectionRetryPolicy, _commandRetryPolicy); + + return connection; } - public override void OnException(Exception x) + protected override void OnException(Exception x) { _logger.Error("Database exception occurred", x); base.OnException(x); } - public override void OnExecutingCommand(IDbCommand cmd) + // fixme.poco - has new interceptors? + + protected override void OnExecutingCommand(DbCommand cmd) { // if no timeout is specified, and the connection has a longer timeout, use it if (OneTimeCommandTimeout == 0 && CommandTimeout == 0 && cmd.Connection.ConnectionTimeout > 30) cmd.CommandTimeout = cmd.Connection.ConnectionTimeout; + + if (EnableSqlTrace) + { + var sb = new StringBuilder(); + sb.Append(cmd.CommandText); + foreach (DbParameter p in cmd.Parameters) + { + sb.Append(" - "); + sb.Append(p.Value); + } + + _logger.Debug(sb.ToString()); + } + base.OnExecutingCommand(cmd); } - public override void OnExecutedCommand(IDbCommand cmd) + protected override void OnExecutedCommand(DbCommand cmd) { - if (EnableSqlTrace) - { - _logger.Debug(cmd.CommandText); - } if (_enableCount) { SqlCount++; } base.OnExecutedCommand(cmd); } + + public IEnumerable FetchByGroups(IEnumerable source, int groupSize, Func, Sql> sqlFactory) + { + return source.SelectByGroups(x => Fetch(sqlFactory(x)), groupSize); + } } } \ No newline at end of file diff --git a/src/Umbraco.Core/Persistence/UmbracoSqlExtensions.cs b/src/Umbraco.Core/Persistence/UmbracoSqlExtensions.cs new file mode 100644 index 0000000000..6bb571fe6e --- /dev/null +++ b/src/Umbraco.Core/Persistence/UmbracoSqlExtensions.cs @@ -0,0 +1,250 @@ +using System; +using System.Collections; +using System.Linq; +using System.Linq.Expressions; +using System.Reflection; +using NPoco; +using Umbraco.Core.Persistence.Querying; + +namespace Umbraco.Core.Persistence +{ + public static class UmbracoSqlExtensions + { + // note: here we take benefit from the fact that NPoco methods that return a Sql, such as + // when doing "sql = sql.Where(...)" actually append to, and return, the original Sql, not + // a new one. + + #region Where + + public static Sql Where(this Sql sql, Expression> predicate) + { + var expresionist = new PocoToSqlExpressionHelper(sql.SqlContext); + var whereExpression = expresionist.Visit(predicate); + sql.Where(whereExpression, expresionist.GetSqlParameters()); + return sql; + } + + public static Sql WhereIn(this Sql sql, Expression> fieldSelector, IEnumerable values) + { + var expresionist = new PocoToSqlExpressionHelper(sql.SqlContext); + var fieldExpression = expresionist.Visit(fieldSelector); + sql.Where(fieldExpression + " IN (@values)", new { /*@values =*/ values }); + return sql; + } + + #endregion + + #region From + + public static Sql From(this Sql sql) + { + var type = typeof (T); + var tableNameAttribute = type.FirstAttribute(); + var tableName = tableNameAttribute == null ? string.Empty : tableNameAttribute.Value; + + sql.From(sql.SqlContext.SqlSyntax.GetQuotedTableName(tableName)); + return sql; + } + + #endregion + + #region OrderBy, GroupBy + + public static Sql OrderBy(this Sql sql, Expression> columnMember) + { + var column = ExpressionHelper.FindProperty(columnMember) as PropertyInfo; + var columnName = column.FirstAttribute().Name; + + var type = typeof (T); + var tableNameAttribute = type.FirstAttribute(); + var tableName = tableNameAttribute == null ? string.Empty : tableNameAttribute.Value; + + // need to ensure the order by is in brackets, see: https://github.com/toptensoftware/PetaPoco/issues/177 + var sqlSyntax = sql.SqlContext.SqlSyntax; + var syntax = $"({sqlSyntax.GetQuotedTableName(tableName)}.{sqlSyntax.GetQuotedColumnName(columnName)})"; + + sql.OrderBy(syntax); + return sql; + } + + public static Sql OrderByDescending(this Sql sql, Expression> columnMember) + { + var column = ExpressionHelper.FindProperty(columnMember) as PropertyInfo; + var columnName = column.FirstAttribute().Name; + + var type = typeof(T); + var tableNameAttribute = type.FirstAttribute(); + var tableName = tableNameAttribute == null ? string.Empty : tableNameAttribute.Value; + + var sqlSyntax = sql.SqlContext.SqlSyntax; + var syntax = $"{sqlSyntax.GetQuotedTableName(tableName)}.{sqlSyntax.GetQuotedColumnName(columnName)} DESC"; + + sql.OrderBy(syntax); + return sql; + } + + public static Sql OrderByDescending(this Sql sql, params object[] columns) + { + sql.Append("ORDER BY " + string.Join(", ", columns.Select(x => x + " DESC"))); + return sql; + } + + public static Sql GroupBy(this Sql sql, Expression> columnMember) + { + var column = ExpressionHelper.FindProperty(columnMember) as PropertyInfo; + var columnName = column.FirstAttribute().Name; + + sql.GroupBy(sql.SqlContext.SqlSyntax.GetQuotedColumnName(columnName)); + return sql; + } + + #endregion + + #region Joins + + public static Sql.SqlJoinClause InnerJoin(this Sql sql) + { + var type = typeof(T); + var tableNameAttribute = type.FirstAttribute(); + var tableName = tableNameAttribute == null ? string.Empty : tableNameAttribute.Value; + + return sql.InnerJoin(sql.SqlContext.SqlSyntax.GetQuotedTableName(tableName)); + } + + public static Sql.SqlJoinClause LeftJoin(this Sql sql) + { + var type = typeof(T); + var tableNameAttribute = type.FirstAttribute(); + var tableName = tableNameAttribute == null ? string.Empty : tableNameAttribute.Value; + + return sql.LeftJoin(sql.SqlContext.SqlSyntax.GetQuotedTableName(tableName)); + } + + public static Sql.SqlJoinClause LeftOuterJoin(this Sql sql) + { + var type = typeof(T); + var tableNameAttribute = type.FirstAttribute(); + var tableName = tableNameAttribute == null ? string.Empty : tableNameAttribute.Value; + + return sql.LeftOuterJoin(sql.SqlContext.SqlSyntax.GetQuotedTableName(tableName)); + } + + public static Sql.SqlJoinClause RightJoin(this Sql sql) + { + var type = typeof(T); + var tableNameAttribute = type.FirstAttribute(); + var tableName = tableNameAttribute == null ? string.Empty : tableNameAttribute.Value; + + return sql.RightJoin(sql.SqlContext.SqlSyntax.GetQuotedTableName(tableName)); + } + + public static Sql On(this Sql.SqlJoinClause clause, + Expression> leftMember, Expression> rightMember, + params object[] args) + { + var sqlSyntax = clause.SqlContext.SqlSyntax; + + var leftType = typeof (TLeft); + var rightType = typeof (TRight); + var leftTableName = sqlSyntax.GetQuotedTableName(leftType.FirstAttribute().Value); + var rightTableName = sqlSyntax.GetQuotedTableName(rightType.FirstAttribute().Value); + + var left = ExpressionHelper.FindProperty(leftMember) as PropertyInfo; + var right = ExpressionHelper.FindProperty(rightMember) as PropertyInfo; + var leftColumnName = sqlSyntax.GetQuotedColumnName(left.FirstAttribute().Name); + var rightColumnName = sqlSyntax.GetQuotedColumnName(right.FirstAttribute().Name); + + var onClause = $"{leftTableName}.{leftColumnName} = {rightTableName}.{rightColumnName}"; + return clause.On(onClause); + } + + #endregion + + #region Select + + public static Sql SelectCount(this Sql sql) + { + sql.Select("COUNT(*)"); + return sql; + } + + public static Sql SelectAll(this Sql sql) + { + sql.Select("*"); + return sql; + } + + public static Sql Select(this Sql sql, Func refexpr = null) + { + var pd = sql.SqlContext.PocoDataFactory.ForType(typeof (T)); + + var tableName = pd.TableInfo.TableName; + var columns = pd.QueryColumns.Select(x => GetColumn(sql.SqlContext.DatabaseType, + tableName, + x.Value.ColumnName, + string.IsNullOrEmpty(x.Value.ColumnAlias) ? x.Value.MemberInfoKey : x.Value.ColumnAlias)); + + sql.Select(string.Join(", ", columns)); + + if (refexpr == null) return sql; + refexpr(new RefSql(sql, null)); + return sql; + } + + /// + /// + /// + /// + /// + /// + /// The name of the DTO reference. + /// The name of the table alias. + /// + /// + /// Select<Foo>() produces: [foo].[value] AS [Foo_Value] + /// With tableAlias: [tableAlias].[value] AS [Foo_Value] + /// With referenceName: [foo].[value] AS [referenceName_Value] + /// + public static RefSql Select(this RefSql refSql, Func refexpr = null, string referenceName = null, string tableAlias = null) + { + if (referenceName == null) referenceName = typeof (T).Name; + if (refSql.Prefix != null) referenceName = refSql.Prefix + PocoData.Separator + referenceName; + var pd = refSql.Sql.SqlContext.PocoDataFactory.ForType(typeof (T)); + + var tableName = tableAlias ?? pd.TableInfo.TableName; + var columns = pd.QueryColumns.Select(x => GetColumn(refSql.Sql.SqlContext.DatabaseType, + tableName, + x.Value.ColumnName, + string.IsNullOrEmpty(x.Value.ColumnAlias) ? x.Value.MemberInfoKey : x.Value.ColumnAlias, + referenceName)); + + refSql.Sql.Append(", " + string.Join(", ", columns)); + + if (refexpr == null) return refSql; + refexpr(new RefSql(refSql.Sql, referenceName)); + return refSql; + } + + public class RefSql + { + public RefSql(Sql sql, string prefix) + { + Sql = sql; + Prefix = prefix; + } + + public Sql Sql { get; } + public string Prefix { get; } + } + + private static string GetColumn(DatabaseType dbType, string tableName, string columnName, string columnAlias, string referenceName = null) + { + tableName = dbType.EscapeTableName(tableName); + columnName = dbType.EscapeSqlIdentifier(columnName); + columnAlias = dbType.EscapeSqlIdentifier((referenceName == null ? "" : (referenceName + "__")) + columnAlias); + return tableName + "." + columnName + " AS " + columnAlias; + } + + #endregion + } +} diff --git a/src/Umbraco.Core/Persistence/UnitOfWork/PetaPocoUnitOfWork.cs b/src/Umbraco.Core/Persistence/UnitOfWork/NPocoUnitOfWork.cs similarity index 88% rename from src/Umbraco.Core/Persistence/UnitOfWork/PetaPocoUnitOfWork.cs rename to src/Umbraco.Core/Persistence/UnitOfWork/NPocoUnitOfWork.cs index a5337e854c..5b6af0b4c0 100644 --- a/src/Umbraco.Core/Persistence/UnitOfWork/PetaPocoUnitOfWork.cs +++ b/src/Umbraco.Core/Persistence/UnitOfWork/NPocoUnitOfWork.cs @@ -1,183 +1,183 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using Umbraco.Core.Models.EntityBase; - -namespace Umbraco.Core.Persistence.UnitOfWork -{ - /// - /// Represents the Unit of Work implementation for PetaPoco - /// - internal class PetaPocoUnitOfWork : DisposableObject, IDatabaseUnitOfWork - { - - /// - /// Used for testing - /// - internal Guid InstanceId { get; private set; } - - private Guid _key; - private readonly Queue _operations = new Queue(); - - /// - /// Creates a new unit of work instance - /// - /// - /// - /// This should normally not be used directly and should be created with the UnitOfWorkProvider - /// - internal PetaPocoUnitOfWork(UmbracoDatabase database) - { - Database = database; - _key = Guid.NewGuid(); - InstanceId = Guid.NewGuid(); - } - - /// - /// Registers an instance to be added through this - /// - /// The - /// The participating in the transaction - public void RegisterAdded(IEntity entity, IUnitOfWorkRepository repository) - { - _operations.Enqueue(new Operation - { - Entity = entity, - Repository = repository, - Type = TransactionType.Insert - }); - } - - /// - /// Registers an instance to be changed through this - /// - /// The - /// The participating in the transaction - public void RegisterChanged(IEntity entity, IUnitOfWorkRepository repository) - { - _operations.Enqueue( - new Operation - { - Entity = entity, - Repository = repository, - Type = TransactionType.Update - }); - } - - /// - /// Registers an instance to be removed through this - /// - /// The - /// The participating in the transaction - public void RegisterRemoved(IEntity entity, IUnitOfWorkRepository repository) - { - _operations.Enqueue( - new Operation - { - Entity = entity, - Repository = repository, - Type = TransactionType.Delete - }); - } - - /// - /// Commits all batched changes within the scope of a PetaPoco transaction - /// - /// - /// Unlike a typical unit of work, this UOW will let you commit more than once since a new transaction is creaed per - /// Commit() call instead of having one Transaction per UOW. - /// - public void Commit() - { - Commit(null); - } - - /// - /// Commits all batched changes within the scope of a PetaPoco transaction - /// - /// - /// Allows you to set a callback which is executed before the transaction is committed, allow you to add additional SQL - /// operations to the overall commit process after the queue has been processed. - /// - internal void Commit(Action transactionCompleting) - { - using (var transaction = Database.GetTransaction()) - { - while (_operations.Count > 0) - { - var operation = _operations.Dequeue(); - switch (operation.Type) - { - case TransactionType.Insert: - operation.Repository.PersistNewItem(operation.Entity); - break; - case TransactionType.Delete: - operation.Repository.PersistDeletedItem(operation.Entity); - break; - case TransactionType.Update: - operation.Repository.PersistUpdatedItem(operation.Entity); - break; - } - } - - //Execute the callback if there is one - if (transactionCompleting != null) - { - transactionCompleting(Database); - } - - transaction.Complete(); - } - - // Clear everything - _operations.Clear(); - _key = Guid.NewGuid(); - } - - public object Key - { - get { return _key; } - } - - public UmbracoDatabase Database { get; private set; } - - #region Operation - - /// - /// Provides a snapshot of an entity and the repository reference it belongs to. - /// - private sealed class Operation - { - /// - /// Gets or sets the entity. - /// - /// The entity. - public IEntity Entity { get; set; } - - /// - /// Gets or sets the repository. - /// - /// The repository. - public IUnitOfWorkRepository Repository { get; set; } - - /// - /// Gets or sets the type of operation. - /// - /// The type of operation. - public TransactionType Type { get; set; } - } - - #endregion - - /// - /// Ensures disposable objects are disposed - /// - /// - /// Ensures that the Transaction instance is disposed of - /// - protected override void DisposeResources() - { - _operations.Clear(); - } - } +using System; +using System.Collections.Generic; +using NPoco; +using Umbraco.Core.Models.EntityBase; + +namespace Umbraco.Core.Persistence.UnitOfWork +{ + /// + /// Represents the Unit of Work implementation for NPoco + /// + internal class NPocoUnitOfWork : DisposableObject, IDatabaseUnitOfWork + { + + /// + /// Used for testing + /// + internal Guid InstanceId { get; private set; } + + private Guid _key; + private readonly Queue _operations = new Queue(); + + /// + /// Creates a new unit of work instance + /// + /// + /// + /// This should normally not be used directly and should be created with the UnitOfWorkProvider + /// + internal NPocoUnitOfWork(UmbracoDatabase database) + { + Database = database; + _key = Guid.NewGuid(); + InstanceId = Guid.NewGuid(); + } + + /// + /// Registers an instance to be added through this + /// + /// The + /// The participating in the transaction + public void RegisterAdded(IEntity entity, IUnitOfWorkRepository repository) + { + _operations.Enqueue(new Operation + { + Entity = entity, + Repository = repository, + Type = TransactionType.Insert + }); + } + + /// + /// Registers an instance to be changed through this + /// + /// The + /// The participating in the transaction + public void RegisterChanged(IEntity entity, IUnitOfWorkRepository repository) + { + _operations.Enqueue( + new Operation + { + Entity = entity, + Repository = repository, + Type = TransactionType.Update + }); + } + + /// + /// Registers an instance to be removed through this + /// + /// The + /// The participating in the transaction + public void RegisterRemoved(IEntity entity, IUnitOfWorkRepository repository) + { + _operations.Enqueue( + new Operation + { + Entity = entity, + Repository = repository, + Type = TransactionType.Delete + }); + } + + /// + /// Commits all batched changes within the scope of a NPoco . + /// + /// + /// Unlike a typical unit of work, this UOW will let you commit more than once since a new transaction is creaed per + /// Commit() call instead of having one transaction per UOW. + /// + public void Commit() + { + Commit(null); + } + + /// + /// Commits all batched changes within the scope of a NPoco . + /// + /// + /// Allows you to set a callback which is executed before the transaction is committed, allow you to add additional SQL + /// operations to the overall commit process after the queue has been processed. + /// + internal void Commit(Action transactionCompleting) + { + using (var transaction = Database.GetTransaction()) + { + while (_operations.Count > 0) + { + var operation = _operations.Dequeue(); + switch (operation.Type) + { + case TransactionType.Insert: + operation.Repository.PersistNewItem(operation.Entity); + break; + case TransactionType.Delete: + operation.Repository.PersistDeletedItem(operation.Entity); + break; + case TransactionType.Update: + operation.Repository.PersistUpdatedItem(operation.Entity); + break; + } + } + + //Execute the callback if there is one + if (transactionCompleting != null) + { + transactionCompleting(Database); + } + + transaction.Complete(); + } + + // Clear everything + _operations.Clear(); + _key = Guid.NewGuid(); + } + + public object Key + { + get { return _key; } + } + + public UmbracoDatabase Database { get; private set; } + + #region Operation + + /// + /// Provides a snapshot of an entity and the repository reference it belongs to. + /// + private sealed class Operation + { + /// + /// Gets or sets the entity. + /// + /// The entity. + public IEntity Entity { get; set; } + + /// + /// Gets or sets the repository. + /// + /// The repository. + public IUnitOfWorkRepository Repository { get; set; } + + /// + /// Gets or sets the type of operation. + /// + /// The type of operation. + public TransactionType Type { get; set; } + } + + #endregion + + /// + /// Ensures disposable objects are disposed + /// + /// + /// Ensures that the Transaction instance is disposed of + /// + protected override void DisposeResources() + { + _operations.Clear(); + } + } } \ No newline at end of file diff --git a/src/Umbraco.Core/Persistence/UnitOfWork/NPocoUnitOfWorkProvider.cs b/src/Umbraco.Core/Persistence/UnitOfWork/NPocoUnitOfWorkProvider.cs new file mode 100644 index 0000000000..c8407eb08d --- /dev/null +++ b/src/Umbraco.Core/Persistence/UnitOfWork/NPocoUnitOfWorkProvider.cs @@ -0,0 +1,47 @@ +using Umbraco.Core.Configuration; +using Umbraco.Core.Logging; + +namespace Umbraco.Core.Persistence.UnitOfWork +{ + /// + /// Represents a Unit of Work Provider for creating a . + /// + public class NPocoUnitOfWorkProvider : IDatabaseUnitOfWorkProvider + { + private readonly IDatabaseFactory _dbFactory; + + /// + /// Initializes a new instance of the class with an . + /// + /// + public NPocoUnitOfWorkProvider(IDatabaseFactory dbFactory) + { + Mandate.ParameterNotNull(dbFactory, "dbFactory"); + _dbFactory = dbFactory; + } + + // for unit tests only + // will re-create a new DefaultDatabaseFactory each time it is called + internal NPocoUnitOfWorkProvider(ILogger logger) + : this(new DefaultDatabaseFactory(GlobalSettings.UmbracoConnectionName, logger)) + { } + + #region Implementation of IUnitOfWorkProvider + + /// + /// Creates a unit of work around a database obtained from the database factory. + /// + /// A unit of work. + /// The unit of work will execute on the current database returned by the database factory. + public IDatabaseUnitOfWork GetUnitOfWork() + { + // get a database from the factory - might be the "ambient" database eg + // the one that's enlisted with the HttpContext - so it's not always a + // "new" database. + var database = _dbFactory.CreateDatabase(); + return new NPocoUnitOfWork(database); + } + + #endregion + } +} \ No newline at end of file diff --git a/src/Umbraco.Core/Persistence/UnitOfWork/PetaPocoUnitOfWorkProvider.cs b/src/Umbraco.Core/Persistence/UnitOfWork/PetaPocoUnitOfWorkProvider.cs deleted file mode 100644 index 65dc09b418..0000000000 --- a/src/Umbraco.Core/Persistence/UnitOfWork/PetaPocoUnitOfWorkProvider.cs +++ /dev/null @@ -1,71 +0,0 @@ -using System; -using Umbraco.Core.Configuration; -using Umbraco.Core.Logging; - -namespace Umbraco.Core.Persistence.UnitOfWork -{ - /// - /// Represents a Unit of Work Provider for creating a - /// - public class PetaPocoUnitOfWorkProvider : IDatabaseUnitOfWorkProvider - { - private readonly IDatabaseFactory _dbFactory; - - /// - /// Parameterless constructor uses defaults - /// - public PetaPocoUnitOfWorkProvider(ILogger logger) - : this(new DefaultDatabaseFactory(GlobalSettings.UmbracoConnectionName, logger)) - { - - } - - /// - /// Constructor accepting custom connectino string and provider name - /// - /// - /// Connection String to use with Database - /// Database Provider for the Connection String - public PetaPocoUnitOfWorkProvider(ILogger logger, string connectionString, string providerName) - : this(new DefaultDatabaseFactory(connectionString, providerName, logger)) - { } - - /// - /// Constructor accepting an IDatabaseFactory instance - /// - /// - public PetaPocoUnitOfWorkProvider(IDatabaseFactory dbFactory) - { - Mandate.ParameterNotNull(dbFactory, "dbFactory"); - _dbFactory = dbFactory; - } - - #region Implementation of IUnitOfWorkProvider - - /// - /// Creates a Unit of work with a new UmbracoDatabase instance for the work item/transaction. - /// - /// - /// - /// Each PetaPoco UOW uses it's own Database object, not the shared Database object that comes from - /// the ApplicationContext.Current.DatabaseContext.Database. This is because each transaction should use it's own Database - /// and we Dispose of this Database object when the UOW is disposed. - /// - public IDatabaseUnitOfWork GetUnitOfWork() - { - return new PetaPocoUnitOfWork(_dbFactory.CreateDatabase()); - } - - #endregion - - /// - /// Static helper method to return a new unit of work - /// - /// - internal static IDatabaseUnitOfWork CreateUnitOfWork(ILogger logger) - { - var provider = new PetaPocoUnitOfWorkProvider(logger); - return provider.GetUnitOfWork(); - } - } -} \ No newline at end of file diff --git a/src/Umbraco.Core/Security/BackOfficeUserManager.cs b/src/Umbraco.Core/Security/BackOfficeUserManager.cs index dfe59e1783..e48079c10b 100644 --- a/src/Umbraco.Core/Security/BackOfficeUserManager.cs +++ b/src/Umbraco.Core/Security/BackOfficeUserManager.cs @@ -118,6 +118,8 @@ namespace Umbraco.Core.Security //custom identity factory for creating the identity object for which we auth against in the back office manager.ClaimsIdentityFactory = new BackOfficeClaimsIdentityFactory(); + manager.EmailService = new EmailService(); + //NOTE: Not implementing these, if people need custom 2 factor auth, they'll need to implement their own UserStore to suport it //// Register two factor authentication providers. This application uses Phone and Emails as a step of receiving a code for verifying the user @@ -132,7 +134,6 @@ namespace Umbraco.Core.Security // BodyFormat = "Your security code is: {0}" //}); - //manager.EmailService = new EmailService(); //manager.SmsService = new SmsService(); } diff --git a/src/Umbraco.Core/Security/EmailService.cs b/src/Umbraco.Core/Security/EmailService.cs new file mode 100644 index 0000000000..93864aa37c --- /dev/null +++ b/src/Umbraco.Core/Security/EmailService.cs @@ -0,0 +1,26 @@ +using System.Net.Mail; +using System.Threading.Tasks; +using Microsoft.AspNet.Identity; + +namespace Umbraco.Core.Security +{ + public class EmailService : IIdentityMessageService + { + public async Task SendAsync(IdentityMessage message) + { + using (var client = new SmtpClient()) + using (var mailMessage = new MailMessage()) + { + mailMessage.Body = message.Body; + mailMessage.To.Add(message.Destination); + mailMessage.Subject = message.Subject; + + //TODO: This check could be nicer but that is the way it is currently + mailMessage.IsBodyHtml = message.Body.IsNullOrWhiteSpace() == false + && message.Body.Contains("<") && message.Body.Contains("/>"); + + await client.SendMailAsync(mailMessage); + } + } + } +} diff --git a/src/Umbraco.Core/Services/ContentService.cs b/src/Umbraco.Core/Services/ContentService.cs index 6a9d447938..f213a584be 100644 --- a/src/Umbraco.Core/Services/ContentService.cs +++ b/src/Umbraco.Core/Services/ContentService.cs @@ -236,7 +236,7 @@ namespace Umbraco.Core.Services public IContent CreateContentWithIdentity(string name, int parentId, string contentTypeAlias, int userId = 0) { var contentType = FindContentTypeByAlias(contentTypeAlias); - var content = new Content(name, parentId, contentType); + var content = new Content(name, parentId, contentType); //NOTE: I really hate the notion of these Creating/Created events - they are so inconsistent, I've only just found // out that in these 'WithIdentity' methods, the Saving/Saved events were not fired, wtf. Anyways, they're added now. @@ -487,27 +487,6 @@ namespace Umbraco.Core.Services } } - [Obsolete("Use the overload with 'long' parameter types instead")] - [EditorBrowsable(EditorBrowsableState.Never)] - public IEnumerable GetPagedChildren(int id, int pageIndex, int pageSize, out int totalChildren, - string orderBy, Direction orderDirection, string filter = "") - { - Mandate.ParameterCondition(pageIndex >= 0, "pageIndex"); - Mandate.ParameterCondition(pageSize > 0, "pageSize"); - using (var repository = RepositoryFactory.CreateContentRepository(UowProvider.GetUnitOfWork())) - { - //if the id is System Root, then just get all - if (id != Constants.System.Root) - { - repository.Query.Where(x => x.ParentId == id); - } - long total; - var contents = repository.GetPagedResultsByQuery(repository.Query, pageIndex, pageSize, out total, orderBy, orderDirection, filter); - totalChildren = Convert.ToInt32(total); - return contents; - } - } - /// /// Gets a collection of objects by Parent Id /// @@ -521,6 +500,24 @@ namespace Umbraco.Core.Services /// An Enumerable list of objects public IEnumerable GetPagedChildren(int id, long pageIndex, int pageSize, out long totalChildren, string orderBy, Direction orderDirection, string filter = "") + { + return GetPagedChildren(id, pageIndex, pageSize, out totalChildren, orderBy, orderDirection, true, filter); + } + + /// + /// Gets a collection of objects by Parent Id + /// + /// Id of the Parent to retrieve Children from + /// Page index (zero based) + /// Page size + /// Total records query would return without paging + /// Field to order by + /// Direction to order by + /// Flag to indicate when ordering by system field + /// Search text filter + /// An Enumerable list of objects + public IEnumerable GetPagedChildren(int id, long pageIndex, int pageSize, out long totalChildren, + string orderBy, Direction orderDirection, bool orderBySystemField, string filter) { Mandate.ParameterCondition(pageIndex >= 0, "pageIndex"); Mandate.ParameterCondition(pageSize > 0, "pageSize"); @@ -533,32 +530,12 @@ namespace Umbraco.Core.Services { query.Where(x => x.ParentId == id); } - var contents = repository.GetPagedResultsByQuery(query, pageIndex, pageSize, out totalChildren, orderBy, orderDirection, filter); + var contents = repository.GetPagedResultsByQuery(query, pageIndex, pageSize, out totalChildren, orderBy, orderDirection, orderBySystemField, filter); return contents; } } - [Obsolete("Use the overload with 'long' parameter types instead")] - [EditorBrowsable(EditorBrowsableState.Never)] - public IEnumerable GetPagedDescendants(int id, int pageIndex, int pageSize, out int totalChildren, string orderBy = "Path", Direction orderDirection = Direction.Ascending, string filter = "") - { - Mandate.ParameterCondition(pageIndex >= 0, "pageIndex"); - Mandate.ParameterCondition(pageSize > 0, "pageSize"); - using (var repository = RepositoryFactory.CreateContentRepository(UowProvider.GetUnitOfWork())) - { - //if the id is System Root, then just get all - if (id != Constants.System.Root) - { - repository.Query.Where(x => x.Path.SqlContains(string.Format(",{0},", id), TextColumnType.NVarchar)); - } - long total; - var contents = repository.GetPagedResultsByQuery(repository.Query, pageIndex, pageSize, out total, orderBy, orderDirection, filter); - totalChildren = Convert.ToInt32(total); - return contents; - } - } - /// /// Gets a collection of objects by Parent Id /// @@ -569,8 +546,25 @@ namespace Umbraco.Core.Services /// Field to order by /// Direction to order by /// Search text filter - /// An Enumerable list of objects + /// An Enumerable list of objects public IEnumerable GetPagedDescendants(int id, long pageIndex, int pageSize, out long totalChildren, string orderBy = "Path", Direction orderDirection = Direction.Ascending, string filter = "") + { + return GetPagedDescendants(id, pageIndex, pageSize, out totalChildren, orderBy, orderDirection, true, filter); + } + + /// + /// Gets a collection of objects by Parent Id + /// + /// Id of the Parent to retrieve Descendants from + /// Page number + /// Page size + /// Total records query would return without paging + /// Field to order by + /// Direction to order by + /// Flag to indicate when ordering by system field + /// Search text filter + /// An Enumerable list of objects + public IEnumerable GetPagedDescendants(int id, long pageIndex, int pageSize, out long totalChildren, string orderBy, Direction orderDirection, bool orderBySystemField, string filter) { Mandate.ParameterCondition(pageIndex >= 0, "pageIndex"); Mandate.ParameterCondition(pageSize > 0, "pageSize"); @@ -583,7 +577,7 @@ namespace Umbraco.Core.Services { query.Where(x => x.Path.SqlContains(string.Format(",{0},", id), TextColumnType.NVarchar)); } - var contents = repository.GetPagedResultsByQuery(query, pageIndex, pageSize, out totalChildren, orderBy, orderDirection, filter); + var contents = repository.GetPagedResultsByQuery(query, pageIndex, pageSize, out totalChildren, orderBy, orderDirection, orderBySystemField, filter); return contents; } @@ -907,7 +901,7 @@ namespace Umbraco.Core.Services { var originalPath = content.Path; - if (Trashing.IsRaisedEventCancelled( + if (Trashing.IsRaisedEventCancelled( new MoveEventArgs(evtMsgs, new MoveEventInfo(content, originalPath, Constants.System.RecycleBinContent)), this)) { @@ -1023,7 +1017,7 @@ namespace Umbraco.Core.Services /// True if unpublishing succeeded, otherwise False public bool UnPublish(IContent content, int userId = 0) { - return ((IContentServiceOperations) this).UnPublish(content, userId).Success; + return ((IContentServiceOperations)this).UnPublish(content, userId).Success; } /// @@ -1144,7 +1138,7 @@ namespace Umbraco.Core.Services using (new WriteLock(Locker)) { - if (Deleting.IsRaisedEventCancelled( + if (Deleting.IsRaisedEventCancelled( new DeleteEventArgs(content, evtMsgs), this)) { @@ -1169,10 +1163,10 @@ namespace Umbraco.Core.Services { repository.Delete(content); uow.Commit(); - + var args = new DeleteEventArgs(content, false, evtMsgs); Deleted.RaiseEvent(args, this); - + //remove any flagged media files repository.DeleteMediaFiles(args.MediaFilesToDelete); } @@ -1351,7 +1345,7 @@ namespace Umbraco.Core.Services /// Optional Id of the User deleting the Content public void MoveToRecycleBin(IContent content, int userId = 0) { - ((IContentServiceOperations) this).MoveToRecycleBin(content, userId); + ((IContentServiceOperations)this).MoveToRecycleBin(content, userId); } /// @@ -1655,7 +1649,7 @@ namespace Umbraco.Core.Services //TODO: This should not be an inner operation, but if we do this, it cannot raise events and cannot be cancellable! _publishingStrategy.PublishingFinalized(shouldBePublished, false); } - + Audit(AuditType.Sort, "Sorting content performed by user", userId, 0); @@ -1932,13 +1926,13 @@ namespace Umbraco.Core.Services content = newest; var evtMsgs = EventMessagesFactory.Get(); - + var published = content.Published ? content : GetPublishedVersion(content.Id); // get the published version if (published == null) { return Attempt.Succeed(new UnPublishStatus(content, UnPublishedStatusType.SuccessAlreadyUnPublished, evtMsgs)); // already unpublished } - + var unpublished = _publishingStrategy.UnPublish(content, userId); if (unpublished == false) return Attempt.Fail(new UnPublishStatus(content, UnPublishedStatusType.FailedCancelledByEvent, evtMsgs)); @@ -2076,7 +2070,7 @@ namespace Umbraco.Core.Services if (raiseEvents) { - if (Saving.IsRaisedEventCancelled( + if (Saving.IsRaisedEventCancelled( new SaveEventArgs(content, evtMsgs), this)) { diff --git a/src/Umbraco.Core/Services/EntityService.cs b/src/Umbraco.Core/Services/EntityService.cs index 4314308f41..5f24eac64b 100644 --- a/src/Umbraco.Core/Services/EntityService.cs +++ b/src/Umbraco.Core/Services/EntityService.cs @@ -1,6 +1,7 @@ using System; using System.Collections.Generic; using System.Linq; +using NPoco; using Umbraco.Core.Cache; using Umbraco.Core.CodeAnnotations; using Umbraco.Core.Events; @@ -86,9 +87,10 @@ namespace Umbraco.Core.Services case UmbracoObjectTypes.DataType: case UmbracoObjectTypes.DocumentTypeContainer: return uow.Database.ExecuteScalar( - new Sql().Select("id") - .From(RepositoryFactory.SqlSyntax) - .Where(RepositoryFactory.SqlSyntax, dto => dto.UniqueId == key)); + NPoco.Sql.BuilderFor(new SqlContext(RepositoryFactory.SqlSyntax, uow.Database)) + .Select("id") + .From() + .Where(dto => dto.UniqueId == key)); case UmbracoObjectTypes.RecycleBin: case UmbracoObjectTypes.Stylesheet: case UmbracoObjectTypes.MemberGroup: @@ -127,9 +129,10 @@ namespace Umbraco.Core.Services case UmbracoObjectTypes.Member: case UmbracoObjectTypes.DataType: return uow.Database.ExecuteScalar( - new Sql().Select("uniqueID") - .From(RepositoryFactory.SqlSyntax) - .Where(RepositoryFactory.SqlSyntax, dto => dto.NodeId == id)); + NPoco.Sql.BuilderFor(new SqlContext(RepositoryFactory.SqlSyntax, uow.Database)) + .Select("uniqueID") + .From() + .Where(dto => dto.NodeId == id)); case UmbracoObjectTypes.RecycleBin: case UmbracoObjectTypes.Stylesheet: case UmbracoObjectTypes.MemberGroup: @@ -342,7 +345,7 @@ namespace Umbraco.Core.Services using (var repository = RepositoryFactory.CreateEntityRepository(UowProvider.GetUnitOfWork())) { var query = repository.Query.Where(x => x.ParentId == parentId); - var contents = repository.GetByQuery(query, objectTypeId); + var contents = repository.GetByQuery(query, objectTypeId).ToList(); // run within using! return contents; } @@ -492,7 +495,10 @@ namespace Umbraco.Core.Services { using (var uow = UowProvider.GetUnitOfWork()) { - var sql = new Sql().Select("nodeObjectType").From(RepositoryFactory.SqlSyntax).Where(RepositoryFactory.SqlSyntax, x => x.NodeId == id); + var sql = NPoco.Sql.BuilderFor(new SqlContext(RepositoryFactory.SqlSyntax, uow.Database)) + .Select("nodeObjectType") + .From() + .Where(x => x.NodeId == id); var nodeObjectTypeId = uow.Database.ExecuteScalar(sql); var objectTypeId = nodeObjectTypeId; return UmbracoObjectTypesExtensions.GetUmbracoObjectType(objectTypeId); @@ -508,7 +514,10 @@ namespace Umbraco.Core.Services { using (var uow = UowProvider.GetUnitOfWork()) { - var sql = new Sql().Select("nodeObjectType").From(RepositoryFactory.SqlSyntax).Where(RepositoryFactory.SqlSyntax, x => x.UniqueId == key); + var sql = NPoco.Sql.BuilderFor(new SqlContext(RepositoryFactory.SqlSyntax, uow.Database)) + .Select("nodeObjectType") + .From() + .Where(x => x.UniqueId == key); var nodeObjectTypeId = uow.Database.ExecuteScalar(sql); var objectTypeId = nodeObjectTypeId; return UmbracoObjectTypesExtensions.GetUmbracoObjectType(objectTypeId); diff --git a/src/Umbraco.Core/Services/IContentService.cs b/src/Umbraco.Core/Services/IContentService.cs index fd46bf1008..625f917ffe 100644 --- a/src/Umbraco.Core/Services/IContentService.cs +++ b/src/Umbraco.Core/Services/IContentService.cs @@ -215,12 +215,7 @@ namespace Umbraco.Core.Services /// Id of the Parent to retrieve Children from /// An Enumerable list of objects IEnumerable GetChildren(int id); - - [Obsolete("Use the overload with 'long' parameter types instead")] - [EditorBrowsable(EditorBrowsableState.Never)] - IEnumerable GetPagedChildren(int id, int pageIndex, int pageSize, out int totalRecords, - string orderBy = "SortOrder", Direction orderDirection = Direction.Ascending, string filter = ""); - + /// /// Gets a collection of objects by Parent Id /// @@ -235,11 +230,21 @@ namespace Umbraco.Core.Services IEnumerable GetPagedChildren(int id, long pageIndex, int pageSize, out long totalRecords, string orderBy = "SortOrder", Direction orderDirection = Direction.Ascending, string filter = ""); - [Obsolete("Use the overload with 'long' parameter types instead")] - [EditorBrowsable(EditorBrowsableState.Never)] - IEnumerable GetPagedDescendants(int id, int pageIndex, int pageSize, out int totalRecords, - string orderBy = "Path", Direction orderDirection = Direction.Ascending, string filter = ""); - + /// + /// Gets a collection of objects by Parent Id + /// + /// Id of the Parent to retrieve Children from + /// Page number + /// Page size + /// Total records query would return without paging + /// Field to order by + /// Direction to order by + /// Flag to indicate when ordering by system field + /// Search text filter + /// An Enumerable list of objects + IEnumerable GetPagedChildren(int id, long pageIndex, int pageSize, out long totalRecords, + string orderBy, Direction orderDirection, bool orderBySystemField, string filter); + /// /// Gets a collection of objects by Parent Id /// @@ -253,7 +258,22 @@ namespace Umbraco.Core.Services /// An Enumerable list of objects IEnumerable GetPagedDescendants(int id, long pageIndex, int pageSize, out long totalRecords, string orderBy = "Path", Direction orderDirection = Direction.Ascending, string filter = ""); - + + /// + /// Gets a collection of objects by Parent Id + /// + /// Id of the Parent to retrieve Descendants from + /// Page number + /// Page size + /// Total records query would return without paging + /// Field to order by + /// Direction to order by + /// Flag to indicate when ordering by system field + /// Search text filter + /// An Enumerable list of objects + IEnumerable GetPagedDescendants(int id, long pageIndex, int pageSize, out long totalRecords, + string orderBy, Direction orderDirection, bool orderBySystemField, string filter); + /// /// Gets a collection of an objects versions by its Id /// @@ -284,7 +304,7 @@ namespace Umbraco.Core.Services /// /// An Enumerable list of objects IEnumerable GetContentInRecycleBin(); - + /// /// Saves a single object /// @@ -483,7 +503,7 @@ namespace Umbraco.Core.Services /// Optional boolean indicating whether or not to raise save events. /// True if publishing succeeded, otherwise False Attempt SaveAndPublishWithStatus(IContent content, int userId = 0, bool raiseEvents = true); - + /// /// Permanently deletes an object. /// diff --git a/src/Umbraco.Core/Services/IMediaService.cs b/src/Umbraco.Core/Services/IMediaService.cs index d104b95ddc..645bcfd1e0 100644 --- a/src/Umbraco.Core/Services/IMediaService.cs +++ b/src/Umbraco.Core/Services/IMediaService.cs @@ -117,12 +117,7 @@ namespace Umbraco.Core.Services /// Id of the Parent to retrieve Children from /// An Enumerable list of objects IEnumerable GetChildren(int id); - - [Obsolete("Use the overload with 'long' parameter types instead")] - [EditorBrowsable(EditorBrowsableState.Never)] - IEnumerable GetPagedChildren(int id, int pageIndex, int pageSize, out int totalRecords, - string orderBy = "SortOrder", Direction orderDirection = Direction.Ascending, string filter = ""); - + /// /// Gets a collection of objects by Parent Id /// @@ -137,11 +132,21 @@ namespace Umbraco.Core.Services IEnumerable GetPagedChildren(int id, long pageIndex, int pageSize, out long totalRecords, string orderBy = "SortOrder", Direction orderDirection = Direction.Ascending, string filter = ""); - [Obsolete("Use the overload with 'long' parameter types instead")] - [EditorBrowsable(EditorBrowsableState.Never)] - IEnumerable GetPagedDescendants(int id, int pageIndex, int pageSize, out int totalRecords, - string orderBy = "Path", Direction orderDirection = Direction.Ascending, string filter = ""); - + /// + /// Gets a collection of objects by Parent Id + /// + /// Id of the Parent to retrieve Children from + /// Page number + /// Page size + /// Total records query would return without paging + /// Field to order by + /// Direction to order by + /// Flag to indicate when ordering by system field + /// Search text filter + /// An Enumerable list of objects + IEnumerable GetPagedChildren(int id, long pageIndex, int pageSize, out long totalRecords, + string orderBy, Direction orderDirection, bool orderBySystemField, string filter); + /// /// Gets a collection of objects by Parent Id /// @@ -156,6 +161,21 @@ namespace Umbraco.Core.Services IEnumerable GetPagedDescendants(int id, long pageIndex, int pageSize, out long totalRecords, string orderBy = "Path", Direction orderDirection = Direction.Ascending, string filter = ""); + /// + /// Gets a collection of objects by Parent Id + /// + /// Id of the Parent to retrieve Descendants from + /// Page number + /// Page size + /// Total records query would return without paging + /// Field to order by + /// Direction to order by + /// Flag to indicate when ordering by system field + /// Search text filter + /// An Enumerable list of objects + IEnumerable GetPagedDescendants(int id, long pageIndex, int pageSize, out long totalRecords, + string orderBy, Direction orderDirection, bool orderBySystemField, string filter); + /// /// Gets descendants of a object by its Id /// @@ -220,7 +240,7 @@ namespace Umbraco.Core.Services /// The to delete /// Id of the User deleting the Media void Delete(IMedia media, int userId = 0); - + /// /// Saves a single object /// diff --git a/src/Umbraco.Core/Services/IMemberService.cs b/src/Umbraco.Core/Services/IMemberService.cs index 20eef54b3c..a893d89feb 100644 --- a/src/Umbraco.Core/Services/IMemberService.cs +++ b/src/Umbraco.Core/Services/IMemberService.cs @@ -34,14 +34,30 @@ namespace Umbraco.Core.Services /// Current page index /// Size of the page /// Total number of records found (out) - /// - /// + /// Field to order by + /// Direction to order by /// - /// + /// Search text filter /// IEnumerable GetAll(long pageIndex, int pageSize, out long totalRecords, string orderBy, Direction orderDirection, string memberTypeAlias = null, string filter = ""); - + + /// + /// Gets a list of paged objects + /// + /// An can be of type + /// Current page index + /// Size of the page + /// Total number of records found (out) + /// Field to order by + /// Direction to order by + /// Flag to indicate when ordering by system field + /// + /// Search text filter + /// + IEnumerable GetAll(long pageIndex, int pageSize, out long totalRecords, + string orderBy, Direction orderDirection, bool orderBySystemField, string memberTypeAlias, string filter); + /// /// Creates an object without persisting it /// @@ -91,7 +107,7 @@ namespace Umbraco.Core.Services /// MemberType the Member should be based on /// IMember CreateMemberWithIdentity(string username, string email, string name, IMemberType memberType); - + /// /// This is simply a helper method which essentially just wraps the MembershipProvider's ChangePassword method /// @@ -115,7 +131,7 @@ namespace Umbraco.Core.Services /// Id of the Member /// True if the Member exists otherwise False bool Exists(int id); - + /// /// Gets a Member by the unique key /// @@ -160,7 +176,7 @@ namespace Umbraco.Core.Services /// Optional list of Member Ids /// IEnumerable GetAllMembers(params int[] ids); - + /// /// Delete Members of the specified MemberType id /// diff --git a/src/Umbraco.Core/Services/MediaService.cs b/src/Umbraco.Core/Services/MediaService.cs index 794765d864..2a459174c0 100644 --- a/src/Umbraco.Core/Services/MediaService.cs +++ b/src/Umbraco.Core/Services/MediaService.cs @@ -395,26 +395,6 @@ namespace Umbraco.Core.Services } } - [Obsolete("Use the overload with 'long' parameter types instead")] - [EditorBrowsable(EditorBrowsableState.Never)] - public IEnumerable GetPagedChildren(int id, int pageIndex, int pageSize, out int totalChildren, - string orderBy, Direction orderDirection, string filter = "") - { - Mandate.ParameterCondition(pageIndex >= 0, "pageIndex"); - Mandate.ParameterCondition(pageSize > 0, "pageSize"); - using (var repository = RepositoryFactory.CreateMediaRepository(UowProvider.GetUnitOfWork())) - { - var query = repository.Query; - query.Where(x => x.ParentId == id); - - long total; - var medias = repository.GetPagedResultsByQuery(query, pageIndex, pageSize, out total, orderBy, orderDirection, filter); - - totalChildren = Convert.ToInt32(total); - return medias; - } - } - /// /// Gets a collection of objects by Parent Id /// @@ -427,7 +407,25 @@ namespace Umbraco.Core.Services /// Search text filter /// An Enumerable list of objects public IEnumerable GetPagedChildren(int id, long pageIndex, int pageSize, out long totalChildren, - string orderBy, Direction orderDirection, string filter = "") + string orderBy, Direction orderDirection, string filter = "") + { + return GetPagedChildren(id, pageIndex, pageSize, out totalChildren, orderBy, orderDirection, true, filter); + } + + /// + /// Gets a collection of objects by Parent Id + /// + /// Id of the Parent to retrieve Children from + /// Page index (zero based) + /// Page size + /// Total records query would return without paging + /// Field to order by + /// Direction to order by + /// Flag to indicate when ordering by system field + /// Search text filter + /// An Enumerable list of objects + public IEnumerable GetPagedChildren(int id, long pageIndex, int pageSize, out long totalChildren, + string orderBy, Direction orderDirection, bool orderBySystemField, string filter) { Mandate.ParameterCondition(pageIndex >= 0, "pageIndex"); Mandate.ParameterCondition(pageSize > 0, "pageSize"); @@ -435,34 +433,12 @@ namespace Umbraco.Core.Services { var query = repository.Query; query.Where(x => x.ParentId == id); - - var medias = repository.GetPagedResultsByQuery(query, pageIndex, pageSize, out totalChildren, orderBy, orderDirection, filter); + + var medias = repository.GetPagedResultsByQuery(query, pageIndex, pageSize, out totalChildren, orderBy, orderDirection, orderBySystemField, filter); return medias; } - } - - [Obsolete("Use the overload with 'long' parameter types instead")] - [EditorBrowsable(EditorBrowsableState.Never)] - public IEnumerable GetPagedDescendants(int id, int pageIndex, int pageSize, out int totalChildren, string orderBy = "Path", Direction orderDirection = Direction.Ascending, string filter = "") - { - Mandate.ParameterCondition(pageIndex >= 0, "pageIndex"); - Mandate.ParameterCondition(pageSize > 0, "pageSize"); - using (var repository = RepositoryFactory.CreateMediaRepository(UowProvider.GetUnitOfWork())) - { - - var query = repository.Query; - //if the id is -1, then just get all - if (id != -1) - { - query.Where(x => x.Path.SqlContains(string.Format(",{0},", id), TextColumnType.NVarchar)); - } - long total; - var contents = repository.GetPagedResultsByQuery(query, pageIndex, pageSize, out total, orderBy, orderDirection, filter); - totalChildren = Convert.ToInt32(total); - return contents; - } - } + } /// /// Gets a collection of objects by Parent Id @@ -476,6 +452,23 @@ namespace Umbraco.Core.Services /// Search text filter /// An Enumerable list of objects public IEnumerable GetPagedDescendants(int id, long pageIndex, int pageSize, out long totalChildren, string orderBy = "Path", Direction orderDirection = Direction.Ascending, string filter = "") + { + return GetPagedDescendants(id, pageIndex, pageSize, out totalChildren, orderBy, orderDirection, true, filter); + } + + /// + /// Gets a collection of objects by Parent Id + /// + /// Id of the Parent to retrieve Descendants from + /// Page number + /// Page size + /// Total records query would return without paging + /// Field to order by + /// Direction to order by + /// Flag to indicate when ordering by system field + /// Search text filter + /// An Enumerable list of objects + public IEnumerable GetPagedDescendants(int id, long pageIndex, int pageSize, out long totalChildren, string orderBy, Direction orderDirection, bool orderBySystemField, string filter) { Mandate.ParameterCondition(pageIndex >= 0, "pageIndex"); Mandate.ParameterCondition(pageSize > 0, "pageSize"); @@ -488,7 +481,7 @@ namespace Umbraco.Core.Services { query.Where(x => x.Path.SqlContains(string.Format(",{0},", id), TextColumnType.NVarchar)); } - var contents = repository.GetPagedResultsByQuery(query, pageIndex, pageSize, out totalChildren, orderBy, orderDirection, filter); + var contents = repository.GetPagedResultsByQuery(query, pageIndex, pageSize, out totalChildren, orderBy, orderDirection, orderBySystemField, filter); return contents; } @@ -699,7 +692,7 @@ namespace Umbraco.Core.Services /// Id of the User deleting the Media public void MoveToRecycleBin(IMedia media, int userId = 0) { - ((IMediaServiceOperations) this).MoveToRecycleBin(media, userId); + ((IMediaServiceOperations)this).MoveToRecycleBin(media, userId); } /// @@ -716,7 +709,7 @@ namespace Umbraco.Core.Services //TODO: IT would be much nicer to mass delete all in one trans in the repo level! var evtMsgs = EventMessagesFactory.Get(); - if (Deleting.IsRaisedEventCancelled( + if (Deleting.IsRaisedEventCancelled( new DeleteEventArgs(media, evtMsgs), this)) { return OperationStatus.Cancelled(evtMsgs); @@ -997,7 +990,7 @@ namespace Umbraco.Core.Services ((IMediaServiceOperations)this).Delete(media, userId); } - + /// /// Permanently deletes versions from an object prior to a specific date. @@ -1053,7 +1046,7 @@ namespace Umbraco.Core.Services Audit(AuditType.Delete, "Delete Media by version performed by user", userId, -1); } - + /// /// Saves a single object /// @@ -1062,7 +1055,7 @@ namespace Umbraco.Core.Services /// Optional boolean indicating whether or not to raise events. public void Save(IMedia media, int userId = 0, bool raiseEvents = true) { - ((IMediaServiceOperations)this).Save (media, userId, raiseEvents); + ((IMediaServiceOperations)this).Save(media, userId, raiseEvents); } /// diff --git a/src/Umbraco.Core/Services/MemberService.cs b/src/Umbraco.Core/Services/MemberService.cs index 753d21db86..b0b31e7279 100644 --- a/src/Umbraco.Core/Services/MemberService.cs +++ b/src/Umbraco.Core/Services/MemberService.cs @@ -30,7 +30,7 @@ namespace Umbraco.Core.Services private readonly EntityXmlSerializer _entitySerializer = new EntityXmlSerializer(); private readonly IDataTypeService _dataTypeService; private static readonly ReaderWriterLockSlim Locker = new ReaderWriterLockSlim(); - + public MemberService(IDatabaseUnitOfWorkProvider provider, RepositoryFactory repositoryFactory, ILogger logger, IEventMessagesFactory eventMessagesFactory, IMemberGroupService memberGroupService, IDataTypeService dataTypeService) : base(provider, repositoryFactory, logger, eventMessagesFactory) { @@ -52,7 +52,7 @@ namespace Umbraco.Core.Services { using (var repository = RepositoryFactory.CreateMemberTypeRepository(UowProvider.GetUnitOfWork())) { - var types = repository.GetAll(new int[]{}).Select(x => x.Alias).ToArray(); + var types = repository.GetAll(new int[] { }).Select(x => x.Alias).ToArray(); if (types.Any() == false) { @@ -289,7 +289,7 @@ namespace Umbraco.Core.Services throw new ArgumentOutOfRangeException("matchType"); } - return repository.GetPagedResultsByQuery(query, pageIndex, pageSize, out totalRecords, "Name", Direction.Ascending); + return repository.GetPagedResultsByQuery(query, pageIndex, pageSize, out totalRecords, "Name", Direction.Ascending, true); } } @@ -340,7 +340,7 @@ namespace Umbraco.Core.Services throw new ArgumentOutOfRangeException("matchType"); } - return repository.GetPagedResultsByQuery(query, pageIndex, pageSize, out totalRecords, "Email", Direction.Ascending); + return repository.GetPagedResultsByQuery(query, pageIndex, pageSize, out totalRecords, "Email", Direction.Ascending, true); } } @@ -391,7 +391,7 @@ namespace Umbraco.Core.Services throw new ArgumentOutOfRangeException("matchType"); } - return repository.GetPagedResultsByQuery(query, pageIndex, pageSize, out totalRecords, "LoginName", Direction.Ascending); + return repository.GetPagedResultsByQuery(query, pageIndex, pageSize, out totalRecords, "LoginName", Direction.Ascending, true); } } @@ -688,7 +688,7 @@ namespace Umbraco.Core.Services var uow = UowProvider.GetUnitOfWork(); using (var repository = RepositoryFactory.CreateMemberRepository(uow)) { - return repository.GetPagedResultsByQuery(null, pageIndex, pageSize, out totalRecords, "LoginName", Direction.Ascending); + return repository.GetPagedResultsByQuery(null, pageIndex, pageSize, out totalRecords, "LoginName", Direction.Ascending, true); } } @@ -698,23 +698,29 @@ namespace Umbraco.Core.Services string orderBy, Direction orderDirection, string memberTypeAlias = null, string filter = "") { long total; - var result = GetAll(Convert.ToInt64(pageIndex), pageSize, out total, orderBy, orderDirection, memberTypeAlias, filter); + var result = GetAll(Convert.ToInt64(pageIndex), pageSize, out total, orderBy, orderDirection, true, memberTypeAlias, filter); totalRecords = Convert.ToInt32(total); return result; } public IEnumerable GetAll(long pageIndex, int pageSize, out long totalRecords, string orderBy, Direction orderDirection, string memberTypeAlias = null, string filter = "") + { + return GetAll(pageIndex, pageSize, out totalRecords, orderBy, orderDirection, true, memberTypeAlias, filter); + } + + public IEnumerable GetAll(long pageIndex, int pageSize, out long totalRecords, + string orderBy, Direction orderDirection, bool orderBySystemField, string memberTypeAlias, string filter) { var uow = UowProvider.GetUnitOfWork(); using (var repository = RepositoryFactory.CreateMemberRepository(uow)) { if (memberTypeAlias == null) { - return repository.GetPagedResultsByQuery(null, pageIndex, pageSize, out totalRecords, orderBy, orderDirection, filter); + return repository.GetPagedResultsByQuery(null, pageIndex, pageSize, out totalRecords, orderBy, orderDirection, orderBySystemField, filter); } var query = repository.Query.Where(x => x.ContentTypeAlias == memberTypeAlias); - return repository.GetPagedResultsByQuery(query, pageIndex, pageSize, out totalRecords, orderBy, orderDirection, filter); + return repository.GetPagedResultsByQuery(query, pageIndex, pageSize, out totalRecords, orderBy, orderDirection, orderBySystemField, filter); } } @@ -1253,52 +1259,52 @@ namespace Umbraco.Core.Services var memType = new MemberType(-1); var propGroup = new PropertyGroup - { - Name = "Membership", - Id = --identity - }; + { + Name = "Membership", + Id = --identity + }; propGroup.PropertyTypes.Add(new PropertyType(Constants.PropertyEditors.TextboxAlias, DataTypeDatabaseType.Ntext, Constants.Conventions.Member.Comments) - { - Name = Constants.Conventions.Member.CommentsLabel, - SortOrder = 0, - Id = --identity, - Key = identity.ToGuid() - }); + { + Name = Constants.Conventions.Member.CommentsLabel, + SortOrder = 0, + Id = --identity, + Key = identity.ToGuid() + }); propGroup.PropertyTypes.Add(new PropertyType(Constants.PropertyEditors.TrueFalseAlias, DataTypeDatabaseType.Integer, Constants.Conventions.Member.IsApproved) - { - Name = Constants.Conventions.Member.IsApprovedLabel, - SortOrder = 3, - Id = --identity, - Key = identity.ToGuid() - }); + { + Name = Constants.Conventions.Member.IsApprovedLabel, + SortOrder = 3, + Id = --identity, + Key = identity.ToGuid() + }); propGroup.PropertyTypes.Add(new PropertyType(Constants.PropertyEditors.TrueFalseAlias, DataTypeDatabaseType.Integer, Constants.Conventions.Member.IsLockedOut) - { - Name = Constants.Conventions.Member.IsLockedOutLabel, - SortOrder = 4, - Id = --identity, - Key = identity.ToGuid() - }); + { + Name = Constants.Conventions.Member.IsLockedOutLabel, + SortOrder = 4, + Id = --identity, + Key = identity.ToGuid() + }); propGroup.PropertyTypes.Add(new PropertyType(Constants.PropertyEditors.NoEditAlias, DataTypeDatabaseType.Date, Constants.Conventions.Member.LastLockoutDate) - { - Name = Constants.Conventions.Member.LastLockoutDateLabel, - SortOrder = 5, - Id = --identity, - Key = identity.ToGuid() - }); + { + Name = Constants.Conventions.Member.LastLockoutDateLabel, + SortOrder = 5, + Id = --identity, + Key = identity.ToGuid() + }); propGroup.PropertyTypes.Add(new PropertyType(Constants.PropertyEditors.NoEditAlias, DataTypeDatabaseType.Date, Constants.Conventions.Member.LastLoginDate) - { - Name = Constants.Conventions.Member.LastLoginDateLabel, - SortOrder = 6, - Id = --identity, - Key = identity.ToGuid() - }); + { + Name = Constants.Conventions.Member.LastLoginDateLabel, + SortOrder = 6, + Id = --identity, + Key = identity.ToGuid() + }); propGroup.PropertyTypes.Add(new PropertyType(Constants.PropertyEditors.NoEditAlias, DataTypeDatabaseType.Date, Constants.Conventions.Member.LastPasswordChangeDate) - { - Name = Constants.Conventions.Member.LastPasswordChangeDateLabel, - SortOrder = 7, - Id = --identity, - Key = identity.ToGuid() - }); + { + Name = Constants.Conventions.Member.LastPasswordChangeDateLabel, + SortOrder = 7, + Id = --identity, + Key = identity.ToGuid() + }); memType.PropertyGroups.Add(propGroup); diff --git a/src/Umbraco.Core/Services/ServiceContext.cs b/src/Umbraco.Core/Services/ServiceContext.cs index a00e7307b8..0017df01e9 100644 --- a/src/Umbraco.Core/Services/ServiceContext.cs +++ b/src/Umbraco.Core/Services/ServiceContext.cs @@ -1,55 +1,43 @@ using System; -using System.Collections.Generic; -using log4net; -using Umbraco.Core.Logging; -using System.IO; -using System.Linq; -using Umbraco.Core.IO; -using Umbraco.Core.Persistence; -using Umbraco.Core.Persistence.UnitOfWork; -using Umbraco.Core.Publishing; -using Umbraco.Core.Events; -using Umbraco.Core.Strings; namespace Umbraco.Core.Services { /// - /// The Umbraco ServiceContext, which provides access to the following services: - /// , , , - /// , and . + /// Represents the Umbraco Service context, which provides access to all services. /// public class ServiceContext { - private Lazy _migrationEntryService; - private Lazy _publicAccessService; - private Lazy _taskService; - private Lazy _domainService; - private Lazy _auditService; - private Lazy _localizedTextService; - private Lazy _tagService; - private Lazy _contentService; - private Lazy _userService; - private Lazy _memberService; - private Lazy _mediaService; - private Lazy _contentTypeService; - private Lazy _dataTypeService; - private Lazy _fileService; - private Lazy _localizationService; - private Lazy _packagingService; - private Lazy _serverRegistrationService; - private Lazy _entityService; - private Lazy _relationService; - private Lazy _treeService; - private Lazy _sectionService; - private Lazy _macroService; - private Lazy _memberTypeService; - private Lazy _memberGroupService; - private Lazy _notificationService; - private Lazy _externalLoginService; + private readonly Lazy _migrationEntryService; + private readonly Lazy _publicAccessService; + private readonly Lazy _taskService; + private readonly Lazy _domainService; + private readonly Lazy _auditService; + private readonly Lazy _localizedTextService; + private readonly Lazy _tagService; + private readonly Lazy _contentService; + private readonly Lazy _userService; + private readonly Lazy _memberService; + private readonly Lazy _mediaService; + private readonly Lazy _contentTypeService; + private readonly Lazy _dataTypeService; + private readonly Lazy _fileService; + private readonly Lazy _localizationService; + private readonly Lazy _packagingService; + private readonly Lazy _serverRegistrationService; + private readonly Lazy _entityService; + private readonly Lazy _relationService; + private readonly Lazy _treeService; + private readonly Lazy _sectionService; + private readonly Lazy _macroService; + private readonly Lazy _memberTypeService; + private readonly Lazy _memberGroupService; + private readonly Lazy _notificationService; + private readonly Lazy _externalLoginService; /// - /// Constructor used for IoC + /// Initializes a new instance of the class with lazy services. /// + /// Used by IoC. Note that LightInject will favor lazy args when picking a constructor. public ServiceContext(Lazy migrationEntryService, Lazy publicAccessService, Lazy taskService, Lazy domainService, Lazy auditService, Lazy localizedTextService, Lazy tagService, Lazy contentService, Lazy userService, Lazy memberService, Lazy mediaService, Lazy contentTypeService, Lazy dataTypeService, Lazy fileService, Lazy localizationService, Lazy packagingService, Lazy serverRegistrationService, Lazy entityService, Lazy relationService, Lazy treeService, Lazy sectionService, Lazy macroService, Lazy memberTypeService, Lazy memberGroupService, Lazy notificationService, Lazy externalLoginService) { _migrationEntryService = migrationEntryService; @@ -81,34 +69,9 @@ namespace Umbraco.Core.Services } /// - /// public ctor - will generally just be used for unit testing all items are optional and if not specified, the defaults will be used + /// Initializes a new instance of the class with services. /// - /// - /// - /// - /// - /// - /// - /// - /// - /// - /// - /// - /// - /// - /// - /// - /// - /// - /// - /// - /// - /// - /// - /// - /// - /// - /// + /// Used in tests. All items are optional and remain null if not specified. public ServiceContext( IContentService contentService = null, IMediaService mediaService = null, @@ -165,378 +128,131 @@ namespace Umbraco.Core.Services if (publicAccessService != null) _publicAccessService = new Lazy(() => publicAccessService); } - /// - /// Creates a service context with a RepositoryFactory which is used to construct Services - /// - /// - /// - /// - /// - /// - /// - /// - /// - public ServiceContext( - RepositoryFactory repositoryFactory, - IDatabaseUnitOfWorkProvider dbUnitOfWorkProvider, - IUnitOfWorkProvider fileUnitOfWorkProvider, - IPublishingStrategy publishingStrategy, - CacheHelper cache, - ILogger logger, - IEventMessagesFactory eventMessagesFactory, - IEnumerable urlSegmentProviders) - { - if (repositoryFactory == null) throw new ArgumentNullException("repositoryFactory"); - if (dbUnitOfWorkProvider == null) throw new ArgumentNullException("dbUnitOfWorkProvider"); - if (fileUnitOfWorkProvider == null) throw new ArgumentNullException("fileUnitOfWorkProvider"); - if (publishingStrategy == null) throw new ArgumentNullException("publishingStrategy"); - if (cache == null) throw new ArgumentNullException("cache"); - if (logger == null) throw new ArgumentNullException("logger"); - if (eventMessagesFactory == null) throw new ArgumentNullException("eventMessagesFactory"); - - BuildServiceCache(dbUnitOfWorkProvider, fileUnitOfWorkProvider, publishingStrategy, cache, - repositoryFactory, - logger, eventMessagesFactory, - urlSegmentProviders); - } - - /// - /// Builds the various services - /// - private void BuildServiceCache( - IDatabaseUnitOfWorkProvider dbUnitOfWorkProvider, - IUnitOfWorkProvider fileUnitOfWorkProvider, - IPublishingStrategy publishingStrategy, - CacheHelper cache, - RepositoryFactory repositoryFactory, - ILogger logger, - IEventMessagesFactory eventMessagesFactory, - IEnumerable urlSegmentProviders) - { - var provider = dbUnitOfWorkProvider; - var fileProvider = fileUnitOfWorkProvider; - - if (_migrationEntryService == null) - _migrationEntryService = new Lazy(() => new MigrationEntryService(provider, repositoryFactory, logger, eventMessagesFactory)); - - if (_externalLoginService == null) - _externalLoginService = new Lazy(() => new ExternalLoginService(provider, repositoryFactory, logger, eventMessagesFactory)); - - if (_publicAccessService == null) - _publicAccessService = new Lazy(() => new PublicAccessService(provider, repositoryFactory, logger, eventMessagesFactory)); - - if (_taskService == null) - _taskService = new Lazy(() => new TaskService(provider, repositoryFactory, logger, eventMessagesFactory)); - - if (_domainService == null) - _domainService = new Lazy(() => new DomainService(provider, repositoryFactory, logger, eventMessagesFactory)); - - if (_auditService == null) - _auditService = new Lazy(() => new AuditService(provider, repositoryFactory, logger, eventMessagesFactory)); - - if (_localizedTextService == null) - { - - _localizedTextService = new Lazy(() => new LocalizedTextService( - new Lazy(() => - { - var mainLangFolder = new DirectoryInfo(IOHelper.MapPath(SystemDirectories.Umbraco + "/config/lang/")); - var appPlugins = new DirectoryInfo(IOHelper.MapPath(SystemDirectories.AppPlugins)); - var configLangFolder = new DirectoryInfo(IOHelper.MapPath(SystemDirectories.Config + "/lang/")); - - var pluginLangFolders = appPlugins.Exists == false - ? Enumerable.Empty() - : appPlugins.GetDirectories() - .SelectMany(x => x.GetDirectories("Lang")) - .SelectMany(x => x.GetFiles("*.xml", SearchOption.TopDirectoryOnly)) - .Where(x => Path.GetFileNameWithoutExtension(x.FullName).Length == 5) - .Select(x => new LocalizedTextServiceSupplementaryFileSource(x, false)); - - //user defined langs that overwrite the default, these should not be used by plugin creators - var userLangFolders = configLangFolder.Exists == false - ? Enumerable.Empty() - : configLangFolder - .GetFiles("*.user.xml", SearchOption.TopDirectoryOnly) - .Where(x => Path.GetFileNameWithoutExtension(x.FullName).Length == 10) - .Select(x => new LocalizedTextServiceSupplementaryFileSource(x, true)); - - return new LocalizedTextServiceFileSources( - logger, - cache.RuntimeCache, - mainLangFolder, - pluginLangFolders.Concat(userLangFolders)); - - }), - logger)); - } - - - if (_notificationService == null) - _notificationService = new Lazy(() => new NotificationService(provider, _userService.Value, _contentService.Value, repositoryFactory, logger)); - - if (_serverRegistrationService == null) - _serverRegistrationService = new Lazy(() => new ServerRegistrationService(provider, repositoryFactory, logger, eventMessagesFactory)); - - if (_userService == null) - _userService = new Lazy(() => new UserService(provider, repositoryFactory, logger, eventMessagesFactory)); - - if (_memberService == null) - _memberService = new Lazy(() => new MemberService(provider, repositoryFactory, logger, eventMessagesFactory, _memberGroupService.Value, _dataTypeService.Value)); - - if (_contentService == null) - _contentService = new Lazy(() => new ContentService(provider, repositoryFactory, logger, eventMessagesFactory, publishingStrategy, _dataTypeService.Value, _userService.Value, urlSegmentProviders)); - - if (_mediaService == null) - _mediaService = new Lazy(() => new MediaService(provider, repositoryFactory, logger, eventMessagesFactory, _dataTypeService.Value, _userService.Value, urlSegmentProviders)); - - if (_contentTypeService == null) - _contentTypeService = new Lazy(() => new ContentTypeService(provider, repositoryFactory, logger, eventMessagesFactory, _contentService.Value, _mediaService.Value)); - - if (_dataTypeService == null) - _dataTypeService = new Lazy(() => new DataTypeService(provider, repositoryFactory, logger, eventMessagesFactory)); - - if (_fileService == null) - _fileService = new Lazy(() => new FileService(fileProvider, provider, repositoryFactory, logger, eventMessagesFactory)); - - if (_localizationService == null) - _localizationService = new Lazy(() => new LocalizationService(provider, repositoryFactory, logger, eventMessagesFactory)); - - if (_entityService == null) - _entityService = new Lazy(() => new EntityService( - provider, repositoryFactory, logger, eventMessagesFactory, - _contentService.Value, _contentTypeService.Value, _mediaService.Value, _dataTypeService.Value, _memberService.Value, _memberTypeService.Value, - //TODO: Consider making this an isolated cache instead of using the global one - cache.RuntimeCache)); - - if (_packagingService == null) - _packagingService = new Lazy(() => new PackagingService(logger, _contentService.Value, _contentTypeService.Value, _mediaService.Value, _macroService.Value, _dataTypeService.Value, _fileService.Value, _localizationService.Value, _entityService.Value, _userService.Value, repositoryFactory, provider, urlSegmentProviders)); - - if (_relationService == null) - _relationService = new Lazy(() => new RelationService(provider, repositoryFactory, logger, eventMessagesFactory, _entityService.Value)); - - if (_treeService == null) - _treeService = new Lazy(() => new EmptyApplicationTreeService()); - - if (_sectionService == null) - _sectionService = new Lazy(() => new EmptySectionService()); - - if (_macroService == null) - _macroService = new Lazy(() => new MacroService(provider, repositoryFactory, logger, eventMessagesFactory)); - - if (_memberTypeService == null) - _memberTypeService = new Lazy(() => new MemberTypeService(provider, repositoryFactory, logger, eventMessagesFactory, _memberService.Value)); - - if (_tagService == null) - _tagService = new Lazy(() => new TagService(provider, repositoryFactory, logger, eventMessagesFactory)); - - if (_memberGroupService == null) - _memberGroupService = new Lazy(() => new MemberGroupService(provider, repositoryFactory, logger, eventMessagesFactory)); - - } - /// /// Gets the /// - public IMigrationEntryService MigrationEntryService - { - get { return _migrationEntryService.Value; } - } + public IMigrationEntryService MigrationEntryService => _migrationEntryService.Value; /// /// Gets the /// - public IPublicAccessService PublicAccessService - { - get { return _publicAccessService.Value; } - } + public IPublicAccessService PublicAccessService => _publicAccessService.Value; /// /// Gets the /// - public ITaskService TaskService - { - get { return _taskService.Value; } - } + public ITaskService TaskService => _taskService.Value; /// /// Gets the /// - public IDomainService DomainService - { - get { return _domainService.Value; } - } + public IDomainService DomainService => _domainService.Value; /// /// Gets the /// - public IAuditService AuditService - { - get { return _auditService.Value; } - } + public IAuditService AuditService => _auditService.Value; /// /// Gets the /// - public ILocalizedTextService TextService - { - get { return _localizedTextService.Value; } - } + public ILocalizedTextService TextService => _localizedTextService.Value; /// /// Gets the /// - public INotificationService NotificationService - { - get { return _notificationService.Value; } - } + public INotificationService NotificationService => _notificationService.Value; /// /// Gets the /// - public IServerRegistrationService ServerRegistrationService - { - get { return _serverRegistrationService.Value; } - } + public IServerRegistrationService ServerRegistrationService => _serverRegistrationService.Value; /// /// Gets the /// - public ITagService TagService - { - get { return _tagService.Value; } - } + public ITagService TagService => _tagService.Value; /// /// Gets the /// - public IMacroService MacroService - { - get { return _macroService.Value; } - } + public IMacroService MacroService => _macroService.Value; /// /// Gets the /// - public IEntityService EntityService - { - get { return _entityService.Value; } - } + public IEntityService EntityService => _entityService.Value; /// /// Gets the /// - public IRelationService RelationService - { - get { return _relationService.Value; } - } + public IRelationService RelationService => _relationService.Value; /// /// Gets the /// - public IContentService ContentService - { - get { return _contentService.Value; } - } + public IContentService ContentService => _contentService.Value; /// /// Gets the /// - public IContentTypeService ContentTypeService - { - get { return _contentTypeService.Value; } - } + public IContentTypeService ContentTypeService => _contentTypeService.Value; /// /// Gets the /// - public IDataTypeService DataTypeService - { - get { return _dataTypeService.Value; } - } + public IDataTypeService DataTypeService => _dataTypeService.Value; /// /// Gets the /// - public IFileService FileService - { - get { return _fileService.Value; } - } + public IFileService FileService => _fileService.Value; /// /// Gets the /// - public ILocalizationService LocalizationService - { - get { return _localizationService.Value; } - } + public ILocalizationService LocalizationService => _localizationService.Value; /// /// Gets the /// - public IMediaService MediaService - { - get { return _mediaService.Value; } - } + public IMediaService MediaService => _mediaService.Value; /// /// Gets the /// - public IPackagingService PackagingService - { - get { return _packagingService.Value; } - } + public IPackagingService PackagingService => _packagingService.Value; /// /// Gets the /// - public IUserService UserService - { - get { return _userService.Value; } - } + public IUserService UserService => _userService.Value; /// /// Gets the /// - public IMemberService MemberService - { - get { return _memberService.Value; } - } + public IMemberService MemberService => _memberService.Value; /// /// Gets the /// - public ISectionService SectionService - { - get { return _sectionService.Value; } - } + public ISectionService SectionService => _sectionService.Value; /// /// Gets the /// - public IApplicationTreeService ApplicationTreeService - { - get { return _treeService.Value; } - } + public IApplicationTreeService ApplicationTreeService => _treeService.Value; /// /// Gets the MemberTypeService /// - public IMemberTypeService MemberTypeService - { - get { return _memberTypeService.Value; } - } + public IMemberTypeService MemberTypeService => _memberTypeService.Value; /// /// Gets the MemberGroupService /// - public IMemberGroupService MemberGroupService - { - get { return _memberGroupService.Value; } - } + public IMemberGroupService MemberGroupService => _memberGroupService.Value; - public IExternalLoginService ExternalLoginService - { - get { return _externalLoginService.Value; } - } + public IExternalLoginService ExternalLoginService => _externalLoginService.Value; } } \ No newline at end of file diff --git a/src/Umbraco.Core/StringExtensions.cs b/src/Umbraco.Core/StringExtensions.cs index 1580c7750c..6d031baee4 100644 --- a/src/Umbraco.Core/StringExtensions.cs +++ b/src/Umbraco.Core/StringExtensions.cs @@ -1286,6 +1286,30 @@ namespace Umbraco.Core */ } + public static string EscapeRegexSpecialCharacters(this string text) + { + var regexSpecialCharacters = new Dictionary + { + {".", @"\."}, + {"(", @"\("}, + {")", @"\)"}, + {"]", @"\]"}, + {"[", @"\["}, + {"{", @"\{"}, + {"}", @"\}"}, + {"?", @"\?"}, + {"!", @"\!"}, + {"$", @"\$"}, + {"^", @"\^"}, + {"+", @"\+"}, + {"*", @"\*"}, + {"|", @"\|"}, + {"<", @"\<"}, + {">", @"\>"} + }; + return ReplaceMany(text, regexSpecialCharacters); + } + public static bool ContainsAny(this string haystack, IEnumerable needles, StringComparison comparison = StringComparison.CurrentCulture) { if (haystack == null) throw new ArgumentNullException("haystack"); diff --git a/src/Umbraco.Core/Strings/Css/StylesheetHelper.cs b/src/Umbraco.Core/Strings/Css/StylesheetHelper.cs index ff7591c6b5..260e8e5159 100644 --- a/src/Umbraco.Core/Strings/Css/StylesheetHelper.cs +++ b/src/Umbraco.Core/Strings/Css/StylesheetHelper.cs @@ -39,7 +39,7 @@ namespace Umbraco.Core.Strings.Css public static string ReplaceRule(string input, string oldRuleName, StylesheetRule rule) { var contents = input; - var ruleRegex = new Regex(string.Format(RuleRegexFormat, oldRuleName), RegexOptions.IgnoreCase | RegexOptions.Singleline); + var ruleRegex = new Regex(string.Format(RuleRegexFormat, oldRuleName.EscapeRegexSpecialCharacters()), RegexOptions.IgnoreCase | RegexOptions.Singleline); contents = ruleRegex.Replace(contents, rule != null ? rule.ToString() : ""); return contents; } diff --git a/src/Umbraco.Core/Strings/LegacyShortStringHelper.cs b/src/Umbraco.Core/Strings/LegacyShortStringHelper.cs deleted file mode 100644 index 901c9ee299..0000000000 --- a/src/Umbraco.Core/Strings/LegacyShortStringHelper.cs +++ /dev/null @@ -1,531 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Globalization; -using System.IO; -using System.Linq; -using System.Text; -using System.Text.RegularExpressions; -using System.Xml; -using Umbraco.Core.Configuration; - -namespace Umbraco.Core.Strings -{ - /// - /// Legacy implementation of string functions for short strings such as aliases or url segments. - /// - /// - /// Not necessarily optimized to work on large bodies of text. - /// Can expose surprising or bogus behavior. - /// Uses invariant culture everywhere. - /// - internal class LegacyShortStringHelper : IShortStringHelper - { - #region Ctor and vars - - /// - /// Freezes the helper so it can prevents its configuration from being modified. - /// - /// Will be called by ShortStringHelperResolver when resolution freezes. - public void Freeze() - { - // we have nothing to protect. - } - - const string UmbracoValidAliasCharacters = "_-abcdefghijklmnopqrstuvwxyz1234567890"; - const string UmbracoInvalidFirstCharacters = "0123456789"; - - #endregion - - #region Short string services JavaScript - - const string SssjsValidCharacters = "_-abcdefghijklmnopqrstuvwxyz1234567890"; - const string SssjsInvalidFirstCharacters = "0123456789"; - - private const string SssjsFormat = @" -var UMBRACO_FORCE_SAFE_ALIAS = {0}; -var UMBRACO_FORCE_SAFE_ALIAS_VALIDCHARS = '{1}'; -var UMBRACO_FORCE_SAFE_ALIAS_INVALID_FIRST_CHARS = '{2}'; - -function safeAlias(alias) {{ - if (UMBRACO_FORCE_SAFE_ALIAS) {{ - var safeAlias = ''; - var aliasLength = alias.length; - for (var i = 0; i < aliasLength; i++) {{ - currentChar = alias.substring(i, i + 1); - if (UMBRACO_FORCE_SAFE_ALIAS_VALIDCHARS.indexOf(currentChar.toLowerCase()) > -1) {{ - // check for camel (if previous character is a space, we'll upper case the current one - if (safeAlias == '' && UMBRACO_FORCE_SAFE_ALIAS_INVALID_FIRST_CHARS.indexOf(currentChar.toLowerCase()) > 0) {{ - currentChar = ''; - }} else {{ - // first char should always be lowercase (camel style) - if (safeAlias.length == 0) - currentChar = currentChar.toLowerCase(); - - if (i < aliasLength - 1 && safeAlias != '' && alias.substring(i - 1, i) == ' ') - currentChar = currentChar.toUpperCase(); - - safeAlias += currentChar; - }} - }} - }} - - alias = safeAlias; - }} - return alias; -}} - -function getSafeAlias(input, value, immediate, callback) {{ - callback(safeAlias(value)); -}} - -function validateSafeAlias(input, value, immediate, callback) {{ - callback(value == safeAlias(value)); -}} - -// legacy backward compatibility requires that one -function isValidAlias(alias) {{ - return alias == safeAlias(alias); -}} -"; - - /// - /// Gets the JavaScript code defining client-side short string services. - /// - public string GetShortStringServicesJavaScript(string controllerPath) - { - return string.Format(SssjsFormat, - UmbracoConfig.For.UmbracoSettings().Content.ForceSafeAliases ? "true" : "false", SssjsValidCharacters, SssjsInvalidFirstCharacters); - } - - #endregion - - #region IShortStringHelper CleanFor... - - /// - /// Cleans a string to produce a string that can safely be used in an alias. - /// - /// The text to filter. - /// The safe alias. - /// The string will be cleaned in the context of invariant culture. - public string CleanStringForSafeAlias(string text) - { - // ported from StringExtensions.ToSafeAlias() - - const string validAliasCharacters = UmbracoValidAliasCharacters; - const string invalidFirstCharacters = UmbracoInvalidFirstCharacters; - var safeString = new StringBuilder(); - int aliasLength = text.Length; - for (var i = 0; i < aliasLength; i++) - { - var currentChar = text.Substring(i, 1); - if (validAliasCharacters.Contains(currentChar.ToLowerInvariant())) - { - // check for camel (if previous character is a space, we'll upper case the current one - if (safeString.Length == 0 && invalidFirstCharacters.Contains(currentChar.ToLowerInvariant())) - { - //currentChar = ""; - } - else - { - if (i < aliasLength - 1 && i > 0 && text.Substring(i - 1, 1) == " ") - currentChar = currentChar.ToUpperInvariant(); - - safeString.Append(currentChar); - } - } - } - - return safeString.ToString(); - } - - /// - /// Cleans a string, in the context of the invariant culture, to produce a string that can safely be used in an alias. - /// - /// The text to filter. - /// The culture. - /// The safe alias. - /// Legacy does not support culture contexts. - public string CleanStringForSafeAlias(string text, CultureInfo culture) - { - return CleanStringForSafeAlias(text); - } - - /// - /// Cleans a string to produce a string that can safely be used in an url segment, in the context of the invariant culture. - /// - /// The text to filter. - /// The safe url segment. - public string CleanStringForUrlSegment(string text) - { - return LegacyFormatUrl(text); - } - - /// - /// Cleans a string, in the context of the invariant culture, to produce a string that can safely be used in an url segment. - /// - /// The text to filter. - /// The culture. - /// The safe url segment. - /// Legacy does not support culture contexts. - public string CleanStringForUrlSegment(string text, CultureInfo culture) - { - return CleanStringForUrlSegment(text); - } - - /// - /// Cleans a string, in the context of the invariant culture, to produce a string that can safely be used as a filename, - /// both internally (on disk) and externally (as a url). - /// - /// The text to filter. - /// The safe filename. - /// Legacy says this was used to "overcome an issue when Umbraco is used in IE in an intranet environment" but that issue is not documented. - public string CleanStringForSafeFileName(string text) - { - var filePath = text; - - // ported from Core.IO.IOHelper.SafeFileName() - - if (String.IsNullOrEmpty(filePath)) - return String.Empty; - - if (!String.IsNullOrWhiteSpace(filePath)) - { - foreach (var character in Path.GetInvalidFileNameChars()) - { - filePath = filePath.Replace(character, '-'); - } - } - else - { - filePath = String.Empty; - } - - //Break up the file in name and extension before applying the UrlReplaceCharacters - var fileNamePart = filePath.Substring(0, filePath.LastIndexOf('.')); - var ext = filePath.Substring(filePath.LastIndexOf('.')); - - //Because the file usually is downloadable as well we check characters against 'UmbracoSettings.UrlReplaceCharacters' - foreach (var n in UmbracoConfig.For.UmbracoSettings().RequestHandler.CharCollection) - { - if (n.Char.IsNullOrWhiteSpace() == false) - fileNamePart = fileNamePart.Replace(n.Char, n.Replacement); - } - - filePath = string.Concat(fileNamePart, ext); - - // Adapted from: http://stackoverflow.com/a/4827510/5018 - // Combined both Reserved Characters and Character Data - // from http://en.wikipedia.org/wiki/Percent-encoding - var stringBuilder = new StringBuilder(); - - const string reservedCharacters = "!*'();:@&=+$,/?%#[]-~{}\"<>\\^`| "; - - foreach (var character in filePath) - { - if (reservedCharacters.IndexOf(character) == -1) - stringBuilder.Append(character); - else - stringBuilder.Append("-"); - } - - // Remove repeating dashes - // From: http://stackoverflow.com/questions/5111967/regex-to-remove-a-specific-repeated-character - var reducedString = Regex.Replace(stringBuilder.ToString(), "-+", "-"); - - return reducedString; - } - - /// - /// Cleans a string, in the context of the invariant culture, to produce a string that can safely be used as a filename, - /// both internally (on disk) and externally (as a url). - /// - /// The text to filter. - /// The culture. - /// The safe filename. - /// Legacy does not support culture contexts. - public string CleanStringForSafeFileName(string text, CultureInfo culture) - { - return CleanStringForSafeFileName(text); - } - - #endregion - - #region CleanString - - // legacy does not implement these - - public string CleanString(string text, CleanStringType stringType) - { - return text; - } - - public string CleanString(string text, CleanStringType stringType, char separator) - { - return text; - } - - public string CleanString(string text, CleanStringType stringType, CultureInfo culture) - { - return text; - } - - public string CleanString(string text, CleanStringType stringType, char separator, CultureInfo culture) - { - return text; - } - - #endregion - - #region SplitPascalCasing - - /// - /// Splits a pascal-cased string by inserting a separator in between each term. - /// - /// The text to split. - /// The separator. - /// The splitted string. - /// Probably only supports Ascii strings. - public string SplitPascalCasing(string text, char separator) - { - // ported from StringExtensions.SplitPascalCasing() - - var replacement = "$1" + separator; - var result = Regex.Replace(text, "([a-z](?=[A-Z])|[A-Z](?=[A-Z][a-z]))", replacement); - return result; - } - - #endregion - - #region Legacy - - /// - /// Cleans a string to produce a string that can safely be used in an alias. - /// - /// The text to filter. - /// The safe alias. - /// The string will be cleaned in the context of invariant culture. - public string LegacyCleanStringForUmbracoAlias(string text) - { - // ported from StringExtensions.ToUmbracoAlias() - // kept here for reference, not used anymore - - if (string.IsNullOrEmpty(text)) return string.Empty; - - //convert case first - //var tmp = text.ConvertCase(caseType); - // note: always Camel anyway - var tmp = LegacyConvertStringCase(text, CleanStringType.CamelCase); - - //remove non-alphanumeric chars - var result = Regex.Replace(tmp, @"[^a-zA-Z0-9\s\.-]+", "", RegexOptions.Compiled); - - // note: spaces are always removed anyway - //if (removeSpaces) - // result = result.Replace(" ", ""); - - return result; - } - - /// - /// Filters a string to convert case, and more. - /// - /// the text to filter. - /// The string case type. - /// The filtered text. - /// - /// This is the legacy method, so we can't really change it, although it has issues (see unit tests). - /// It does more than "converting the case", and also remove spaces, etc. - /// - public string LegacyConvertStringCase(string phrase, CleanStringType cases) - { - // ported from StringExtensions.ConvertCase - - cases &= CleanStringType.CaseMask; - - var splittedPhrase = Regex.Split(phrase, @"[^a-zA-Z0-9\']", RegexOptions.Compiled); - - if (cases == CleanStringType.Unchanged) - return string.Join("", splittedPhrase); - - //var splittedPhrase = phrase.Split(' ', '-', '.'); - var sb = new StringBuilder(); - - foreach (var splittedPhraseChars in splittedPhrase.Select(s => s.ToCharArray())) - { - if (splittedPhraseChars.Length > 0) - { - splittedPhraseChars[0] = ((new String(splittedPhraseChars[0], 1)).ToUpperInvariant().ToCharArray())[0]; - } - sb.Append(new String(splittedPhraseChars)); - } - - var result = sb.ToString(); - - if (cases == CleanStringType.CamelCase) - { - if (result.Length > 1) - { - var pattern = new Regex("^([A-Z]*)([A-Z].*)$", RegexOptions.Singleline | RegexOptions.Compiled); - var match = pattern.Match(result); - if (match.Success) - { - result = match.Groups[1].Value.ToLowerInvariant() + match.Groups[2].Value; - - return result.Substring(0, 1).ToLowerInvariant() + result.Substring(1); - } - - return result; - } - - return result.ToLowerInvariant(); - } - - return result; - } - - /// - /// Converts string to a URL alias. - /// - /// The value. - /// The char replacements. - /// if set to true replace double dashes. - /// if set to true strip non ASCII. - /// if set to true URL encode. - /// - /// - /// This ensures that ONLY ascii chars are allowed and of those ascii chars, only digits and lowercase chars, all - /// punctuation, etc... are stripped out, however this method allows you to pass in string's to replace with the - /// specified replacement character before the string is converted to ascii and it has invalid characters stripped out. - /// This allows you to replace strings like & , etc.. with your replacement character before the automatic - /// reduction. - /// - public string LegacyToUrlAlias(string value, IDictionary charReplacements, bool replaceDoubleDashes, bool stripNonAscii, bool urlEncode) - { - // to lower case invariant - // replace chars one by one using charReplacements - // (opt) convert to ASCII then remove anything that's not ASCII - // trim - and _ then (opt) remove double - - // (opt) url-encode - - // charReplacement is actually *string* replacement ie it can replace " " by a non-breaking space - // so it's kind of a pre-filter actually... - // we need pre-filters, and post-filters, within each token... - // not so... we may want to replace   with a space BEFORE cutting into tokens... - - //first to lower case - value = value.ToLowerInvariant(); - - //then replacement chars - value = charReplacements.Aggregate(value, (current, kvp) => current.Replace(kvp.Key, kvp.Value)); - - //then convert to only ascii, this will remove the rest of any invalid chars - if (stripNonAscii) - { - value = Encoding.ASCII.GetString( - Encoding.Convert( - Encoding.UTF8, - Encoding.GetEncoding( - Encoding.ASCII.EncodingName, - new EncoderReplacementFallback(String.Empty), - new DecoderExceptionFallback()), - Encoding.UTF8.GetBytes(value))); - - //remove all characters that do not fall into the following categories (apart from the replacement val) - var validCodeRanges = - //digits - Enumerable.Range(48, 10).Concat( - //lowercase chars - Enumerable.Range(97, 26)); - - var sb = new StringBuilder(); - foreach (var c in value.Where(c => charReplacements.Values.Contains(c.ToString(CultureInfo.InvariantCulture)) || validCodeRanges.Contains(c))) - { - sb.Append(c); - } - - value = sb.ToString(); - } - - //trim dashes from end - value = value.Trim('-', '_'); - - //replace double occurances of - or _ - value = replaceDoubleDashes ? Regex.Replace(value, @"([-_]){2,}", "$1", RegexOptions.Compiled) : value; - - //url encode result - return urlEncode ? System.Web.HttpUtility.UrlEncode(value) : value; - } - - /// - /// Cleans a string to produce a string that can safely be used in an url segment. - /// - /// The text to filter. - /// The safe url segment. - /// - /// Uses UmbracoSettings.UrlReplaceCharacters - /// and UmbracoSettings.RemoveDoubleDashesFromUrlReplacing. - /// - public string LegacyFormatUrl(string url) - { - var newUrl = url.ToLowerInvariant(); - foreach (var n in UmbracoConfig.For.UmbracoSettings().RequestHandler.CharCollection) - { - if (n.Char != "") - newUrl = newUrl.Replace(n.Char, n.Replacement); - } - - // check for double dashes - if (UmbracoConfig.For.UmbracoSettings().RequestHandler.RemoveDoubleDashes) - { - newUrl = Regex.Replace(newUrl, @"[-]{2,}", "-"); - } - - return newUrl; - } - - #endregion - - #region ReplaceMany - - /// - /// Returns a new string in which all occurences of specified strings are replaced by other specified strings. - /// - /// The string to filter. - /// The replacements definition. - /// The filtered string. - public string ReplaceMany(string text, IDictionary replacements) - { - // Have done various tests, implementing my own "super fast" state machine to handle - // replacement of many items, or via regexes, but on short strings and not too - // many replacements (which prob. is going to be our case) nothing can beat this... - // (at least with safe and checked code -- we don't want unsafe/unchecked here) - - // Note that it will do chained-replacements ie replaced items can be replaced - // in turn by another replacement (ie the order of replacements is important) - - return replacements.Aggregate(text, (current, kvp) => current.Replace(kvp.Key, kvp.Value)); - } - - /// - /// Returns a new string in which all occurences of specified characters are replaced by a specified character. - /// - /// The string to filter. - /// The characters to replace. - /// The replacement character. - /// The filtered string. - public string ReplaceMany(string text, char[] chars, char replacement) - { - // be safe - if (text == null) - throw new ArgumentNullException("text"); - if (chars == null) - throw new ArgumentNullException("chars"); - - // see note above - - return chars.Aggregate(text, (current, c) => current.Replace(c, replacement)); - } - - #endregion - } -} diff --git a/src/Umbraco.Core/Sync/DatabaseServerMessenger.cs b/src/Umbraco.Core/Sync/DatabaseServerMessenger.cs index fffa158a46..c16ce5a1a8 100644 --- a/src/Umbraco.Core/Sync/DatabaseServerMessenger.cs +++ b/src/Umbraco.Core/Sync/DatabaseServerMessenger.cs @@ -8,6 +8,7 @@ using System.Threading; using System.Web; using Newtonsoft.Json; using Newtonsoft.Json.Linq; +using NPoco; using Umbraco.Core.Cache; using Umbraco.Core.IO; using Umbraco.Core.Logging; @@ -244,10 +245,10 @@ namespace Umbraco.Core.Sync // // FIXME not true if we're running on a background thread, assuming we can? - var sql = new Sql().Select("*") - .From(_appContext.DatabaseContext.SqlSyntax) - .Where(_appContext.DatabaseContext.SqlSyntax, dto => dto.Id > _lastId) - .OrderBy(_appContext.DatabaseContext.SqlSyntax, dto => dto.Id); + var sql = _appContext.DatabaseContext.Sql().SelectAll() + .From() + .Where(dto => dto.Id > _lastId) + .OrderBy(dto => dto.Id); var dtos = _appContext.DatabaseContext.Database.Fetch(sql); if (dtos.Count <= 0) return; @@ -348,9 +349,9 @@ namespace Umbraco.Core.Sync /// and it should instead cold-boot. private void EnsureInstructions() { - var sql = new Sql().Select("*") - .From(_appContext.DatabaseContext.SqlSyntax) - .Where(_appContext.DatabaseContext.SqlSyntax, dto => dto.Id == _lastId); + var sql = _appContext.DatabaseContext.Sql().SelectAll() + .From() + .Where(dto => dto.Id == _lastId); var dtos = _appContext.DatabaseContext.Database.Fetch(sql); diff --git a/src/Umbraco.Core/Umbraco.Core.csproj b/src/Umbraco.Core/Umbraco.Core.csproj index ac36147368..57c9263ea7 100644 --- a/src/Umbraco.Core/Umbraco.Core.csproj +++ b/src/Umbraco.Core/Umbraco.Core.csproj @@ -92,6 +92,10 @@ ..\packages\Newtonsoft.Json.8.0.3\lib\net45\Newtonsoft.Json.dll True + + ..\packages\NPoco.3.1.0-u005\lib\net45\NPoco.dll + True + ..\packages\Owin.1.0\lib\net40\Owin.dll @@ -333,6 +337,7 @@ + @@ -368,6 +373,9 @@ + + Component + @@ -445,7 +453,6 @@ - @@ -465,6 +472,9 @@ + + + @@ -480,6 +490,7 @@ + @@ -755,7 +766,6 @@ - @@ -766,7 +776,7 @@ - + @@ -964,19 +974,13 @@ - - - - + - - - @@ -997,7 +1001,6 @@ - @@ -1012,7 +1015,7 @@ - + @@ -1045,8 +1048,8 @@ - - + + @@ -1150,7 +1153,6 @@ - @@ -1298,7 +1300,6 @@ - diff --git a/src/Umbraco.Core/Umbraco.Core.csproj.DotSettings b/src/Umbraco.Core/Umbraco.Core.csproj.DotSettings index 662f95686e..73e96563f9 100644 --- a/src/Umbraco.Core/Umbraco.Core.csproj.DotSettings +++ b/src/Umbraco.Core/Umbraco.Core.csproj.DotSettings @@ -1,2 +1,2 @@  - CSharp50 \ No newline at end of file + CSharp60 \ No newline at end of file diff --git a/src/Umbraco.Core/UmbracoApplicationBase.cs b/src/Umbraco.Core/UmbracoApplicationBase.cs index d83410aad0..37941a5ff6 100644 --- a/src/Umbraco.Core/UmbracoApplicationBase.cs +++ b/src/Umbraco.Core/UmbracoApplicationBase.cs @@ -92,6 +92,11 @@ namespace Umbraco.Core /// /// Override init and raise the event /// + /// + /// DID YOU KNOW? The Global.asax Init call is the thing that initializes all of the httpmodules, ties up a bunch of stuff with IIS, etc... + /// Therefore, since OWIN is an HttpModule when running in IIS/ASP.Net the OWIN startup is not executed until this method fires and by that + /// time, Umbraco has performed it's bootup sequence. + /// public override void Init() { base.Init(); diff --git a/src/Umbraco.Core/packages.config b/src/Umbraco.Core/packages.config index d3aa7b8ba5..1cbbee0585 100644 --- a/src/Umbraco.Core/packages.config +++ b/src/Umbraco.Core/packages.config @@ -13,6 +13,7 @@ + diff --git a/src/Umbraco.Tests/App.config b/src/Umbraco.Tests/App.config index 918335bf91..211c8322b9 100644 --- a/src/Umbraco.Tests/App.config +++ b/src/Umbraco.Tests/App.config @@ -2,12 +2,12 @@ - +
- + - + @@ -52,7 +52,7 @@ - + @@ -64,9 +64,9 @@ - + - + @@ -121,13 +121,13 @@ - + - + - + - + diff --git a/src/Umbraco.Tests/Configurations/UmbracoSettings/SecurityElementTests.cs b/src/Umbraco.Tests/Configurations/UmbracoSettings/SecurityElementTests.cs index 8fbf4a1523..58a9a438a2 100644 --- a/src/Umbraco.Tests/Configurations/UmbracoSettings/SecurityElementTests.cs +++ b/src/Umbraco.Tests/Configurations/UmbracoSettings/SecurityElementTests.cs @@ -11,16 +11,25 @@ namespace Umbraco.Tests.Configurations.UmbracoSettings { Assert.IsTrue(SettingsSection.Security.KeepUserLoggedIn == true); } + [Test] public void HideDisabledUsersInBackoffice() { Assert.IsTrue(SettingsSection.Security.HideDisabledUsersInBackoffice == false); } + + [Test] + public void AllowPasswordReset() + { + Assert.IsTrue(SettingsSection.Security.AllowPasswordReset == true); + } + [Test] public void AuthCookieDomain() { Assert.IsTrue(SettingsSection.Security.AuthCookieDomain == null); } + [Test] public void AuthCookieName() { diff --git a/src/Umbraco.Tests/Configurations/UmbracoSettings/umbracoSettings.config b/src/Umbraco.Tests/Configurations/UmbracoSettings/umbracoSettings.config index 9bc8e99b66..7cc941d671 100644 --- a/src/Umbraco.Tests/Configurations/UmbracoSettings/umbracoSettings.config +++ b/src/Umbraco.Tests/Configurations/UmbracoSettings/umbracoSettings.config @@ -102,7 +102,10 @@ false - + + + true + diff --git a/src/Umbraco.Tests/EnumerableExtensionsTests.cs b/src/Umbraco.Tests/EnumerableExtensionsTests.cs index 8edba760a1..da69ab9d40 100644 --- a/src/Umbraco.Tests/EnumerableExtensionsTests.cs +++ b/src/Umbraco.Tests/EnumerableExtensionsTests.cs @@ -156,6 +156,15 @@ namespace Umbraco.Tests CollectionAssert.AreEquivalent(integers, flattened); } + [Test] + public void InGroupsOf_CanRepeat() + { + var integers = new[] { 0, 1, 2, 3, 4, 5, 6, 7, 8 }; + var inGroupsOf = integers.InGroupsOf(2); + Assert.AreEqual(5, inGroupsOf.Count()); + Assert.AreEqual(5, inGroupsOf.Count()); // again + } + [TestCase] public void DistinctBy_ReturnsDistinctElements_AndResetsIteratorCorrectly() { diff --git a/src/Umbraco.Tests/Migrations/AlterMigrationTests.cs b/src/Umbraco.Tests/Migrations/AlterMigrationTests.cs index 49c0e1e8ac..9168ee6ace 100644 --- a/src/Umbraco.Tests/Migrations/AlterMigrationTests.cs +++ b/src/Umbraco.Tests/Migrations/AlterMigrationTests.cs @@ -1,6 +1,7 @@ using System; using System.Linq; using Moq; +using NPoco; using NUnit.Framework; using Umbraco.Core.Logging; using Umbraco.Core.Persistence; @@ -19,6 +20,7 @@ namespace Umbraco.Tests.Migrations { // Arrange var sqlSyntax = new SqlCeSyntaxProvider(); + // fixme Database vs UmbracoDatabase var context = new MigrationContext(DatabaseProviders.SqlServerCE, new Database("test", "System.Data.SqlClient"), Mock.Of(), sqlSyntax); var stub = new DropForeignKeyMigrationStub(sqlSyntax, Mock.Of()); diff --git a/src/Umbraco.Tests/Migrations/MigrationRunnerTests.cs b/src/Umbraco.Tests/Migrations/MigrationRunnerTests.cs index ee1639d41a..5be8f9bda9 100644 --- a/src/Umbraco.Tests/Migrations/MigrationRunnerTests.cs +++ b/src/Umbraco.Tests/Migrations/MigrationRunnerTests.cs @@ -2,6 +2,7 @@ using System; using System.Collections.Generic; using System.Linq; using Moq; +using NPoco; using NUnit.Framework; using Semver; using Umbraco.Core.Logging; @@ -29,6 +30,7 @@ namespace Umbraco.Tests.Migrations var ctx = runner.InitializeMigrations( //new List {new DoRunMigration(), new DoNotRunMigration()}, migrations.ToList(), + // fixme Database vs UmbracoDatabase new Database("umbracoDbDSN") , DatabaseProviders.SqlServerCE, Mock.Of(), true); @@ -48,6 +50,7 @@ namespace Umbraco.Tests.Migrations var ctx = runner.InitializeMigrations( //new List {new DoRunMigration(), new DoNotRunMigration()}, migrations.ToList(), + // fixme Database vs UmbracoDatabase new Database("umbracoDbDSN") , DatabaseProviders.SqlServerCE, Mock.Of(), true); @@ -67,6 +70,7 @@ namespace Umbraco.Tests.Migrations var ctx = runner.InitializeMigrations( //new List {new DoRunMigration(), new DoNotRunMigration()}, migrations.ToList(), + // fixme Database vs UmbracoDatabase new Database("umbracoDbDSN") , DatabaseProviders.SqlServerCE, Mock.Of(), true); diff --git a/src/Umbraco.Tests/Migrations/Upgrades/BaseUpgradeTest.cs b/src/Umbraco.Tests/Migrations/Upgrades/BaseUpgradeTest.cs index 8faa4f8717..e21ee81e2b 100644 --- a/src/Umbraco.Tests/Migrations/Upgrades/BaseUpgradeTest.cs +++ b/src/Umbraco.Tests/Migrations/Upgrades/BaseUpgradeTest.cs @@ -2,6 +2,7 @@ using System.Collections.Generic; using System.Text.RegularExpressions; using Moq; +using NPoco; using NUnit.Framework; using Semver; using Umbraco.Core; @@ -58,7 +59,6 @@ namespace Umbraco.Tests.Migrations.Upgrades } var logger = Mock.Of(); - var sqlHelper = Mock.Of(); var sql = GetSyntaxProvider(); //Setup the MigrationRunner @@ -83,11 +83,11 @@ namespace Umbraco.Tests.Migrations.Upgrades new UpdateCmsContentVersionTable(sql, logger), new UpdateCmsPropertyTypeGroupTable(sql, logger)); - bool upgraded = migrationRunner.Execute(db, provider, sqlHelper, true); + bool upgraded = migrationRunner.Execute(db, provider, sql, true); Assert.That(upgraded, Is.True); - var schemaHelper = new DatabaseSchemaHelper(db, Mock.Of(), sqlHelper); + var schemaHelper = new DatabaseSchemaHelper(db, Mock.Of(), sql); bool hasTabTable = schemaHelper.TableExist("cmsTab"); bool hasPropertyTypeGroupTable = schemaHelper.TableExist("cmsPropertyTypeGroup"); diff --git a/src/Umbraco.Tests/Migrations/Upgrades/SqlCeDataUpgradeTest.cs b/src/Umbraco.Tests/Migrations/Upgrades/SqlCeDataUpgradeTest.cs index 5ef07ef569..d8d4bd5fe2 100644 --- a/src/Umbraco.Tests/Migrations/Upgrades/SqlCeDataUpgradeTest.cs +++ b/src/Umbraco.Tests/Migrations/Upgrades/SqlCeDataUpgradeTest.cs @@ -68,7 +68,7 @@ namespace Umbraco.Tests.Migrations.Upgrades public override UmbracoDatabase GetConfiguredDatabase() { - return new UmbracoDatabase("Datasource=|DataDirectory|UmbracoPetaPocoTests.sdf;Flush Interval=1;", "System.Data.SqlServerCe.4.0", Mock.Of()); + return new UmbracoDatabase("Datasource=|DataDirectory|UmbracoNPocoTests.sdf;Flush Interval=1;", "System.Data.SqlServerCe.4.0", Mock.Of()); } public override DatabaseProviders GetDatabaseProvider() @@ -79,6 +79,6 @@ namespace Umbraco.Tests.Migrations.Upgrades public override string GetDatabaseSpecificSqlScript() { return SqlScripts.SqlResources.SqlCe_SchemaAndData_4110; - } + } } } \ No newline at end of file diff --git a/src/Umbraco.Tests/Migrations/Upgrades/SqlCeUpgradeTest.cs b/src/Umbraco.Tests/Migrations/Upgrades/SqlCeUpgradeTest.cs index 856a8fcf4e..6e889313f8 100644 --- a/src/Umbraco.Tests/Migrations/Upgrades/SqlCeUpgradeTest.cs +++ b/src/Umbraco.Tests/Migrations/Upgrades/SqlCeUpgradeTest.cs @@ -17,13 +17,13 @@ namespace Umbraco.Tests.Migrations.Upgrades { public override void DatabaseSpecificSetUp() { - string filePath = string.Concat(Path, "\\UmbracoPetaPocoTests.sdf"); + string filePath = string.Concat(Path, "\\UmbracoNPocoTests.sdf"); if (!File.Exists(filePath)) { try { - //Delete database file before continueing + //Delete database file before continueing if (File.Exists(filePath)) { File.Delete(filePath); @@ -47,7 +47,7 @@ namespace Umbraco.Tests.Migrations.Upgrades { TestHelper.ClearDatabase(); } - + } public override void DatabaseSpecificTearDown() @@ -65,7 +65,7 @@ namespace Umbraco.Tests.Migrations.Upgrades public override UmbracoDatabase GetConfiguredDatabase() { - return new UmbracoDatabase("Datasource=|DataDirectory|UmbracoPetaPocoTests.sdf;Flush Interval=1;", "System.Data.SqlServerCe.4.0", Mock.Of()); + return new UmbracoDatabase("Datasource=|DataDirectory|UmbracoNPocoTests.sdf;Flush Interval=1;", "System.Data.SqlServerCe.4.0", Mock.Of()); } public override DatabaseProviders GetDatabaseProvider() diff --git a/src/Umbraco.Tests/Migrations/Upgrades/ValidateOlderSchemaTest.cs b/src/Umbraco.Tests/Migrations/Upgrades/ValidateOlderSchemaTest.cs index f64b7041ea..0b761d0a67 100644 --- a/src/Umbraco.Tests/Migrations/Upgrades/ValidateOlderSchemaTest.cs +++ b/src/Umbraco.Tests/Migrations/Upgrades/ValidateOlderSchemaTest.cs @@ -4,6 +4,7 @@ using System.Data.SqlServerCe; using System.IO; using System.Text.RegularExpressions; using Moq; +using NPoco; using NUnit.Framework; using SQLCE4Umbraco; using Umbraco.Core.Configuration; @@ -58,7 +59,7 @@ namespace Umbraco.Tests.Migrations.Upgrades AppDomain.CurrentDomain.SetData("DataDirectory", Path); //Delete database file before continueing - string filePath = string.Concat(Path, "\\UmbracoPetaPocoTests.sdf"); + string filePath = string.Concat(Path, "\\UmbracoNPocoTests.sdf"); if (File.Exists(filePath)) { File.Delete(filePath); @@ -88,18 +89,18 @@ namespace Umbraco.Tests.Migrations.Upgrades //legacy API database connection close SqlCeContextGuardian.CloseBackgroundConnection(); - string filePath = string.Concat(Path, "\\UmbracoPetaPocoTests.sdf"); + string filePath = string.Concat(Path, "\\UmbracoNPocoTests.sdf"); if (File.Exists(filePath)) { File.Delete(filePath); } } - + public string Path { get; set; } public UmbracoDatabase GetConfiguredDatabase() { - return new UmbracoDatabase("Datasource=|DataDirectory|UmbracoPetaPocoTests.sdf;Flush Interval=1;", "System.Data.SqlServerCe.4.0", Mock.Of()); + return new UmbracoDatabase("Datasource=|DataDirectory|UmbracoNPocoTests.sdf;Flush Interval=1;", "System.Data.SqlServerCe.4.0", Mock.Of()); } public string GetDatabaseSpecificSqlScript() diff --git a/src/Umbraco.Tests/Migrations/Upgrades/ValidateV7UpgradeTest.cs b/src/Umbraco.Tests/Migrations/Upgrades/ValidateV7UpgradeTest.cs index 3e49663546..6822728ad4 100644 --- a/src/Umbraco.Tests/Migrations/Upgrades/ValidateV7UpgradeTest.cs +++ b/src/Umbraco.Tests/Migrations/Upgrades/ValidateV7UpgradeTest.cs @@ -1,5 +1,6 @@ using System.Linq; using Moq; +using NPoco; using NUnit.Framework; using Umbraco.Core.Logging; using Umbraco.Core.Persistence; @@ -19,6 +20,7 @@ namespace Umbraco.Tests.Migrations.Upgrades { var sqlSyntax = new SqlCeSyntaxProvider(); var migration = new AddIndexToCmsMacroTable(true, sqlSyntax, Mock.Of()); + // fixme Database vs UmbracoDatabase var migrationContext = new MigrationContext(DatabaseProviders.SqlServerCE, new Database("test", "System.Data.SqlClient"), Mock.Of(), sqlSyntax); migration.GetUpExpressions(migrationContext); @@ -35,6 +37,7 @@ namespace Umbraco.Tests.Migrations.Upgrades { var sqlSyntax = new SqlCeSyntaxProvider(); var migration = new AddIndexToCmsMacroPropertyTable(true, sqlSyntax, Mock.Of()); + // fixme Database vs UmbracoDatabase var migrationContext = new MigrationContext(DatabaseProviders.SqlServerCE, new Database("test", "System.Data.SqlClient"), Mock.Of(), sqlSyntax); migration.GetUpExpressions(migrationContext); diff --git a/src/Umbraco.Tests/Models/Mapping/ContentTypeModelMappingTests.cs b/src/Umbraco.Tests/Models/Mapping/ContentTypeModelMappingTests.cs index 86b321c9e3..6fa7499553 100644 --- a/src/Umbraco.Tests/Models/Mapping/ContentTypeModelMappingTests.cs +++ b/src/Umbraco.Tests/Models/Mapping/ContentTypeModelMappingTests.cs @@ -1,13 +1,17 @@ using System; using System.Collections.Generic; +using System.IO; using System.Linq; using AutoMapper; +using LightInject; using Moq; using NUnit.Framework; using umbraco; using umbraco.cms.presentation; using Umbraco.Core; +using Umbraco.Core.Cache; using Umbraco.Core.Logging; +using Umbraco.Core.Manifest; using Umbraco.Core.Models; using Umbraco.Core.Persistence; using Umbraco.Core.Persistence.SqlSyntax; @@ -37,10 +41,11 @@ namespace Umbraco.Tests.Models.Mapping public void Setup() { var nullCacheHelper = CacheHelper.CreateDisabledCacheHelper(); + var logger = Mock.Of(); //Create an app context using mocks var appContext = new ApplicationContext( - new DatabaseContext(Mock.Of(), Mock.Of(), Mock.Of(), "test"), + new DatabaseContext(Mock.Of(), logger, Mock.Of(), "test"), //Create service context using mocks new ServiceContext( @@ -52,13 +57,14 @@ namespace Umbraco.Tests.Models.Mapping fileService: _fileService.Object), nullCacheHelper, - new ProfilingLogger(Mock.Of(), Mock.Of())); + new ProfilingLogger(logger, Mock.Of())); //create a fake property editor resolver to return fake property editors Func> typeListProducerList = Enumerable.Empty; _propertyEditorResolver = new Mock( //ctor args - Mock.Of(), Mock.Of(), typeListProducerList, nullCacheHelper.RuntimeCache); + Mock.Of(), logger, typeListProducerList, + new ManifestBuilder(nullCacheHelper.RuntimeCache, new ManifestParser(logger, new DirectoryInfo(TestHelper.CurrentAssemblyDirectory), Mock.Of()))); Mapper.Initialize(configuration => { diff --git a/src/Umbraco.Tests/Persistence/DatabaseContextTests.cs b/src/Umbraco.Tests/Persistence/DatabaseContextTests.cs index 5883562f3b..db6bab1160 100644 --- a/src/Umbraco.Tests/Persistence/DatabaseContextTests.cs +++ b/src/Umbraco.Tests/Persistence/DatabaseContextTests.cs @@ -27,14 +27,14 @@ namespace Umbraco.Tests.Persistence new DefaultDatabaseFactory(Core.Configuration.GlobalSettings.UmbracoConnectionName, Mock.Of()), Mock.Of(), new SqlCeSyntaxProvider(), "System.Data.SqlServerCe.4.0"); - //unfortunately we have to set this up because the PetaPocoExtensions require singleton access + //unfortunately we have to set this up because the NPocoExtensions require singleton access ApplicationContext.Current = new ApplicationContext( CacheHelper.CreateDisabledCacheHelper(), new ProfilingLogger(Mock.Of(), Mock.Of())) { DatabaseContext = _dbContext, IsReady = true - }; + }; } [TearDown] @@ -78,10 +78,10 @@ namespace Umbraco.Tests.Persistence //Get the connectionstring settings from config var settings = ConfigurationManager.ConnectionStrings[Core.Configuration.GlobalSettings.UmbracoConnectionName]; - //by default the conn string is: Datasource=|DataDirectory|UmbracoPetaPocoTests.sdf;Flush Interval=1; + //by default the conn string is: Datasource=|DataDirectory|UmbracoNPocoTests.sdf;Flush Interval=1; //we'll just replace the sdf file with our custom one: //Create the Sql CE database - var engine = new SqlCeEngine(settings.ConnectionString.Replace("UmbracoPetaPocoTests", "DatabaseContextTests")); + var engine = new SqlCeEngine(settings.ConnectionString.Replace("UmbracoNPocoTests", "DatabaseContextTests")); engine.CreateDatabase(); var dbFactory = new DefaultDatabaseFactory(engine.LocalConnectionString, "System.Data.SqlServerCe.4.0", Mock.Of()); @@ -96,7 +96,7 @@ namespace Umbraco.Tests.Persistence var appCtx = new ApplicationContext( new DatabaseContext(Mock.Of(), Mock.Of(), Mock.Of(), "test"), - new ServiceContext(migrationEntryService: Mock.Of()), + new ServiceContext(migrationEntryService: Mock.Of()), CacheHelper.CreateDisabledCacheHelper(), new ProfilingLogger(Mock.Of(), Mock.Of())); diff --git a/src/Umbraco.Tests/Persistence/FaultHandling/ConnectionRetryTest.cs b/src/Umbraco.Tests/Persistence/FaultHandling/ConnectionRetryTest.cs index 841db8198c..f97b030dda 100644 --- a/src/Umbraco.Tests/Persistence/FaultHandling/ConnectionRetryTest.cs +++ b/src/Umbraco.Tests/Persistence/FaultHandling/ConnectionRetryTest.cs @@ -10,7 +10,7 @@ namespace Umbraco.Tests.Persistence.FaultHandling public class ConnectionRetryTest { [Test] - public void PetaPocoConnection_Cant_Connect_To_SqlDatabase_With_Invalid_User() + public void Cant_Connect_To_SqlDatabase_With_Invalid_User() { // Arrange const string providerName = "System.Data.SqlClient"; @@ -24,7 +24,7 @@ namespace Umbraco.Tests.Persistence.FaultHandling } [Test] - public void PetaPocoConnection_Cant_Connect_To_SqlDatabase_Because_Of_Network() + public void Cant_Connect_To_SqlDatabase_Because_Of_Network() { // Arrange const string providerName = "System.Data.SqlClient"; diff --git a/src/Umbraco.Tests/Persistence/Migrations/MigrationStartupHandlerTests.cs b/src/Umbraco.Tests/Persistence/Migrations/MigrationStartupHandlerTests.cs index 70daccc74c..13bfb7f7af 100644 --- a/src/Umbraco.Tests/Persistence/Migrations/MigrationStartupHandlerTests.cs +++ b/src/Umbraco.Tests/Persistence/Migrations/MigrationStartupHandlerTests.cs @@ -1,10 +1,12 @@ using System; using System.Collections.Generic; using System.Data; +using System.Data.Common; using System.Linq; using System.Text; using System.Threading.Tasks; using Moq; +using NPoco; using NUnit.Framework; using Semver; using Umbraco.Core; @@ -22,6 +24,43 @@ namespace Umbraco.Tests.Persistence.Migrations [TestFixture] public class MigrationStartupHandlerTests { + // NPoco wants a DbConnection and NOT an IDbConnection + // and DbConnection is hard to mock... + private class MockConnection : DbConnection + { + protected override DbTransaction BeginDbTransaction(IsolationLevel isolationLevel) + { + return Mock.Of(); // enough here + } + + public override void Close() + { + throw new NotImplementedException(); + } + + public override void ChangeDatabase(string databaseName) + { + throw new NotImplementedException(); + } + + public override void Open() + { + throw new NotImplementedException(); + } + + public override string ConnectionString { get; set; } + + protected override DbCommand CreateDbCommand() + { + throw new NotImplementedException(); + } + + public override string Database { get; } + public override string DataSource { get; } + public override string ServerVersion { get; } + public override ConnectionState State => ConnectionState.Open; // else NPoco reopens + } + [Test] public void Executes_For_Any_Product_Name_When_Not_Specified() { @@ -29,9 +68,8 @@ namespace Umbraco.Tests.Persistence.Migrations var testHandler1 = new TestMigrationHandler(changed1); testHandler1.OnApplicationStarting(Mock.Of(), new ApplicationContext(CacheHelper.CreateDisabledCacheHelper(), new ProfilingLogger(Mock.Of(), Mock.Of()))); - var conn = new Mock(); - conn.Setup(x => x.BeginTransaction(It.IsAny())).Returns(Mock.Of()); - var db = new Mock(conn.Object); + var conn = new MockConnection(); + var db = new Mock(conn); var runner1 = new MigrationRunner(Mock.Of(), Mock.Of(), Mock.Of(), new SemVersion(1), new SemVersion(2), "Test1", new IMigration[] { Mock.Of() }); @@ -49,9 +87,8 @@ namespace Umbraco.Tests.Persistence.Migrations var testHandler2 = new TestMigrationHandler("Test2", changed2); testHandler2.OnApplicationStarting(Mock.Of(), new ApplicationContext(CacheHelper.CreateDisabledCacheHelper(), new ProfilingLogger(Mock.Of(), Mock.Of()))); - var conn = new Mock(); - conn.Setup(x => x.BeginTransaction(It.IsAny())).Returns(Mock.Of()); - var db = new Mock(conn.Object); + var conn = new MockConnection(); + var db = new Mock(conn); var runner1 = new MigrationRunner(Mock.Of(), Mock.Of(), Mock.Of(), new SemVersion(1), new SemVersion(2), "Test1", new IMigration[] { Mock.Of()}); @@ -71,11 +108,17 @@ namespace Umbraco.Tests.Persistence.Migrations public int CountExecuted { get; set; } } - public class TestMigrationHandler : MigrationStartupHander + public class TestMigrationHandler : MigrationStartupHandler { private readonly string _prodName; private readonly Args _changed; + // need that one else it breaks IoC + public TestMigrationHandler() + { + _changed = new Args(); + } + public TestMigrationHandler(Args changed) { _changed = changed; diff --git a/src/Umbraco.Tests/Persistence/NPocoExtensionsTest.cs b/src/Umbraco.Tests/Persistence/NPocoExtensionsTest.cs new file mode 100644 index 0000000000..eb4bdfc23e --- /dev/null +++ b/src/Umbraco.Tests/Persistence/NPocoExtensionsTest.cs @@ -0,0 +1,123 @@ +using System; +using System.Collections.Generic; +using System.Text.RegularExpressions; +using NUnit.Framework; +using Umbraco.Core.Models.Rdbms; +using Umbraco.Core.Persistence; +using Umbraco.Tests.TestHelpers; + +namespace Umbraco.Tests.Persistence +{ + // fixme.npoco - is this still appropriate? + // + [DatabaseTestBehavior(DatabaseBehavior.NewDbFileAndSchemaPerTest)] + [TestFixture] + public class NPocoExtensionsTest : BaseDatabaseFactoryTest + { + [SetUp] + public override void Initialize() + { + base.Initialize(); + } + + [TearDown] + public override void TearDown() + { + base.TearDown(); + } + + [Test] + public void Can_Bulk_Insert() + { + // Arrange + var db = DatabaseContext.Database; + + var servers = new List(); + for (var i = 0; i < 1000; i++) + { + servers.Add(new ServerRegistrationDto + { + ServerAddress = "address" + i, + ServerIdentity = "computer" + i, + DateRegistered = DateTime.Now, + IsActive = true, + DateAccessed = DateTime.Now + }); + } + + // Act + using (ProfilingLogger.TraceDuration("starting insert", "finished insert")) + { + db.BulkInsertRecords(SqlSyntax, servers); + } + + // Assert + Assert.That(db.ExecuteScalar("SELECT COUNT(*) FROM umbracoServer"), Is.EqualTo(1000)); + } + + [Test] + public void Generate_Bulk_Import_Sql() + { + // Arrange + var db = DatabaseContext.Database; + + var servers = new List(); + for (var i = 0; i < 2; i++) + { + servers.Add(new ServerRegistrationDto + { + ServerAddress = "address" + i, + ServerIdentity = "computer" + i, + DateRegistered = DateTime.Now, + IsActive = true, + DateAccessed = DateTime.Now + }); + } + db.OpenSharedConnection(); + + // Act + string[] sql; + db.GenerateBulkInsertCommand(servers, db.Connection, out sql); + db.CloseSharedConnection(); + + // Assert + Assert.That(sql[0], + Is.EqualTo("INSERT INTO [umbracoServer] ([umbracoServer].[address], [umbracoServer].[computerName], [umbracoServer].[registeredDate], [umbracoServer].[lastNotifiedDate], [umbracoServer].[isActive], [umbracoServer].[isMaster]) VALUES (@0,@1,@2,@3,@4,@5), (@6,@7,@8,@9,@10,@11)")); + } + + + [Test] + public void Generate_Bulk_Import_Sql_Exceeding_Max_Params() + { + // Arrange + var db = DatabaseContext.Database; + + var servers = new List(); + for (var i = 0; i < 1500; i++) + { + servers.Add(new ServerRegistrationDto + { + ServerAddress = "address" + i, + ServerIdentity = "computer" + i, + DateRegistered = DateTime.Now, + IsActive = true, + DateAccessed = DateTime.Now, + IsMaster = true + }); + } + db.OpenSharedConnection(); + + // Act + string[] sql; + db.GenerateBulkInsertCommand(servers, db.Connection, out sql); + db.CloseSharedConnection(); + + // Assert + Assert.That(sql.Length, Is.EqualTo(5)); + foreach (var s in sql) + { + Assert.LessOrEqual(Regex.Matches(s, "@\\d+").Count, 2000); + } + } + } +} \ No newline at end of file diff --git a/src/Umbraco.Tests/Persistence/PetaPocoCachesTest.cs b/src/Umbraco.Tests/Persistence/PetaPocoCachesTest.cs new file mode 100644 index 0000000000..965341d7ea --- /dev/null +++ b/src/Umbraco.Tests/Persistence/PetaPocoCachesTest.cs @@ -0,0 +1,193 @@ +using System; +using System.Linq; +using NUnit.Framework; +using Umbraco.Core.Models; +using Umbraco.Core.Services; +using Umbraco.Tests.Services; +using Umbraco.Tests.TestHelpers; +using Umbraco.Tests.TestHelpers.Entities; + +namespace Umbraco.Tests.Persistence +{ + // fixme.npoco - what shall we do with those tests? + // + [DatabaseTestBehavior(DatabaseBehavior.NewDbFileAndSchemaPerTest)] + [TestFixture, Ignore] + public class PetaPocoCachesTest : BaseServiceTest + { + /// + /// This tests the peta poco caches + /// + /// + /// This test WILL fail. This is because we cannot stop PetaPoco from creating more cached items for queries such as + /// ContentTypeRepository.GetAll(1,2,3,4); + /// when combined with other GetAll queries that pass in an array of Ids, each query generated for different length + /// arrays will produce a unique query which then gets added to the cache. + /// + /// This test confirms this, if you analyze the DIFFERENCE output below you can see why the cached queries grow. + /// + //[Test] + //public void Check_Peta_Poco_Caches() + //{ + // var result = new List>>(); + + // Database.PocoData.UseLongKeys = true; + + // for (int i = 0; i < 2; i++) + // { + // int id1, id2, id3; + // string alias; + // CreateStuff(out id1, out id2, out id3, out alias); + // QueryStuff(id1, id2, id3, alias); + + // double totalBytes1; + // IEnumerable keys; + // Console.Write(PocoData.PrintDebugCacheReport(out totalBytes1, out keys)); + + // result.Add(new Tuple>(totalBytes1, keys.Count(), keys)); + // } + + // for (int index = 0; index < result.Count; index++) + // { + // var tuple = result[index]; + // Console.WriteLine("Bytes: {0}, Delegates: {1}", tuple.Item1, tuple.Item2); + // if (index != 0) + // { + // Console.WriteLine("----------------DIFFERENCE---------------------"); + // var diff = tuple.Item3.Except(result[index - 1].Item3); + // foreach (var d in diff) + // { + // Console.WriteLine(d); + // } + // } + + // } + + // var allByteResults = result.Select(x => x.Item1).Distinct(); + // var totalKeys = result.Select(x => x.Item2).Distinct(); + + // Assert.AreEqual(1, allByteResults.Count()); + // Assert.AreEqual(1, totalKeys.Count()); + //} + + //[Test] + //public void Verify_Memory_Expires() + //{ + // Database.PocoData.SlidingExpirationSeconds = 2; + + // var managedCache = new Database.ManagedCache(); + + // int id1, id2, id3; + // string alias; + // CreateStuff(out id1, out id2, out id3, out alias); + // QueryStuff(id1, id2, id3, alias); + + // var count1 = managedCache.GetCache().GetCount(); + // Console.WriteLine("Keys = " + count1); + // Assert.Greater(count1, 0); + + // Thread.Sleep(10000); + + // var count2 = managedCache.GetCache().GetCount(); + // Console.WriteLine("Keys = " + count2); + // Assert.Less(count2, count1); + //} + + private void QueryStuff(int id1, int id2, int id3, string alias1) + { + var contentService = ServiceContext.ContentService; + + ServiceContext.TagService.GetTagsForEntity(id1); + + ServiceContext.TagService.GetAllContentTags(); + + ServiceContext.TagService.GetTagsForEntity(id2); + + ServiceContext.TagService.GetTagsForEntity(id3); + + contentService.CountDescendants(id3); + + contentService.CountChildren(id3); + + contentService.Count(contentTypeAlias: alias1); + + contentService.Count(); + + contentService.GetById(Guid.NewGuid()); + + contentService.GetByLevel(2); + + contentService.GetChildren(id1); + + contentService.GetDescendants(id2); + + contentService.GetVersions(id3); + + contentService.GetRootContent(); + + contentService.GetContentForExpiration(); + + contentService.GetContentForRelease(); + + contentService.GetContentInRecycleBin(); + + ((ContentService)contentService).GetPublishedDescendants(new Content("Test", -1, new ContentType(-1)) + { + Id = id1, + Path = "-1," + id1 + }); + + contentService.GetByVersion(Guid.NewGuid()); + } + + private void CreateStuff(out int id1, out int id2, out int id3, out string alias) + { + var contentService = ServiceContext.ContentService; + + var ctAlias = "umbTextpage" + Guid.NewGuid().ToString("N"); + alias = ctAlias; + + for (int i = 0; i < 20; i++) + { + contentService.CreateContentWithIdentity("Test", -1, "umbTextpage", 0); + } + var contentTypeService = ServiceContext.ContentTypeService; + var contentType = MockedContentTypes.CreateSimpleContentType(ctAlias, "test Doc Type"); + contentTypeService.Save(contentType); + for (int i = 0; i < 20; i++) + { + contentService.CreateContentWithIdentity("Test", -1, ctAlias, 0); + } + var parent = contentService.CreateContentWithIdentity("Test", -1, ctAlias, 0); + id1 = parent.Id; + + for (int i = 0; i < 20; i++) + { + contentService.CreateContentWithIdentity("Test", parent, ctAlias); + } + IContent current = parent; + for (int i = 0; i < 20; i++) + { + current = contentService.CreateContentWithIdentity("Test", current, ctAlias); + } + contentType = MockedContentTypes.CreateSimpleContentType("umbMandatory" + Guid.NewGuid().ToString("N"), "Mandatory Doc Type", true); + contentType.PropertyGroups.First().PropertyTypes.Add( + new PropertyType("test", DataTypeDatabaseType.Ntext, "tags") + { + DataTypeDefinitionId = 1041 + }); + contentTypeService.Save(contentType); + var content1 = MockedContent.CreateSimpleContent(contentType, "Tagged content 1", -1); + content1.SetTags("tags", new[] { "hello", "world", "some", "tags" }, true); + contentService.Publish(content1); + id2 = content1.Id; + + var content2 = MockedContent.CreateSimpleContent(contentType, "Tagged content 2", -1); + content2.SetTags("tags", new[] { "hello", "world", "some", "tags" }, true); + contentService.Publish(content2); + id3 = content2.Id; + + contentService.MoveToRecycleBin(content1); + } + } +} \ No newline at end of file diff --git a/src/Umbraco.Tests/Persistence/PetaPocoExtensionsTest.cs b/src/Umbraco.Tests/Persistence/PetaPocoExtensionsTest.cs deleted file mode 100644 index 96aae1bcc2..0000000000 --- a/src/Umbraco.Tests/Persistence/PetaPocoExtensionsTest.cs +++ /dev/null @@ -1,308 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text.RegularExpressions; -using System.Threading; -using NUnit.Framework; -using Umbraco.Core; -using Umbraco.Core.Models; -using Umbraco.Core.Models.Rdbms; -using Umbraco.Core.Persistence; -using Umbraco.Core.Services; -using Umbraco.Tests.Services; -using Umbraco.Tests.TestHelpers; -using Umbraco.Tests.TestHelpers.Entities; - -namespace Umbraco.Tests.Persistence -{ - [DatabaseTestBehavior(DatabaseBehavior.NewDbFileAndSchemaPerTest)] - [TestFixture, NUnit.Framework.Ignore] - public class PetaPocoCachesTest : BaseServiceTest - { - /// - /// This tests the peta poco caches - /// - /// - /// This test WILL fail. This is because we cannot stop PetaPoco from creating more cached items for queries such as - /// ContentTypeRepository.GetAll(1,2,3,4); - /// when combined with other GetAll queries that pass in an array of Ids, each query generated for different length - /// arrays will produce a unique query which then gets added to the cache. - /// - /// This test confirms this, if you analyze the DIFFERENCE output below you can see why the cached queries grow. - /// - [Test] - public void Check_Peta_Poco_Caches() - { - var result = new List>>(); - - Database.PocoData.UseLongKeys = true; - - for (int i = 0; i < 2; i++) - { - int id1, id2, id3; - string alias; - CreateStuff(out id1, out id2, out id3, out alias); - QueryStuff(id1, id2, id3, alias); - - double totalBytes1; - IEnumerable keys; - Console.Write(Database.PocoData.PrintDebugCacheReport(out totalBytes1, out keys)); - - result.Add(new Tuple>(totalBytes1, keys.Count(), keys)); - } - - for (int index = 0; index < result.Count; index++) - { - var tuple = result[index]; - Console.WriteLine("Bytes: {0}, Delegates: {1}", tuple.Item1, tuple.Item2); - if (index != 0) - { - Console.WriteLine("----------------DIFFERENCE---------------------"); - var diff = tuple.Item3.Except(result[index - 1].Item3); - foreach (var d in diff) - { - Console.WriteLine(d); - } - } - - } - - var allByteResults = result.Select(x => x.Item1).Distinct(); - var totalKeys = result.Select(x => x.Item2).Distinct(); - - Assert.AreEqual(1, allByteResults.Count()); - Assert.AreEqual(1, totalKeys.Count()); - } - - [Test] - public void Verify_Memory_Expires() - { - Database.PocoData.SlidingExpirationSeconds = 2; - - var managedCache = new Database.ManagedCache(); - - int id1, id2, id3; - string alias; - CreateStuff(out id1, out id2, out id3, out alias); - QueryStuff(id1, id2, id3, alias); - - var count1 = managedCache.GetCache().GetCount(); - Console.WriteLine("Keys = " + count1); - Assert.Greater(count1, 0); - - Thread.Sleep(10000); - - var count2 = managedCache.GetCache().GetCount(); - Console.WriteLine("Keys = " + count2); - Assert.Less(count2, count1); - } - - private void QueryStuff(int id1, int id2, int id3, string alias1) - { - var contentService = ServiceContext.ContentService; - - ServiceContext.TagService.GetTagsForEntity(id1); - - ServiceContext.TagService.GetAllContentTags(); - - ServiceContext.TagService.GetTagsForEntity(id2); - - ServiceContext.TagService.GetTagsForEntity(id3); - - contentService.CountDescendants(id3); - - contentService.CountChildren(id3); - - contentService.Count(contentTypeAlias: alias1); - - contentService.Count(); - - contentService.GetById(Guid.NewGuid()); - - contentService.GetByLevel(2); - - contentService.GetChildren(id1); - - contentService.GetDescendants(id2); - - contentService.GetVersions(id3); - - contentService.GetRootContent(); - - contentService.GetContentForExpiration(); - - contentService.GetContentForRelease(); - - contentService.GetContentInRecycleBin(); - - ((ContentService)contentService).GetPublishedDescendants(new Content("Test", -1, new ContentType(-1)) - { - Id = id1, - Path = "-1," + id1 - }); - - contentService.GetByVersion(Guid.NewGuid()); - } - - private void CreateStuff(out int id1, out int id2, out int id3, out string alias) - { - var contentService = ServiceContext.ContentService; - - var ctAlias = "umbTextpage" + Guid.NewGuid().ToString("N"); - alias = ctAlias; - - for (int i = 0; i < 20; i++) - { - contentService.CreateContentWithIdentity("Test", -1, "umbTextpage", 0); - } - var contentTypeService = ServiceContext.ContentTypeService; - var contentType = MockedContentTypes.CreateSimpleContentType(ctAlias, "test Doc Type"); - contentTypeService.Save(contentType); - for (int i = 0; i < 20; i++) - { - contentService.CreateContentWithIdentity("Test", -1, ctAlias, 0); - } - var parent = contentService.CreateContentWithIdentity("Test", -1, ctAlias, 0); - id1 = parent.Id; - - for (int i = 0; i < 20; i++) - { - contentService.CreateContentWithIdentity("Test", parent, ctAlias); - } - IContent current = parent; - for (int i = 0; i < 20; i++) - { - current = contentService.CreateContentWithIdentity("Test", current, ctAlias); - } - contentType = MockedContentTypes.CreateSimpleContentType("umbMandatory" + Guid.NewGuid().ToString("N"), "Mandatory Doc Type", true); - contentType.PropertyGroups.First().PropertyTypes.Add( - new PropertyType("test", DataTypeDatabaseType.Ntext, "tags") - { - DataTypeDefinitionId = 1041 - }); - contentTypeService.Save(contentType); - var content1 = MockedContent.CreateSimpleContent(contentType, "Tagged content 1", -1); - content1.SetTags("tags", new[] { "hello", "world", "some", "tags" }, true); - contentService.Publish(content1); - id2 = content1.Id; - - var content2 = MockedContent.CreateSimpleContent(contentType, "Tagged content 2", -1); - content2.SetTags("tags", new[] { "hello", "world", "some", "tags" }, true); - contentService.Publish(content2); - id3 = content2.Id; - - contentService.MoveToRecycleBin(content1); - } - } - - [DatabaseTestBehavior(DatabaseBehavior.NewDbFileAndSchemaPerTest)] - [TestFixture] - public class PetaPocoExtensionsTest : BaseDatabaseFactoryTest - { - [SetUp] - public override void Initialize() - { - base.Initialize(); - } - - [TearDown] - public override void TearDown() - { - base.TearDown(); - } - - [Test] - public void Can_Bulk_Insert() - { - // Arrange - var db = DatabaseContext.Database; - - var servers = new List(); - for (var i = 0; i < 1000; i++) - { - servers.Add(new ServerRegistrationDto - { - ServerAddress = "address" + i, - ServerIdentity = "computer" + i, - DateRegistered = DateTime.Now, - IsActive = true, - DateAccessed = DateTime.Now - }); - } - - // Act - using (ProfilingLogger.TraceDuration("starting insert", "finished insert")) - { - db.BulkInsertRecords(SqlSyntax, servers); - } - - // Assert - Assert.That(db.ExecuteScalar("SELECT COUNT(*) FROM umbracoServer"), Is.EqualTo(1000)); - } - - [Test] - public void Generate_Bulk_Import_Sql() - { - // Arrange - var db = DatabaseContext.Database; - - var servers = new List(); - for (var i = 0; i < 2; i++) - { - servers.Add(new ServerRegistrationDto - { - ServerAddress = "address" + i, - ServerIdentity = "computer" + i, - DateRegistered = DateTime.Now, - IsActive = true, - DateAccessed = DateTime.Now - }); - } - db.OpenSharedConnection(); - - // Act - string[] sql; - db.GenerateBulkInsertCommand(servers, db.Connection, out sql); - db.CloseSharedConnection(); - - // Assert - Assert.That(sql[0], - Is.EqualTo("INSERT INTO [umbracoServer] ([umbracoServer].[address], [umbracoServer].[computerName], [umbracoServer].[registeredDate], [umbracoServer].[lastNotifiedDate], [umbracoServer].[isActive], [umbracoServer].[isMaster]) VALUES (@0,@1,@2,@3,@4,@5), (@6,@7,@8,@9,@10,@11)")); - } - - - [Test] - public void Generate_Bulk_Import_Sql_Exceeding_Max_Params() - { - // Arrange - var db = DatabaseContext.Database; - - var servers = new List(); - for (var i = 0; i < 1500; i++) - { - servers.Add(new ServerRegistrationDto - { - ServerAddress = "address" + i, - ServerIdentity = "computer" + i, - DateRegistered = DateTime.Now, - IsActive = true, - DateAccessed = DateTime.Now, - IsMaster = true - }); - } - db.OpenSharedConnection(); - - // Act - string[] sql; - db.GenerateBulkInsertCommand(servers, db.Connection, out sql); - db.CloseSharedConnection(); - - // Assert - Assert.That(sql.Length, Is.EqualTo(5)); - foreach (var s in sql) - { - Assert.LessOrEqual(Regex.Matches(s, "@\\d+").Count, 2000); - } - } - } -} \ No newline at end of file diff --git a/src/Umbraco.Tests/Persistence/Querying/ContentRepositorySqlClausesTest.cs b/src/Umbraco.Tests/Persistence/Querying/ContentRepositorySqlClausesTest.cs index 99b3a3cdce..d926d3ce43 100644 --- a/src/Umbraco.Tests/Persistence/Querying/ContentRepositorySqlClausesTest.cs +++ b/src/Umbraco.Tests/Persistence/Querying/ContentRepositorySqlClausesTest.cs @@ -1,4 +1,5 @@ using System; +using NPoco; using NUnit.Framework; using Umbraco.Core; using Umbraco.Core.Models.Rdbms; @@ -23,21 +24,21 @@ namespace Umbraco.Tests.Persistence.Querying .InnerJoin("[umbracoNode]").On("[cmsContent].[nodeId] = [umbracoNode].[id]") .Where("([umbracoNode].[nodeObjectType] = @0)", new Guid("c66ba18e-eaf3-4cff-8a22-41b16d66a972")); - var sql = new Sql(); - sql.Select("*") - .From(SqlSyntax) - .InnerJoin(SqlSyntax) - .On(SqlSyntax, left => left.VersionId, right => right.VersionId) - .InnerJoin(SqlSyntax) - .On(SqlSyntax, left => left.NodeId, right => right.NodeId) - .InnerJoin(SqlSyntax) - .On(SqlSyntax, left => left.NodeId, right => right.NodeId) - .Where(SqlSyntax, x => x.NodeObjectType == NodeObjectType); + var sql = Sql(); + sql.SelectAll() + .From() + .InnerJoin() + .On(left => left.VersionId, right => right.VersionId) + .InnerJoin() + .On(left => left.NodeId, right => right.NodeId) + .InnerJoin() + .On(left => left.NodeId, right => right.NodeId) + .Where(x => x.NodeObjectType == NodeObjectType); Assert.That(sql.SQL, Is.EqualTo(expected.SQL)); Assert.AreEqual(expected.Arguments.Length, sql.Arguments.Length); - for (int i = 0; i < expected.Arguments.Length; i++) + for (var i = 0; i < expected.Arguments.Length; i++) { Assert.AreEqual(expected.Arguments[i], sql.Arguments[i]); } @@ -50,8 +51,8 @@ namespace Umbraco.Tests.Persistence.Querying { var NodeObjectType = new Guid(Constants.ObjectTypes.Document); - var expected = new Sql(); - expected.Select("*") + var expected = Sql(); + expected.SelectAll() .From("[cmsDocument]") .InnerJoin("[cmsContentVersion]").On("[cmsDocument].[versionId] = [cmsContentVersion].[VersionId]") .InnerJoin("[cmsContent]").On("[cmsContentVersion].[ContentId] = [cmsContent].[nodeId]") @@ -59,17 +60,17 @@ namespace Umbraco.Tests.Persistence.Querying .Where("([umbracoNode].[nodeObjectType] = @0)", new Guid("c66ba18e-eaf3-4cff-8a22-41b16d66a972")) .Where("([umbracoNode].[id] = @0)", 1050); - var sql = new Sql(); - sql.Select("*") - .From(SqlSyntax) - .InnerJoin(SqlSyntax) - .On(SqlSyntax, left => left.VersionId, right => right.VersionId) - .InnerJoin(SqlSyntax) - .On(SqlSyntax, left => left.NodeId, right => right.NodeId) - .InnerJoin(SqlSyntax) - .On(SqlSyntax, left => left.NodeId, right => right.NodeId) - .Where(SqlSyntax, x => x.NodeObjectType == NodeObjectType) - .Where(SqlSyntax, x => x.NodeId == 1050); + var sql = Sql(); + sql.SelectAll() + .From() + .InnerJoin() + .On(left => left.VersionId, right => right.VersionId) + .InnerJoin() + .On(left => left.NodeId, right => right.NodeId) + .InnerJoin() + .On(left => left.NodeId, right => right.NodeId) + .Where(x => x.NodeObjectType == NodeObjectType) + .Where(x => x.NodeId == 1050); Assert.That(sql.SQL, Is.EqualTo(expected.SQL)); @@ -99,19 +100,19 @@ namespace Umbraco.Tests.Persistence.Querying .Where("([cmsContentVersion].[VersionId] = @0)", new Guid("2b543516-a944-4ee6-88c6-8813da7aaa07")) .OrderBy("[cmsContentVersion].[VersionDate] DESC"); - var sql = new Sql(); - sql.Select("*") - .From(SqlSyntax) - .InnerJoin(SqlSyntax) - .On(SqlSyntax, left => left.VersionId, right => right.VersionId) - .InnerJoin(SqlSyntax) - .On(SqlSyntax, left => left.NodeId, right => right.NodeId) - .InnerJoin(SqlSyntax) - .On(SqlSyntax, left => left.NodeId, right => right.NodeId) - .Where(SqlSyntax, x => x.NodeObjectType == NodeObjectType) - .Where(SqlSyntax, x => x.NodeId == 1050) - .Where(SqlSyntax, x => x.VersionId == versionId) - .OrderByDescending(SqlSyntax, x => x.VersionDate); + var sql = Sql(); + sql.SelectAll() + .From() + .InnerJoin() + .On(left => left.VersionId, right => right.VersionId) + .InnerJoin() + .On(left => left.NodeId, right => right.NodeId) + .InnerJoin() + .On(left => left.NodeId, right => right.NodeId) + .Where(x => x.NodeObjectType == NodeObjectType) + .Where(x => x.NodeId == 1050) + .Where(x => x.VersionId == versionId) + .OrderByDescending(x => x.VersionDate); Assert.That(sql.SQL, Is.EqualTo(expected.SQL)); Assert.AreEqual(expected.Arguments.Length, sql.Arguments.Length); @@ -136,13 +137,13 @@ namespace Umbraco.Tests.Persistence.Querying expected.Where("([cmsPropertyData].[contentNodeId] = @0)", 1050); expected.Where("([cmsPropertyData].[versionId] = @0)", new Guid("2b543516-a944-4ee6-88c6-8813da7aaa07")); - var sql = new Sql(); - sql.Select("*") - .From(SqlSyntax) - .InnerJoin(SqlSyntax) - .On(SqlSyntax, left => left.PropertyTypeId, right => right.Id) - .Where(SqlSyntax, x => x.NodeId == id) - .Where(SqlSyntax, x => x.VersionId == versionId); + var sql = Sql(); + sql.SelectAll() + .From() + .InnerJoin() + .On(left => left.PropertyTypeId, right => right.Id) + .Where(x => x.NodeId == id) + .Where(x => x.VersionId == versionId); Assert.That(sql.SQL, Is.EqualTo(expected.SQL)); Assert.AreEqual(expected.Arguments.Length, sql.Arguments.Length); diff --git a/src/Umbraco.Tests/Persistence/Querying/ContentTypeRepositorySqlClausesTest.cs b/src/Umbraco.Tests/Persistence/Querying/ContentTypeRepositorySqlClausesTest.cs index bf2d0693ae..6c16ce927a 100644 --- a/src/Umbraco.Tests/Persistence/Querying/ContentTypeRepositorySqlClausesTest.cs +++ b/src/Umbraco.Tests/Persistence/Querying/ContentTypeRepositorySqlClausesTest.cs @@ -1,4 +1,5 @@ using System; +using NPoco; using NUnit.Framework; using Umbraco.Core; using Umbraco.Core.Models.Rdbms; @@ -15,9 +16,8 @@ namespace Umbraco.Tests.Persistence.Querying public void Can_Verify_Base_Clause() { var nodeObjectType = new Guid(Constants.ObjectTypes.DocumentType); - var sqlSyntaxProvider = new SqlCeSyntaxProvider(); - var expected = new Sql(); + var expected = Sql(); expected.Select("*") .From("[cmsDocumentType]") .RightJoin("[cmsContentType]") @@ -27,15 +27,15 @@ namespace Umbraco.Tests.Persistence.Querying .Where("([umbracoNode].[nodeObjectType] = @0)", new Guid("a2cb7800-f571-4787-9638-bc48539a0efb")) .Where("([cmsDocumentType].[IsDefault] = @0)", true); - var sql = new Sql(); - sql.Select("*") - .From(sqlSyntaxProvider) - .RightJoin(sqlSyntaxProvider) - .On(sqlSyntaxProvider, left => left.NodeId, right => right.ContentTypeNodeId) - .InnerJoin(sqlSyntaxProvider) - .On(sqlSyntaxProvider, left => left.NodeId, right => right.NodeId) - .Where(sqlSyntaxProvider, x => x.NodeObjectType == nodeObjectType) - .Where(sqlSyntaxProvider, x => x.IsDefault == true); + var sql = Sql(); + sql.SelectAll() + .From() + .RightJoin() + .On(left => left.NodeId, right => right.ContentTypeNodeId) + .InnerJoin() + .On(left => left.NodeId, right => right.NodeId) + .Where(x => x.NodeObjectType == nodeObjectType) + .Where(x => x.IsDefault == true); Assert.That(sql.SQL, Is.EqualTo(expected.SQL)); @@ -52,10 +52,9 @@ namespace Umbraco.Tests.Persistence.Querying public void Can_Verify_Base_Where_Clause() { var nodeObjectType = new Guid(Constants.ObjectTypes.DocumentType); - var sqlSyntaxProvider = new SqlCeSyntaxProvider(); - var expected = new Sql(); - expected.Select("*") + var expected = Sql(); + expected.SelectAll() .From("[cmsDocumentType]") .RightJoin("[cmsContentType]") .On("[cmsContentType].[nodeId] = [cmsDocumentType].[contentTypeNodeId]") @@ -65,16 +64,16 @@ namespace Umbraco.Tests.Persistence.Querying .Where("[cmsDocumentType].[IsDefault] = @0", true) .Where("([umbracoNode].[id] = @0)", 1050); - var sql = new Sql(); - sql.Select("*") - .From(sqlSyntaxProvider) - .RightJoin(sqlSyntaxProvider) - .On(sqlSyntaxProvider, left => left.NodeId, right => right.ContentTypeNodeId) - .InnerJoin(sqlSyntaxProvider) - .On(sqlSyntaxProvider, left => left.NodeId, right => right.NodeId) - .Where(sqlSyntaxProvider, x => x.NodeObjectType == nodeObjectType) - .Where(sqlSyntaxProvider, x => x.IsDefault) - .Where(sqlSyntaxProvider, x => x.NodeId == 1050); + var sql = Sql(); + sql.SelectAll() + .From() + .RightJoin() + .On(left => left.NodeId, right => right.ContentTypeNodeId) + .InnerJoin() + .On(left => left.NodeId, right => right.NodeId) + .Where(x => x.NodeObjectType == nodeObjectType) + .Where(x => x.IsDefault) + .Where(x => x.NodeId == 1050); Assert.That(sql.SQL, Is.EqualTo(expected.SQL)); @@ -90,20 +89,19 @@ namespace Umbraco.Tests.Persistence.Querying [Test] public void Can_Verify_PerformQuery_Clause() { - var sqlSyntaxProvider = new SqlCeSyntaxProvider(); - var expected = new Sql(); - expected.Select("*") + var expected = Sql(); + expected.SelectAll() .From("[cmsPropertyTypeGroup]") .RightJoin("[cmsPropertyType]").On("[cmsPropertyTypeGroup].[id] = [cmsPropertyType].[propertyTypeGroupId]") .InnerJoin("[cmsDataType]").On("[cmsPropertyType].[dataTypeId] = [cmsDataType].[nodeId]"); - var sql = new Sql(); - sql.Select("*") - .From(sqlSyntaxProvider) - .RightJoin(sqlSyntaxProvider) - .On(sqlSyntaxProvider, left => left.Id, right => right.PropertyTypeGroupId) - .InnerJoin(sqlSyntaxProvider) - .On(sqlSyntaxProvider, left => left.DataTypeId, right => right.DataTypeId); + var sql = Sql(); + sql.SelectAll() + .From() + .RightJoin() + .On(left => left.Id, right => right.PropertyTypeGroupId) + .InnerJoin() + .On(left => left.DataTypeId, right => right.DataTypeId); Assert.That(sql.SQL, Is.EqualTo(expected.SQL)); @@ -113,16 +111,15 @@ namespace Umbraco.Tests.Persistence.Querying [Test] public void Can_Verify_AllowedContentTypeIds_Clause() { - var expected = new Sql(); - var sqlSyntaxProvider = new SqlCeSyntaxProvider(); - expected.Select("*") + var expected = Sql(); + expected.SelectAll() .From("[cmsContentTypeAllowedContentType]") .Where("([cmsContentTypeAllowedContentType].[Id] = @0)", 1050); - var sql = new Sql(); - sql.Select("*") - .From(sqlSyntaxProvider) - .Where(sqlSyntaxProvider, x => x.Id == 1050); + var sql = Sql(); + sql.SelectAll() + .From() + .Where(x => x.Id == 1050); Assert.That(sql.SQL, Is.EqualTo(expected.SQL)); @@ -138,22 +135,21 @@ namespace Umbraco.Tests.Persistence.Querying [Test] public void Can_Verify_PropertyGroupCollection_Clause() { - var expected = new Sql(); - var sqlSyntaxProvider = new SqlCeSyntaxProvider(); - expected.Select("*") + var expected = Sql(); + expected.SelectAll() .From("[cmsPropertyTypeGroup]") .RightJoin("[cmsPropertyType]").On("[cmsPropertyTypeGroup].[id] = [cmsPropertyType].[propertyTypeGroupId]") .InnerJoin("[cmsDataType]").On("[cmsPropertyType].[dataTypeId] = [cmsDataType].[nodeId]") .Where("([cmsPropertyType].[contentTypeId] = @0)", 1050); - var sql = new Sql(); - sql.Select("*") - .From(sqlSyntaxProvider) - .RightJoin(sqlSyntaxProvider) - .On(sqlSyntaxProvider, left => left.Id, right => right.PropertyTypeGroupId) - .InnerJoin(sqlSyntaxProvider) - .On(sqlSyntaxProvider, left => left.DataTypeId, right => right.DataTypeId) - .Where(sqlSyntaxProvider, x => x.ContentTypeId == 1050); + var sql = Sql(); + sql.SelectAll() + .From() + .RightJoin() + .On(left => left.Id, right => right.PropertyTypeGroupId) + .InnerJoin() + .On(left => left.DataTypeId, right => right.DataTypeId) + .Where(x => x.ContentTypeId == 1050); Assert.That(sql.SQL, Is.EqualTo(expected.SQL)); diff --git a/src/Umbraco.Tests/Persistence/Querying/ContentTypeSqlMappingTests.cs b/src/Umbraco.Tests/Persistence/Querying/ContentTypeSqlMappingTests.cs index 8c299d414b..006d2dc659 100644 --- a/src/Umbraco.Tests/Persistence/Querying/ContentTypeSqlMappingTests.cs +++ b/src/Umbraco.Tests/Persistence/Querying/ContentTypeSqlMappingTests.cs @@ -3,12 +3,12 @@ using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; +using NPoco; using NUnit.Framework; using Umbraco.Core; using Umbraco.Core.Models; using Umbraco.Core.Models.Rdbms; using Umbraco.Core.Persistence; -using Umbraco.Core.Persistence.Relators; using Umbraco.Core.Persistence.Repositories; using Umbraco.Core.Persistence.SqlSyntax; using Umbraco.Tests.TestHelpers; diff --git a/src/Umbraco.Tests/Persistence/Querying/DataTypeDefinitionRepositorySqlClausesTest.cs b/src/Umbraco.Tests/Persistence/Querying/DataTypeDefinitionRepositorySqlClausesTest.cs index 55805282a4..5ba86af69d 100644 --- a/src/Umbraco.Tests/Persistence/Querying/DataTypeDefinitionRepositorySqlClausesTest.cs +++ b/src/Umbraco.Tests/Persistence/Querying/DataTypeDefinitionRepositorySqlClausesTest.cs @@ -1,4 +1,5 @@ using System; +using NPoco; using NUnit.Framework; using Umbraco.Core; using Umbraco.Core.Models.Rdbms; @@ -21,12 +22,12 @@ namespace Umbraco.Tests.Persistence.Querying .InnerJoin("[umbracoNode]").On("[cmsDataType].[nodeId] = [umbracoNode].[id]") .Where("([umbracoNode].[nodeObjectType] = @0)", new Guid("30a2a501-1978-4ddb-a57b-f7efed43ba3c")); - var sql = new Sql(); - sql.Select("*") - .From(SqlSyntax) - .InnerJoin(SqlSyntax) - .On(SqlSyntax, left => left.DataTypeId, right => right.NodeId) - .Where(SqlSyntax, x => x.NodeObjectType == NodeObjectTypeId); + var sql = Sql(); + sql.SelectAll() + .From() + .InnerJoin() + .On(left => left.DataTypeId, right => right.NodeId) + .Where(x => x.NodeObjectType == NodeObjectTypeId); Assert.That(sql.SQL, Is.EqualTo(expected.SQL)); diff --git a/src/Umbraco.Tests/Persistence/Querying/ExpressionTests.cs b/src/Umbraco.Tests/Persistence/Querying/ExpressionTests.cs index 9100a77eb0..ce8fa1068a 100644 --- a/src/Umbraco.Tests/Persistence/Querying/ExpressionTests.cs +++ b/src/Umbraco.Tests/Persistence/Querying/ExpressionTests.cs @@ -1,11 +1,13 @@ using System; using System.Linq.Expressions; using Moq; +using NPoco; using NUnit.Framework; using Umbraco.Core.Logging; using Umbraco.Core.Models; using Umbraco.Core.Models.Membership; using Umbraco.Core.Models.Rdbms; +using Umbraco.Core.Persistence; using Umbraco.Core.Persistence.Mappers; using Umbraco.Core.Persistence.Querying; using Umbraco.Core.Persistence.SqlSyntax; @@ -14,7 +16,7 @@ using Umbraco.Tests.TestHelpers; namespace Umbraco.Tests.Persistence.Querying { [TestFixture] - public class ExpressionTests + public class ExpressionTests : BaseUsingSqlCeSyntax { // [Test] // public void Can_Query_With_Content_Type_Alias() @@ -34,9 +36,8 @@ namespace Umbraco.Tests.Persistence.Querying public void Can_Verify_Path_StartsWith_Predicate_In_Same_Result() { //Arrange - var sqlSyntax = new SqlCeSyntaxProvider(); Expression> predicate = content => content.Path.StartsWith("-1"); - var modelToSqlExpressionHelper = new ModelToSqlExpressionHelper(sqlSyntax, new ContentMapper(sqlSyntax)); + var modelToSqlExpressionHelper = new ModelToSqlExpressionHelper(SqlContext.SqlSyntax, new ContentMapper(SqlContext.SqlSyntax)); var result = modelToSqlExpressionHelper.Visit(predicate); Console.WriteLine("Model to Sql ExpressionHelper: \n" + result); @@ -49,9 +50,8 @@ namespace Umbraco.Tests.Persistence.Querying public void Can_Verify_ParentId_StartsWith_Predicate_In_Same_Result() { //Arrange - var sqlSyntax = new SqlCeSyntaxProvider(); Expression> predicate = content => content.ParentId == -1; - var modelToSqlExpressionHelper = new ModelToSqlExpressionHelper(sqlSyntax, new ContentMapper(sqlSyntax)); + var modelToSqlExpressionHelper = new ModelToSqlExpressionHelper(SqlContext.SqlSyntax, new ContentMapper(SqlContext.SqlSyntax)); var result = modelToSqlExpressionHelper.Visit(predicate); Console.WriteLine("Model to Sql ExpressionHelper: \n" + result); @@ -63,9 +63,8 @@ namespace Umbraco.Tests.Persistence.Querying [Test] public void Equals_Operator_For_Value_Gets_Escaped() { - var sqlSyntax = new SqlCeSyntaxProvider(); Expression> predicate = user => user.Username == "hello@world.com"; - var modelToSqlExpressionHelper = new ModelToSqlExpressionHelper(sqlSyntax, new UserMapper(sqlSyntax)); + var modelToSqlExpressionHelper = new ModelToSqlExpressionHelper(SqlContext.SqlSyntax, new UserMapper(SqlContext.SqlSyntax)); var result = modelToSqlExpressionHelper.Visit(predicate); Console.WriteLine("Model to Sql ExpressionHelper: \n" + result); @@ -79,7 +78,7 @@ namespace Umbraco.Tests.Persistence.Querying { var sqlSyntax = new SqlCeSyntaxProvider(); Expression> predicate = user => user.Username.Equals("hello@world.com"); - var modelToSqlExpressionHelper = new ModelToSqlExpressionHelper(sqlSyntax, new UserMapper(sqlSyntax)); + var modelToSqlExpressionHelper = new ModelToSqlExpressionHelper(SqlContext.SqlSyntax, new UserMapper(SqlContext.SqlSyntax)); var result = modelToSqlExpressionHelper.Visit(predicate); Console.WriteLine("Model to Sql ExpressionHelper: \n" + result); @@ -93,8 +92,10 @@ namespace Umbraco.Tests.Persistence.Querying { //mysql escapes backslashes, so we'll test with that var sqlSyntax = new MySqlSyntaxProvider(Mock.Of()); + var sqlContext = new SqlContext(sqlSyntax, SqlContext.PocoDataFactory, DatabaseType.MySQL); + Expression> predicate = user => user.Username.Equals("mydomain\\myuser"); - var modelToSqlExpressionHelper = new ModelToSqlExpressionHelper(sqlSyntax, new UserMapper(sqlSyntax)); + var modelToSqlExpressionHelper = new ModelToSqlExpressionHelper(sqlContext.SqlSyntax, new UserMapper(sqlContext.SqlSyntax)); var result = modelToSqlExpressionHelper.Visit(predicate); Console.WriteLine("Model to Sql ExpressionHelper: \n" + result); @@ -109,8 +110,10 @@ namespace Umbraco.Tests.Persistence.Querying { //mysql escapes backslashes, so we'll test with that var sqlSyntax = new MySqlSyntaxProvider(Mock.Of()); + var sqlContext = new SqlContext(sqlSyntax, SqlContext.PocoDataFactory, DatabaseType.MySQL); + Expression> predicate = user => user.Login.StartsWith("mydomain\\myuser"); - var modelToSqlExpressionHelper = new PocoToSqlExpressionHelper(sqlSyntax); + var modelToSqlExpressionHelper = new PocoToSqlExpressionHelper(sqlContext); var result = modelToSqlExpressionHelper.Visit(predicate); Console.WriteLine("Poco to Sql ExpressionHelper: \n" + result); diff --git a/src/Umbraco.Tests/Persistence/Querying/MediaRepositorySqlClausesTest.cs b/src/Umbraco.Tests/Persistence/Querying/MediaRepositorySqlClausesTest.cs index 5d4501eb15..6fcbd6643e 100644 --- a/src/Umbraco.Tests/Persistence/Querying/MediaRepositorySqlClausesTest.cs +++ b/src/Umbraco.Tests/Persistence/Querying/MediaRepositorySqlClausesTest.cs @@ -1,4 +1,5 @@ using System; +using NPoco; using NUnit.Framework; using Umbraco.Core; using Umbraco.Core.Models.Rdbms; @@ -22,14 +23,14 @@ namespace Umbraco.Tests.Persistence.Querying .InnerJoin("[umbracoNode]").On("[cmsContent].[nodeId] = [umbracoNode].[id]") .Where("([umbracoNode].[nodeObjectType] = @0)", new Guid("b796f64c-1f99-4ffb-b886-4bf4bc011a9c")); - var sql = new Sql(); - sql.Select("*") - .From(SqlSyntax) - .InnerJoin(SqlSyntax) - .On(SqlSyntax, left => left.NodeId, right => right.NodeId) - .InnerJoin(SqlSyntax) - .On(SqlSyntax, left => left.NodeId, right => right.NodeId) - .Where(SqlSyntax, x => x.NodeObjectType == NodeObjectTypeId); + var sql = Sql(); + sql.SelectAll() + .From() + .InnerJoin() + .On(left => left.NodeId, right => right.NodeId) + .InnerJoin() + .On(left => left.NodeId, right => right.NodeId) + .Where(x => x.NodeObjectType == NodeObjectTypeId); Assert.That(sql.SQL, Is.EqualTo(expected.SQL)); diff --git a/src/Umbraco.Tests/Persistence/Querying/MediaTypeRepositorySqlClausesTest.cs b/src/Umbraco.Tests/Persistence/Querying/MediaTypeRepositorySqlClausesTest.cs index 6d6ec4ed2c..f1893f6ee5 100644 --- a/src/Umbraco.Tests/Persistence/Querying/MediaTypeRepositorySqlClausesTest.cs +++ b/src/Umbraco.Tests/Persistence/Querying/MediaTypeRepositorySqlClausesTest.cs @@ -1,4 +1,5 @@ using System; +using NPoco; using NUnit.Framework; using Umbraco.Core; using Umbraco.Core.Models.Rdbms; @@ -21,12 +22,12 @@ namespace Umbraco.Tests.Persistence.Querying .InnerJoin("[umbracoNode]").On("[cmsContentType].[nodeId] = [umbracoNode].[id]") .Where("([umbracoNode].[nodeObjectType] = @0)", new Guid("4ea4382b-2f5a-4c2b-9587-ae9b3cf3602e")); - var sql = new Sql(); - sql.Select("*") - .From(SqlSyntax) - .InnerJoin(SqlSyntax) - .On(SqlSyntax, left => left.NodeId, right => right.NodeId) - .Where(SqlSyntax, x => x.NodeObjectType == NodeObjectTypeId); + var sql = Sql(); + sql.SelectAll() + .From() + .InnerJoin() + .On(left => left.NodeId, right => right.NodeId) + .Where(x => x.NodeObjectType == NodeObjectTypeId); Assert.That(sql.SQL, Is.EqualTo(expected.SQL)); diff --git a/src/Umbraco.Tests/Persistence/Querying/PetaPocoSqlTests.cs b/src/Umbraco.Tests/Persistence/Querying/NPocoSqlTests.cs similarity index 63% rename from src/Umbraco.Tests/Persistence/Querying/PetaPocoSqlTests.cs rename to src/Umbraco.Tests/Persistence/Querying/NPocoSqlTests.cs index 705e625d47..de0081be23 100644 --- a/src/Umbraco.Tests/Persistence/Querying/PetaPocoSqlTests.cs +++ b/src/Umbraco.Tests/Persistence/Querying/NPocoSqlTests.cs @@ -1,18 +1,15 @@ using System; -using System.Linq; +using NPoco; using NUnit.Framework; -using Umbraco.Core.Models; -using Umbraco.Core.Models.Membership; using Umbraco.Core.Models.Rdbms; using Umbraco.Core.Persistence; -using Umbraco.Core.Persistence.Repositories; using Umbraco.Tests.TestHelpers; using Umbraco.Core.Persistence.Querying; namespace Umbraco.Tests.Persistence.Querying { [TestFixture] - public class PetaPocoSqlTests : BaseUsingSqlCeSyntax + public class NPocoSqlTests : BaseUsingSqlCeSyntax { //x => @@ -20,8 +17,8 @@ namespace Umbraco.Tests.Persistence.Querying public void Where_Clause_With_Starts_With_Additional_Parameters() { var content = new NodeDto() { NodeId = 123, Path = "-1,123" }; - var sql = new Sql("SELECT *").From(SqlSyntax) - .Where(SqlSyntax, x => x.Path.SqlStartsWith(content.Path, TextColumnType.NVarchar)); + var sql = Sql().SelectAll().From() + .Where(x => x.Path.SqlStartsWith(content.Path, TextColumnType.NVarchar)); Assert.AreEqual("SELECT * FROM [umbracoNode] WHERE (upper([umbracoNode].[path]) LIKE upper(@0))", sql.SQL.Replace("\n", " ")); Assert.AreEqual(1, sql.Arguments.Length); @@ -32,8 +29,8 @@ namespace Umbraco.Tests.Persistence.Querying public void Where_Clause_With_Starts_With_By_Variable() { var content = new NodeDto() {NodeId = 123, Path = "-1,123"}; - var sql = new Sql("SELECT *").From(SqlSyntax) - .Where(SqlSyntax, x => x.Path.StartsWith(content.Path) && x.NodeId != content.NodeId); + var sql = Sql().SelectAll().From() + .Where(x => x.Path.StartsWith(content.Path) && x.NodeId != content.NodeId); Assert.AreEqual("SELECT * FROM [umbracoNode] WHERE ((upper([umbracoNode].[path]) LIKE upper(@0) AND ([umbracoNode].[id] <> @1)))", sql.SQL.Replace("\n", " ")); Assert.AreEqual(2, sql.Arguments.Length); @@ -44,9 +41,9 @@ namespace Umbraco.Tests.Persistence.Querying [Test] public void Where_Clause_With_Not_Starts_With() { - var level = 1; - var sql = new Sql("SELECT *").From(SqlSyntax) - .Where(SqlSyntax, x => x.Level == level && !x.Path.StartsWith("-20")); + const int level = 1; + var sql = Sql().SelectAll().From() + .Where(x => x.Level == level && !x.Path.StartsWith("-20")); Assert.AreEqual("SELECT * FROM [umbracoNode] WHERE ((([umbracoNode].[level] = @0) AND NOT (upper([umbracoNode].[path]) LIKE upper(@1))))", sql.SQL.Replace("\n", " ")); Assert.AreEqual(2, sql.Arguments.Length); @@ -57,8 +54,9 @@ namespace Umbraco.Tests.Persistence.Querying [Test] public void Where_Clause_With_EqualsFalse_Starts_With() { - var level = 1; - var sql = new Sql("SELECT *").From(SqlSyntax).Where(SqlSyntax, x => x.Level == level && x.Path.StartsWith("-20") == false); + const int level = 1; + var sql = Sql().SelectAll().From() + .Where(x => x.Level == level && x.Path.StartsWith("-20") == false); Assert.AreEqual("SELECT * FROM [umbracoNode] WHERE ((([umbracoNode].[level] = @0) AND NOT (upper([umbracoNode].[path]) LIKE upper(@1))))", sql.SQL.Replace("\n", " ")); Assert.AreEqual(2, sql.Arguments.Length); @@ -69,8 +67,8 @@ namespace Umbraco.Tests.Persistence.Querying [Test] public void Where_Clause_With_Equals_Clause() { - var sql = new Sql("SELECT *").From(SqlSyntax) - .Where(SqlSyntax, x => x.Text.Equals("Hello@world.com")); + var sql = Sql().SelectAll().From() + .Where(x => x.Text.Equals("Hello@world.com")); Assert.AreEqual("SELECT * FROM [umbracoNode] WHERE (upper([umbracoNode].[text]) = upper(@0))", sql.SQL.Replace("\n", " ")); Assert.AreEqual(1, sql.Arguments.Length); @@ -80,8 +78,8 @@ namespace Umbraco.Tests.Persistence.Querying [Test] public void Where_Clause_With_False_Boolean() { - var sql = new Sql("SELECT *").From(SqlSyntax) - .Where(SqlSyntax, x => !x.Trashed); + var sql = Sql().SelectAll().From() + .Where(x => x.Trashed == false); Assert.AreEqual("SELECT * FROM [umbracoNode] WHERE (NOT ([umbracoNode].[trashed] = @0))", sql.SQL.Replace("\n", " ")); Assert.AreEqual(1, sql.Arguments.Length); @@ -91,7 +89,7 @@ namespace Umbraco.Tests.Persistence.Querying [Test] public void Where_Clause_With_EqualsFalse_Boolean() { - var sql = new Sql("SELECT *").From(SqlSyntax).Where(SqlSyntax, x => x.Trashed == false); + var sql = Sql().SelectAll().From().Where(x => x.Trashed == false); Assert.AreEqual("SELECT * FROM [umbracoNode] WHERE (NOT ([umbracoNode].[trashed] = @0))", sql.SQL.Replace("\n", " ")); Assert.AreEqual(1, sql.Arguments.Length); @@ -101,8 +99,8 @@ namespace Umbraco.Tests.Persistence.Querying [Test] public void Where_Clause_With_Boolean() { - var sql = new Sql("SELECT *").From(SqlSyntax) - .Where(SqlSyntax, x => x.Trashed); + var sql = Sql().SelectAll().From() + .Where(x => x.Trashed); Assert.AreEqual("SELECT * FROM [umbracoNode] WHERE ([umbracoNode].[trashed] = @0)", sql.SQL.Replace("\n", " ")); Assert.AreEqual(1, sql.Arguments.Length); @@ -112,8 +110,8 @@ namespace Umbraco.Tests.Persistence.Querying [Test] public void Where_Clause_With_ToUpper() { - var sql = new Sql("SELECT *").From(SqlSyntax) - .Where(SqlSyntax, x => x.Text.ToUpper() == "hello".ToUpper()); + var sql = Sql().SelectAll().From() + .Where(x => x.Text.ToUpper() == "hello".ToUpper()); Assert.AreEqual("SELECT * FROM [umbracoNode] WHERE ((upper([umbracoNode].[text]) = upper(@0)))", sql.SQL.Replace("\n", " ")); Assert.AreEqual(1, sql.Arguments.Length); @@ -123,8 +121,8 @@ namespace Umbraco.Tests.Persistence.Querying [Test] public void Where_Clause_With_ToString() { - var sql = new Sql("SELECT *").From(SqlSyntax) - .Where(SqlSyntax, x => x.Text == 1.ToString()); + var sql = Sql().SelectAll().From() + .Where(x => x.Text == 1.ToString()); Assert.AreEqual("SELECT * FROM [umbracoNode] WHERE (([umbracoNode].[text] = @0))", sql.SQL.Replace("\n", " ")); Assert.AreEqual(1, sql.Arguments.Length); @@ -134,8 +132,8 @@ namespace Umbraco.Tests.Persistence.Querying [Test] public void Where_Clause_With_Wildcard() { - var sql = new Sql("SELECT *").From(SqlSyntax) - .Where(SqlSyntax, x => x.Text.StartsWith("D")); + var sql = Sql().SelectAll().From() + .Where(x => x.Text.StartsWith("D")); Assert.AreEqual("SELECT * FROM [umbracoNode] WHERE (upper([umbracoNode].[text]) LIKE upper(@0))", sql.SQL.Replace("\n", " ")); Assert.AreEqual(1, sql.Arguments.Length); @@ -145,8 +143,8 @@ namespace Umbraco.Tests.Persistence.Querying [Test] public void Where_Clause_Single_Constant() { - var sql = new Sql("SELECT *").From(SqlSyntax) - .Where(SqlSyntax, x => x.NodeId == 2); + var sql = Sql().SelectAll().From() + .Where(x => x.NodeId == 2); Assert.AreEqual("SELECT * FROM [umbracoNode] WHERE (([umbracoNode].[id] = @0))", sql.SQL.Replace("\n", " ")); Assert.AreEqual(1, sql.Arguments.Length); @@ -156,8 +154,8 @@ namespace Umbraco.Tests.Persistence.Querying [Test] public void Where_Clause_And_Constant() { - var sql = new Sql("SELECT *").From(SqlSyntax) - .Where(SqlSyntax, x => x.NodeId != 2 && x.NodeId != 3); + var sql = Sql().SelectAll().From() + .Where(x => x.NodeId != 2 && x.NodeId != 3); Assert.AreEqual("SELECT * FROM [umbracoNode] WHERE ((([umbracoNode].[id] <> @0) AND ([umbracoNode].[id] <> @1)))", sql.SQL.Replace("\n", " ")); Assert.AreEqual(2, sql.Arguments.Length); @@ -168,8 +166,8 @@ namespace Umbraco.Tests.Persistence.Querying [Test] public void Where_Clause_Or_Constant() { - var sql = new Sql("SELECT *").From(SqlSyntax) - .Where(SqlSyntax, x => x.Text == "hello" || x.NodeId == 3); + var sql = Sql().SelectAll().From() + .Where(x => x.Text == "hello" || x.NodeId == 3); Assert.AreEqual("SELECT * FROM [umbracoNode] WHERE ((([umbracoNode].[text] = @0) OR ([umbracoNode].[id] = @1)))", sql.SQL.Replace("\n", " ")); Assert.AreEqual(2, sql.Arguments.Length); @@ -180,11 +178,11 @@ namespace Umbraco.Tests.Persistence.Querying [Test] public void Can_Select_From_With_Type() { - var expected = new Sql(); - expected.Select("*").From("[cmsContent]"); + var expected = Sql(); + expected.SelectAll().From("[cmsContent]"); - var sql = new Sql(); - sql.Select("*").From(SqlSyntax); + var sql = Sql(); + sql.SelectAll().From(); Assert.That(sql.SQL, Is.EqualTo(expected.SQL)); @@ -194,16 +192,16 @@ namespace Umbraco.Tests.Persistence.Querying [Test] public void Can_InnerJoin_With_Types() { - var expected = new Sql(); - expected.Select("*") + var expected = Sql(); + expected.SelectAll() .From("[cmsDocument]") .InnerJoin("[cmsContentVersion]") .On("[cmsDocument].[versionId] = [cmsContentVersion].[VersionId]"); - var sql = new Sql(); - sql.Select("*").From(SqlSyntax) - .InnerJoin(SqlSyntax) - .On(SqlSyntax, left => left.VersionId, right => right.VersionId); + var sql = Sql(); + sql.SelectAll().From() + .InnerJoin() + .On(left => left.VersionId, right => right.VersionId); Assert.That(sql.SQL, Is.EqualTo(expected.SQL)); @@ -213,11 +211,11 @@ namespace Umbraco.Tests.Persistence.Querying [Test] public void Can_OrderBy_With_Type() { - var expected = new Sql(); - expected.Select("*").From("[cmsContent]").OrderBy("([cmsContent].[contentType])"); + var expected = Sql(); + expected.SelectAll().From("[cmsContent]").OrderBy("([cmsContent].[contentType])"); - var sql = new Sql(); - sql.Select("*").From(SqlSyntax).OrderBy(SqlSyntax, x => x.ContentTypeId); + var sql = Sql(); + sql.SelectAll().From().OrderBy(x => x.ContentTypeId); Assert.That(sql.SQL, Is.EqualTo(expected.SQL)); @@ -227,11 +225,11 @@ namespace Umbraco.Tests.Persistence.Querying [Test] public void Can_GroupBy_With_Type() { - var expected = new Sql(); - expected.Select("*").From("[cmsContent]").GroupBy("[contentType]"); + var expected = Sql(); + expected.SelectAll().From("[cmsContent]").GroupBy("[contentType]"); - var sql = new Sql(); - sql.Select("*").From(SqlSyntax).GroupBy(SqlSyntax, x => x.ContentTypeId); + var sql = Sql(); + sql.SelectAll().From().GroupBy(x => x.ContentTypeId); Assert.That(sql.SQL, Is.EqualTo(expected.SQL)); @@ -241,11 +239,11 @@ namespace Umbraco.Tests.Persistence.Querying [Test] public void Can_Use_Where_Predicate() { - var expected = new Sql(); - expected.Select("*").From("[cmsContent]").Where("([cmsContent].[nodeId] = @0)", 1045); + var expected = Sql(); + expected.SelectAll().From("[cmsContent]").Where("([cmsContent].[nodeId] = @0)", 1045); - var sql = new Sql(); - sql.Select("*").From(SqlSyntax).Where(SqlSyntax, x => x.NodeId == 1045); + var sql = Sql(); + sql.SelectAll().From().Where(x => x.NodeId == 1045); Assert.That(sql.SQL, Is.EqualTo(expected.SQL)); @@ -255,17 +253,17 @@ namespace Umbraco.Tests.Persistence.Querying [Test] public void Can_Use_Where_And_Predicate() { - var expected = new Sql(); - expected.Select("*") + var expected = Sql(); + expected.SelectAll() .From("[cmsContent]") .Where("([cmsContent].[nodeId] = @0)", 1045) .Where("([cmsContent].[contentType] = @0)", 1050); - var sql = new Sql(); - sql.Select("*") - .From(SqlSyntax) - .Where(SqlSyntax, x => x.NodeId == 1045) - .Where(SqlSyntax, x => x.ContentTypeId == 1050); + var sql = Sql(); + sql.SelectAll() + .From() + .Where(x => x.NodeId == 1045) + .Where(x => x.ContentTypeId == 1050); Assert.That(sql.SQL, Is.EqualTo(expected.SQL)); diff --git a/src/Umbraco.Tests/Persistence/Querying/QueryBuilderTests.cs b/src/Umbraco.Tests/Persistence/Querying/QueryBuilderTests.cs index 62582ace64..9844e6fb26 100644 --- a/src/Umbraco.Tests/Persistence/Querying/QueryBuilderTests.cs +++ b/src/Umbraco.Tests/Persistence/Querying/QueryBuilderTests.cs @@ -1,4 +1,5 @@ using System; +using NPoco; using NUnit.Framework; using Umbraco.Core; using Umbraco.Core.Models; @@ -18,11 +19,11 @@ namespace Umbraco.Tests.Persistence.Querying public void Can_Build_StartsWith_Query_For_IContent() { // Arrange - var sql = new Sql(); - sql.Select("*"); + var sql = Sql(); + sql.SelectAll(); sql.From("umbracoNode"); - var query = new Query(SqlSyntax, MappingResolver).Where(x => x.Path.StartsWith("-1")); + var query = new Query(SqlContext.SqlSyntax, MappingResolver).Where(x => x.Path.StartsWith("-1")); // Act var translator = new SqlTranslator(sql, query); @@ -45,11 +46,11 @@ namespace Umbraco.Tests.Persistence.Querying public void Can_Build_ParentId_Query_For_IContent() { // Arrange - var sql = new Sql(); - sql.Select("*"); + var sql = Sql(); + sql.SelectAll(); sql.From("umbracoNode"); - var query = new Query(SqlSyntax, MappingResolver).Where(x => x.ParentId == -1); + var query = new Query(SqlContext.SqlSyntax, MappingResolver).Where(x => x.ParentId == -1); // Act var translator = new SqlTranslator(sql, query); @@ -72,11 +73,11 @@ namespace Umbraco.Tests.Persistence.Querying public void Can_Build_ContentTypeAlias_Query_For_IContentType() { // Arrange - var sql = new Sql(); - sql.Select("*"); + var sql = Sql(); + sql.SelectAll(); sql.From("umbracoNode"); - var query = new Query(SqlSyntax, MappingResolver).Where(x => x.Alias == "umbTextpage"); + var query = new Query(SqlContext.SqlSyntax, MappingResolver).Where(x => x.Alias == "umbTextpage"); // Act var translator = new SqlTranslator(sql, query); @@ -102,18 +103,18 @@ namespace Umbraco.Tests.Persistence.Querying var id = 1046; var nodeObjectTypeId = new Guid(Constants.ObjectTypes.Document); - var sql = new Sql(); - sql.Select("*") - .From(SqlSyntax) - .InnerJoin(SqlSyntax) - .On(SqlSyntax, left => left.VersionId, right => right.VersionId) - .InnerJoin(SqlSyntax) - .On(SqlSyntax, left => left.NodeId, right => right.NodeId) - .InnerJoin(SqlSyntax) - .On(SqlSyntax, left => left.NodeId, right => right.NodeId) - .Where(SqlSyntax, x => x.NodeObjectType == nodeObjectTypeId); + var sql = Sql(); + sql.SelectAll() + .From() + .InnerJoin() + .On(left => left.VersionId, right => right.VersionId) + .InnerJoin() + .On(left => left.NodeId, right => right.NodeId) + .InnerJoin() + .On(left => left.NodeId, right => right.NodeId) + .Where(x => x.NodeObjectType == nodeObjectTypeId); - var query = new Query(SqlSyntax, MappingResolver).Where(x => x.Path.StartsWith(path) && x.Id != id && x.Published == true && x.Trashed == false); + var query = new Query(SqlContext.SqlSyntax, MappingResolver).Where(x => x.Path.StartsWith(path) && x.Id != id && x.Published == true && x.Trashed == false); // Act var translator = new SqlTranslator(sql, query); diff --git a/src/Umbraco.Tests/Persistence/Repositories/AuditRepositoryTest.cs b/src/Umbraco.Tests/Persistence/Repositories/AuditRepositoryTest.cs index 29c2960cf8..6be6bd5f6e 100644 --- a/src/Umbraco.Tests/Persistence/Repositories/AuditRepositoryTest.cs +++ b/src/Umbraco.Tests/Persistence/Repositories/AuditRepositoryTest.cs @@ -15,7 +15,7 @@ namespace Umbraco.Tests.Persistence.Repositories [Test] public void Can_Add_Audit_Entry() { - var provider = new PetaPocoUnitOfWorkProvider(Logger); + var provider = new NPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); using (var repo = new AuditRepository(unitOfWork, CacheHelper, Logger, SqlSyntax, MappingResolver)) { diff --git a/src/Umbraco.Tests/Persistence/Repositories/ContentRepositoryTest.cs b/src/Umbraco.Tests/Persistence/Repositories/ContentRepositoryTest.cs index c78abce427..f9244c3987 100644 --- a/src/Umbraco.Tests/Persistence/Repositories/ContentRepositoryTest.cs +++ b/src/Umbraco.Tests/Persistence/Repositories/ContentRepositoryTest.cs @@ -1,6 +1,7 @@ using System; using System.Collections.Generic; using System.Linq; +using System.Text.RegularExpressions; using System.Xml.Linq; using Moq; using NUnit.Framework; @@ -19,6 +20,7 @@ using Umbraco.Core.Persistence.UnitOfWork; using Umbraco.Tests.TestHelpers; using Umbraco.Tests.TestHelpers.Entities; using Umbraco.Core.Persistence.DatabaseModelDefinitions; +using Umbraco.Core.Persistence.SqlSyntax; namespace Umbraco.Tests.Persistence.Repositories { @@ -48,17 +50,17 @@ namespace Umbraco.Tests.Persistence.Repositories private ContentRepository CreateRepository(IDatabaseUnitOfWork unitOfWork, out ContentTypeRepository contentTypeRepository, out TemplateRepository templateRepository) { - templateRepository = new TemplateRepository(unitOfWork, CacheHelper, Logger, SqlSyntax, Mock.Of(), Mock.Of(), Mock.Of(), Mock.Of()); - var tagRepository = new TagRepository(unitOfWork, CacheHelper, Logger, SqlSyntax, Mock.Of()); - contentTypeRepository = new ContentTypeRepository(unitOfWork, CacheHelper, Logger, SqlSyntax, templateRepository, Mock.Of()); - var repository = new ContentRepository(unitOfWork, CacheHelper, Logger, SqlSyntax, contentTypeRepository, templateRepository, tagRepository, Mock.Of(), Mock.Of()); + templateRepository = new TemplateRepository(unitOfWork, CacheHelper, Logger, SqlSyntax, Mock.Of(), Mock.Of(), Mock.Of(), MappingResolver); + var tagRepository = new TagRepository(unitOfWork, CacheHelper, Logger, SqlSyntax, MappingResolver); + contentTypeRepository = new ContentTypeRepository(unitOfWork, CacheHelper, Logger, SqlSyntax, templateRepository, MappingResolver); + var repository = new ContentRepository(unitOfWork, CacheHelper, Logger, SqlSyntax, contentTypeRepository, templateRepository, tagRepository, Mock.Of(), MappingResolver); return repository; } [Test] public void Rebuild_Xml_Structures_With_Non_Latest_Version() { - var provider = new PetaPocoUnitOfWorkProvider(Logger); + var provider = new NPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); ContentTypeRepository contentTypeRepository; using (var repository = CreateRepository(unitOfWork, out contentTypeRepository)) @@ -70,7 +72,7 @@ namespace Umbraco.Tests.Persistence.Repositories //create 100 non published for (var i = 0; i < 100; i++) - { + { var c1 = MockedContent.CreateSimpleContent(contentType1); repository.AddOrUpdate(c1); allCreated.Add(c1); @@ -110,7 +112,7 @@ namespace Umbraco.Tests.Persistence.Repositories [Test] public void Rebuild_All_Xml_Structures() { - var provider = new PetaPocoUnitOfWorkProvider(Logger); + var provider = new NPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); ContentTypeRepository contentTypeRepository; using (var repository = CreateRepository(unitOfWork, out contentTypeRepository)) @@ -157,7 +159,7 @@ namespace Umbraco.Tests.Persistence.Repositories [Test] public void Rebuild_All_Xml_Structures_For_Content_Type() { - var provider = new PetaPocoUnitOfWorkProvider(Logger); + var provider = new NPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); ContentTypeRepository contentTypeRepository; using (var repository = CreateRepository(unitOfWork, out contentTypeRepository)) @@ -174,7 +176,7 @@ namespace Umbraco.Tests.Persistence.Repositories for (var i = 0; i < 30; i++) { //These will be non-published so shouldn't show up - var c1 = MockedContent.CreateSimpleContent(contentType1); + var c1 = MockedContent.CreateSimpleContent(contentType1); repository.AddOrUpdate(c1); allCreated.Add(c1); } @@ -223,7 +225,7 @@ namespace Umbraco.Tests.Persistence.Repositories public void Ensures_Permissions_Are_Set_If_Parent_Entity_Permissions_Exist() { // Arrange - var provider = new PetaPocoUnitOfWorkProvider(Logger); + var provider = new NPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); ContentTypeRepository contentTypeRepository; @@ -257,7 +259,7 @@ namespace Umbraco.Tests.Persistence.Repositories public void Can_Perform_Add_On_ContentRepository() { // Arrange - var provider = new PetaPocoUnitOfWorkProvider(Logger); + var provider = new NPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); ContentTypeRepository contentTypeRepository; using (var repository = CreateRepository(unitOfWork, out contentTypeRepository)) @@ -273,7 +275,7 @@ namespace Umbraco.Tests.Persistence.Repositories // Assert Assert.That(contentType.HasIdentity, Is.True); Assert.That(textpage.HasIdentity, Is.True); - + } } @@ -281,7 +283,7 @@ namespace Umbraco.Tests.Persistence.Repositories public void Can_Perform_Add_With_Default_Template() { // Arrange - var provider = new PetaPocoUnitOfWorkProvider(Logger); + var provider = new NPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); ContentTypeRepository contentTypeRepository; TemplateRepository templateRepository; @@ -297,7 +299,7 @@ namespace Umbraco.Tests.Persistence.Repositories Content textpage = MockedContent.CreateSimpleContent(contentType); // Act - + contentTypeRepository.AddOrUpdate(contentType); repository.AddOrUpdate(textpage); unitOfWork.Commit(); @@ -313,7 +315,7 @@ namespace Umbraco.Tests.Persistence.Repositories public void Can_Save_Content_With_AtSign_In_Name_On_ContentRepository() { // Arrange - var provider = new PetaPocoUnitOfWorkProvider(Logger); + var provider = new NPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); ContentTypeRepository contentTypeRepository; using (var repository = CreateRepository(unitOfWork, out contentTypeRepository)) @@ -347,7 +349,7 @@ namespace Umbraco.Tests.Persistence.Repositories public void Can_Perform_Multiple_Adds_On_ContentRepository() { // Arrange - var provider = new PetaPocoUnitOfWorkProvider(Logger); + var provider = new NPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); ContentTypeRepository contentTypeRepository; using (var repository = CreateRepository(unitOfWork, out contentTypeRepository)) @@ -378,7 +380,7 @@ namespace Umbraco.Tests.Persistence.Repositories public void Can_Verify_Fresh_Entity_Is_Not_Dirty() { // Arrange - var provider = new PetaPocoUnitOfWorkProvider(Logger); + var provider = new NPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); ContentTypeRepository contentTypeRepository; using (var repository = CreateRepository(unitOfWork, out contentTypeRepository)) @@ -396,7 +398,7 @@ namespace Umbraco.Tests.Persistence.Repositories public void Can_Perform_Update_On_ContentRepository() { // Arrange - var provider = new PetaPocoUnitOfWorkProvider(Logger); + var provider = new NPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); ContentTypeRepository contentTypeRepository; using (var repository = CreateRepository(unitOfWork, out contentTypeRepository)) @@ -419,7 +421,7 @@ namespace Umbraco.Tests.Persistence.Repositories public void Can_Update_With_Null_Template() { // Arrange - var provider = new PetaPocoUnitOfWorkProvider(Logger); + var provider = new NPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); ContentTypeRepository contentTypeRepository; using (var repository = CreateRepository(unitOfWork, out contentTypeRepository)) @@ -441,7 +443,7 @@ namespace Umbraco.Tests.Persistence.Repositories public void Can_Perform_Delete_On_ContentRepository() { // Arrange - var provider = new PetaPocoUnitOfWorkProvider(Logger); + var provider = new NPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); ContentTypeRepository contentTypeRepository; using (var repository = CreateRepository(unitOfWork, out contentTypeRepository)) @@ -470,7 +472,7 @@ namespace Umbraco.Tests.Persistence.Repositories public void Can_Perform_Get_On_ContentRepository() { // Arrange - var provider = new PetaPocoUnitOfWorkProvider(Logger); + var provider = new NPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); ContentTypeRepository contentTypeRepository; using (var repository = CreateRepository(unitOfWork, out contentTypeRepository)) @@ -496,7 +498,7 @@ namespace Umbraco.Tests.Persistence.Repositories public void Can_Perform_GetByQuery_On_ContentRepository() { // Arrange - var provider = new PetaPocoUnitOfWorkProvider(Logger); + var provider = new NPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); ContentTypeRepository contentTypeRepository; using (var repository = CreateRepository(unitOfWork, out contentTypeRepository)) @@ -514,11 +516,11 @@ namespace Umbraco.Tests.Persistence.Repositories public void Can_Perform_Get_All_With_Many_Version() { // Arrange - var provider = new PetaPocoUnitOfWorkProvider(Logger); + var provider = new NPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); ContentTypeRepository contentTypeRepository; using (var repository = CreateRepository(unitOfWork, out contentTypeRepository)) - { + { var result = repository.GetAll().ToArray(); foreach (var content in result) { @@ -541,11 +543,60 @@ namespace Umbraco.Tests.Persistence.Repositories } } + [Test] + public void RegexAliasTest() + { + var regex = VersionableRepositoryBaseAliasRegex.For(new SqlServerSyntaxProvider()); + Assert.AreEqual(@"(\[\w+]\.\[\w+])\s+AS\s+(\[\w+])", regex.ToString()); + const string sql = "SELECT [table].[column1] AS [alias1], [table].[column2] AS [alias2] FROM [table];"; + var matches = regex.Matches(sql); + Assert.AreEqual(2, matches.Count); + Assert.AreEqual("[table].[column1]", matches[0].Groups[1].Value); + Assert.AreEqual("[alias1]", matches[0].Groups[2].Value); + Assert.AreEqual("[table].[column2]", matches[1].Groups[1].Value); + Assert.AreEqual("[alias2]", matches[1].Groups[2].Value); + } + + [Test] + public void Can_Perform_GetPagedResultsByQuery_Sorting_On_Custom_Property() + { + // Arrange + var provider = new NPocoUnitOfWorkProvider(Logger); + var unitOfWork = provider.GetUnitOfWork(); + ContentTypeRepository contentTypeRepository; + using (var repository = CreateRepository(unitOfWork, out contentTypeRepository)) + { + // Act + var query = repository.Query.Where(x => x.Name.Contains("Text")); + long totalRecords; + + try + { + DatabaseContext.Database.EnableSqlTrace = true; + DatabaseContext.Database.EnableSqlCount(); + + var result = repository.GetPagedResultsByQuery(query, 0, 2, out totalRecords, "title", Direction.Ascending, false); + + Assert.AreEqual(3, totalRecords); + Assert.AreEqual(2, result.Count()); + + result = repository.GetPagedResultsByQuery(query, 1, 2, out totalRecords, "title", Direction.Ascending, false); + + Assert.AreEqual(1, result.Count()); + } + finally + { + DatabaseContext.Database.EnableSqlTrace = false; + DatabaseContext.Database.DisableSqlCount(); + } + } + } + [Test] public void Can_Perform_GetPagedResultsByQuery_ForFirstPage_On_ContentRepository() { // Arrange - var provider = new PetaPocoUnitOfWorkProvider(Logger); + var provider = new NPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); ContentTypeRepository contentTypeRepository; using (var repository = CreateRepository(unitOfWork, out contentTypeRepository)) @@ -553,12 +604,23 @@ namespace Umbraco.Tests.Persistence.Repositories // Act var query = repository.Query.Where(x => x.Level == 2); long totalRecords; - var result = repository.GetPagedResultsByQuery(query, 0, 1, out totalRecords, "Name", Direction.Ascending); - // Assert - Assert.That(totalRecords, Is.GreaterThanOrEqualTo(2)); - Assert.That(result.Count(), Is.EqualTo(1)); - Assert.That(result.First().Name, Is.EqualTo("Text Page 1")); + try + { + DatabaseContext.Database.EnableSqlTrace = true; + DatabaseContext.Database.EnableSqlCount(); + var result = repository.GetPagedResultsByQuery(query, 0, 1, out totalRecords, "Name", Direction.Ascending, true); + + // Assert + Assert.That(totalRecords, Is.GreaterThanOrEqualTo(2)); + Assert.That(result.Count(), Is.EqualTo(1)); + Assert.That(result.First().Name, Is.EqualTo("Text Page 1")); + } + finally + { + DatabaseContext.Database.EnableSqlTrace = false; + DatabaseContext.Database.DisableSqlCount(); + } } } @@ -566,7 +628,7 @@ namespace Umbraco.Tests.Persistence.Repositories public void Can_Perform_GetPagedResultsByQuery_ForSecondPage_On_ContentRepository() { // Arrange - var provider = new PetaPocoUnitOfWorkProvider(Logger); + var provider = new NPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); ContentTypeRepository contentTypeRepository; using (var repository = CreateRepository(unitOfWork, out contentTypeRepository)) @@ -574,7 +636,7 @@ namespace Umbraco.Tests.Persistence.Repositories // Act var query = repository.Query.Where(x => x.Level == 2); long totalRecords; - var result = repository.GetPagedResultsByQuery(query, 1, 1, out totalRecords, "Name", Direction.Ascending); + var result = repository.GetPagedResultsByQuery(query, 1, 1, out totalRecords, "Name", Direction.Ascending, true); // Assert Assert.That(totalRecords, Is.GreaterThanOrEqualTo(2)); @@ -587,7 +649,7 @@ namespace Umbraco.Tests.Persistence.Repositories public void Can_Perform_GetPagedResultsByQuery_WithSinglePage_On_ContentRepository() { // Arrange - var provider = new PetaPocoUnitOfWorkProvider(Logger); + var provider = new NPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); ContentTypeRepository contentTypeRepository; using (var repository = CreateRepository(unitOfWork, out contentTypeRepository)) @@ -595,7 +657,7 @@ namespace Umbraco.Tests.Persistence.Repositories // Act var query = repository.Query.Where(x => x.Level == 2); long totalRecords; - var result = repository.GetPagedResultsByQuery(query, 0, 2, out totalRecords, "Name", Direction.Ascending); + var result = repository.GetPagedResultsByQuery(query, 0, 2, out totalRecords, "Name", Direction.Ascending, true); // Assert Assert.That(totalRecords, Is.GreaterThanOrEqualTo(2)); @@ -608,7 +670,7 @@ namespace Umbraco.Tests.Persistence.Repositories public void Can_Perform_GetPagedResultsByQuery_WithDescendingOrder_On_ContentRepository() { // Arrange - var provider = new PetaPocoUnitOfWorkProvider(Logger); + var provider = new NPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); ContentTypeRepository contentTypeRepository; using (var repository = CreateRepository(unitOfWork, out contentTypeRepository)) @@ -616,7 +678,7 @@ namespace Umbraco.Tests.Persistence.Repositories // Act var query = repository.Query.Where(x => x.Level == 2); long totalRecords; - var result = repository.GetPagedResultsByQuery(query, 0, 1, out totalRecords, "Name", Direction.Descending); + var result = repository.GetPagedResultsByQuery(query, 0, 1, out totalRecords, "Name", Direction.Descending, true); // Assert Assert.That(totalRecords, Is.GreaterThanOrEqualTo(2)); @@ -629,7 +691,7 @@ namespace Umbraco.Tests.Persistence.Repositories public void Can_Perform_GetPagedResultsByQuery_WithFilterMatchingSome_On_ContentRepository() { // Arrange - var provider = new PetaPocoUnitOfWorkProvider(Logger); + var provider = new NPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); ContentTypeRepository contentTypeRepository; using (var repository = CreateRepository(unitOfWork, out contentTypeRepository)) @@ -637,7 +699,7 @@ namespace Umbraco.Tests.Persistence.Repositories // Act var query = repository.Query.Where(x => x.Level == 2); long totalRecords; - var result = repository.GetPagedResultsByQuery(query, 0, 1, out totalRecords, "Name", Direction.Ascending, "Page 2"); + var result = repository.GetPagedResultsByQuery(query, 0, 1, out totalRecords, "Name", Direction.Ascending, true, "Page 2"); // Assert Assert.That(totalRecords, Is.EqualTo(1)); @@ -650,7 +712,7 @@ namespace Umbraco.Tests.Persistence.Repositories public void Can_Perform_GetPagedResultsByQuery_WithFilterMatchingAll_On_ContentRepository() { // Arrange - var provider = new PetaPocoUnitOfWorkProvider(Logger); + var provider = new NPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); ContentTypeRepository contentTypeRepository; using (var repository = CreateRepository(unitOfWork, out contentTypeRepository)) @@ -658,7 +720,7 @@ namespace Umbraco.Tests.Persistence.Repositories // Act var query = repository.Query.Where(x => x.Level == 2); long totalRecords; - var result = repository.GetPagedResultsByQuery(query, 0, 1, out totalRecords, "Name", Direction.Ascending, "Page"); + var result = repository.GetPagedResultsByQuery(query, 0, 1, out totalRecords, "Name", Direction.Ascending, true, "Page"); // Assert Assert.That(totalRecords, Is.EqualTo(2)); @@ -671,7 +733,7 @@ namespace Umbraco.Tests.Persistence.Repositories public void Can_Perform_GetAll_By_Param_Ids_On_ContentRepository() { // Arrange - var provider = new PetaPocoUnitOfWorkProvider(Logger); + var provider = new NPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); ContentTypeRepository contentTypeRepository; using (var repository = CreateRepository(unitOfWork, out contentTypeRepository)) @@ -690,7 +752,7 @@ namespace Umbraco.Tests.Persistence.Repositories public void Can_Perform_GetAll_On_ContentRepository() { // Arrange - var provider = new PetaPocoUnitOfWorkProvider(Logger); + var provider = new NPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); ContentTypeRepository contentTypeRepository; using (var repository = CreateRepository(unitOfWork, out contentTypeRepository)) @@ -711,7 +773,7 @@ namespace Umbraco.Tests.Persistence.Repositories public void Can_Perform_Exists_On_ContentRepository() { // Arrange - var provider = new PetaPocoUnitOfWorkProvider(Logger); + var provider = new NPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); ContentTypeRepository contentTypeRepository; using (var repository = CreateRepository(unitOfWork, out contentTypeRepository)) @@ -730,7 +792,7 @@ namespace Umbraco.Tests.Persistence.Repositories public void Can_Perform_Count_On_ContentRepository() { // Arrange - var provider = new PetaPocoUnitOfWorkProvider(Logger); + var provider = new NPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); ContentTypeRepository contentTypeRepository; using (var repository = CreateRepository(unitOfWork, out contentTypeRepository)) @@ -749,7 +811,7 @@ namespace Umbraco.Tests.Persistence.Repositories public void Can_Verify_Keys_Set() { // Arrange - var provider = new PetaPocoUnitOfWorkProvider(Logger); + var provider = new NPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); ContentTypeRepository contentTypeRepository; using (var repository = CreateRepository(unitOfWork, out contentTypeRepository)) @@ -770,7 +832,7 @@ namespace Umbraco.Tests.Persistence.Repositories public void Can_Get_Content_By_Guid_Key() { // Arrange - var provider = new PetaPocoUnitOfWorkProvider(Logger); + var provider = new NPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); ContentTypeRepository contentTypeRepository; using (var repository = CreateRepository(unitOfWork, out contentTypeRepository)) diff --git a/src/Umbraco.Tests/Persistence/Repositories/ContentTypeRepositoryTest.cs b/src/Umbraco.Tests/Persistence/Repositories/ContentTypeRepositoryTest.cs index 2c1404683f..1d27925fc5 100644 --- a/src/Umbraco.Tests/Persistence/Repositories/ContentTypeRepositoryTest.cs +++ b/src/Umbraco.Tests/Persistence/Repositories/ContentTypeRepositoryTest.cs @@ -75,7 +75,7 @@ namespace Umbraco.Tests.Persistence.Repositories public void Maps_Templates_Correctly() { // Arrange - var provider = new PetaPocoUnitOfWorkProvider(Logger); + var provider = new NPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); using (var templateRepo = new TemplateRepository(unitOfWork, CacheHelper.CreateDisabledCacheHelper(), Logger, SqlSyntax, Mock.Of(), Mock.Of(), Mock.Of(), MappingResolver)) using (var repository = CreateRepository(unitOfWork)) @@ -110,7 +110,7 @@ namespace Umbraco.Tests.Persistence.Repositories [Test] public void Can_Move() { - var provider = new PetaPocoUnitOfWorkProvider(Logger); + var provider = new NPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); using (var containerRepository = CreateContainerRepository(unitOfWork, Constants.ObjectTypes.DocumentTypeContainerGuid)) using (var repository = CreateRepository(unitOfWork)) @@ -156,7 +156,7 @@ namespace Umbraco.Tests.Persistence.Repositories [Test] public void Can_Create_Container() { - var provider = new PetaPocoUnitOfWorkProvider(Logger); + var provider = new NPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); EntityContainer container; using (var containerRepository = CreateContainerRepository(unitOfWork, Constants.ObjectTypes.DocumentTypeContainerGuid)) @@ -176,7 +176,7 @@ namespace Umbraco.Tests.Persistence.Repositories [Test] public void Can_Delete_Container() { - var provider = new PetaPocoUnitOfWorkProvider(Logger); + var provider = new NPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); EntityContainer container; using (var containerRepository = CreateContainerRepository(unitOfWork, Constants.ObjectTypes.DocumentTypeContainerGuid)) @@ -201,7 +201,7 @@ namespace Umbraco.Tests.Persistence.Repositories [Test] public void Can_Create_Container_Containing_Media_Types() { - var provider = new PetaPocoUnitOfWorkProvider(Logger); + var provider = new NPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); using (var containerRepository = CreateContainerRepository(unitOfWork, Constants.ObjectTypes.MediaTypeContainerGuid)) using (var repository = CreateRepository(unitOfWork)) @@ -222,7 +222,7 @@ namespace Umbraco.Tests.Persistence.Repositories [Test] public void Can_Delete_Container_Containing_Media_Types() { - var provider = new PetaPocoUnitOfWorkProvider(Logger); + var provider = new NPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); EntityContainer container; IMediaType contentType; @@ -258,7 +258,7 @@ namespace Umbraco.Tests.Persistence.Repositories public void Can_Perform_Add_On_ContentTypeRepository() { // Arrange - var provider = new PetaPocoUnitOfWorkProvider(Logger); + var provider = new NPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); using (var repository = CreateRepository(unitOfWork)) { @@ -289,7 +289,7 @@ namespace Umbraco.Tests.Persistence.Repositories public void Can_Perform_Add_On_ContentTypeRepository_After_Model_Mapping() { // Arrange - var provider = new PetaPocoUnitOfWorkProvider(Logger); + var provider = new NPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); using (var repository = CreateRepository(unitOfWork)) { @@ -338,7 +338,7 @@ namespace Umbraco.Tests.Persistence.Repositories public void Can_Perform_Update_On_ContentTypeRepository() { // Arrange - var provider = new PetaPocoUnitOfWorkProvider(Logger); + var provider = new NPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); using (var repository = CreateRepository(unitOfWork)) { @@ -414,7 +414,7 @@ namespace Umbraco.Tests.Persistence.Repositories public void Can_Perform_Update_On_ContentTypeRepository_After_Model_Mapping() { // Arrange - var provider = new PetaPocoUnitOfWorkProvider(Logger); + var provider = new NPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); using (var repository = CreateRepository(unitOfWork)) { @@ -477,7 +477,7 @@ namespace Umbraco.Tests.Persistence.Repositories public void Can_Perform_Delete_On_ContentTypeRepository() { // Arrange - var provider = new PetaPocoUnitOfWorkProvider(Logger); + var provider = new NPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); using (var repository = CreateRepository(unitOfWork)) { @@ -501,7 +501,7 @@ namespace Umbraco.Tests.Persistence.Repositories public void Can_Perform_Delete_With_Heirarchy_On_ContentTypeRepository() { // Arrange - var provider = new PetaPocoUnitOfWorkProvider(Logger); + var provider = new NPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); using (var repository = CreateRepository(unitOfWork)) { @@ -531,7 +531,7 @@ namespace Umbraco.Tests.Persistence.Repositories public void Can_Perform_Query_On_ContentTypeRepository_Sort_By_Name() { // Arrange - var provider = new PetaPocoUnitOfWorkProvider(Logger); + var provider = new NPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); using (var repository = CreateRepository(unitOfWork)) { @@ -560,7 +560,7 @@ namespace Umbraco.Tests.Persistence.Repositories public void Can_Perform_Get_On_ContentTypeRepository() { // Arrange - var provider = new PetaPocoUnitOfWorkProvider(Logger); + var provider = new NPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); using (var repository = CreateRepository(unitOfWork)) { @@ -578,7 +578,7 @@ namespace Umbraco.Tests.Persistence.Repositories public void Can_Perform_Get_By_Guid_On_ContentTypeRepository() { // Arrange - var provider = new PetaPocoUnitOfWorkProvider(Logger); + var provider = new NPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); using (var repository = CreateRepository(unitOfWork)) { @@ -600,7 +600,7 @@ namespace Umbraco.Tests.Persistence.Repositories public void Can_Perform_Get_By_Missing_Guid_On_ContentTypeRepository() { // Arrange - var provider = new PetaPocoUnitOfWorkProvider(Logger); + var provider = new NPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); using (var repository = CreateRepository(unitOfWork)) { @@ -616,7 +616,7 @@ namespace Umbraco.Tests.Persistence.Repositories public void Can_Perform_GetAll_On_ContentTypeRepository() { // Arrange - var provider = new PetaPocoUnitOfWorkProvider(Logger); + var provider = new NPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); using (var repository = CreateRepository(unitOfWork)) { @@ -638,7 +638,7 @@ namespace Umbraco.Tests.Persistence.Repositories public void Can_Perform_GetAll_By_Guid_On_ContentTypeRepository() { // Arrange - var provider = new PetaPocoUnitOfWorkProvider(Logger); + var provider = new NPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); using (var repository = CreateRepository(unitOfWork)) { @@ -661,7 +661,7 @@ namespace Umbraco.Tests.Persistence.Repositories public void Can_Perform_Exists_On_ContentTypeRepository() { // Arrange - var provider = new PetaPocoUnitOfWorkProvider(Logger); + var provider = new NPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); using (var repository = CreateRepository(unitOfWork)) { @@ -678,7 +678,7 @@ namespace Umbraco.Tests.Persistence.Repositories public void Can_Update_ContentType_With_PropertyType_Removed() { // Arrange - var provider = new PetaPocoUnitOfWorkProvider(Logger); + var provider = new NPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); using (var repository = CreateRepository(unitOfWork)) { @@ -702,7 +702,7 @@ namespace Umbraco.Tests.Persistence.Repositories public void Can_Verify_PropertyTypes_On_SimpleTextpage() { // Arrange - var provider = new PetaPocoUnitOfWorkProvider(Logger); + var provider = new NPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); using (var repository = CreateRepository(unitOfWork)) { @@ -720,7 +720,7 @@ namespace Umbraco.Tests.Persistence.Repositories public void Can_Verify_PropertyTypes_On_Textpage() { // Arrange - var provider = new PetaPocoUnitOfWorkProvider(Logger); + var provider = new NPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); using (var repository = CreateRepository(unitOfWork)) { @@ -738,7 +738,7 @@ namespace Umbraco.Tests.Persistence.Repositories public void Can_Verify_PropertyType_With_No_Group() { // Arrange - var provider = new PetaPocoUnitOfWorkProvider(Logger); + var provider = new NPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); using (var repository = CreateRepository(unitOfWork)) { @@ -772,7 +772,7 @@ namespace Umbraco.Tests.Persistence.Repositories public void Can_Verify_AllowedChildContentTypes_On_ContentType() { // Arrange - var provider = new PetaPocoUnitOfWorkProvider(Logger); + var provider = new NPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); using (var repository = CreateRepository(unitOfWork)) { @@ -806,7 +806,7 @@ namespace Umbraco.Tests.Persistence.Repositories public void Can_Verify_Removal_Of_Used_PropertyType_From_ContentType() { // Arrange - var provider = new PetaPocoUnitOfWorkProvider(Logger); + var provider = new NPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); ContentTypeRepository repository; using (var contentRepository = CreateRepository(unitOfWork, out repository)) @@ -833,7 +833,7 @@ namespace Umbraco.Tests.Persistence.Repositories public void Can_Verify_Addition_Of_PropertyType_After_ContentType_Is_Used() { // Arrange - var provider = new PetaPocoUnitOfWorkProvider(Logger); + var provider = new NPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); ContentTypeRepository repository; using (var contentRepository = CreateRepository(unitOfWork, out repository)) @@ -861,7 +861,7 @@ namespace Umbraco.Tests.Persistence.Repositories public void Can_Verify_Usage_Of_New_PropertyType_On_Content() { // Arrange - var provider = new PetaPocoUnitOfWorkProvider(Logger); + var provider = new NPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); ContentTypeRepository repository; using (var contentRepository = CreateRepository(unitOfWork, out repository)) @@ -897,7 +897,7 @@ namespace Umbraco.Tests.Persistence.Repositories () { // Arrange - var provider = new PetaPocoUnitOfWorkProvider(Logger); + var provider = new NPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); ContentTypeRepository repository; using (var contentRepository = CreateRepository(unitOfWork, out repository)) diff --git a/src/Umbraco.Tests/Persistence/Repositories/DataTypeDefinitionRepositoryTest.cs b/src/Umbraco.Tests/Persistence/Repositories/DataTypeDefinitionRepositoryTest.cs index bc5314abb1..075093c92e 100644 --- a/src/Umbraco.Tests/Persistence/Repositories/DataTypeDefinitionRepositoryTest.cs +++ b/src/Umbraco.Tests/Persistence/Repositories/DataTypeDefinitionRepositoryTest.cs @@ -1,12 +1,14 @@ using System; using System.Data; using System.Linq; +using System.Reflection; using System.Text.RegularExpressions; using Moq; using NUnit.Framework; using Umbraco.Core; using Umbraco.Core.Cache; using Umbraco.Core.Configuration.UmbracoSettings; +using Umbraco.Core.DependencyInjection; using Umbraco.Core.IO; using Umbraco.Core.Logging; using Umbraco.Core.Models; @@ -32,6 +34,23 @@ namespace Umbraco.Tests.Persistence.Repositories base.Initialize(); } + protected override CacheHelper CreateCacheHelper() + { + // hackish, but it works + var testName = TestContext.CurrentContext.Test.Name; + if (testName == "Can_Get_Pre_Value_As_String_With_Cache" + || testName == "Can_Get_Pre_Value_Collection_With_Cache") + { + return new CacheHelper( + new ObjectCacheRuntimeCacheProvider(), + new StaticCacheProvider(), + new StaticCacheProvider(), + new IsolatedRuntimeCache(type => new ObjectCacheRuntimeCacheProvider())); // default would be NullCacheProvider + } + + return base.CreateCacheHelper(); + } + private IDataTypeDefinitionRepository CreateRepository(IDatabaseUnitOfWork unitOfWork) { return Container.GetInstance(unitOfWork); @@ -39,7 +58,7 @@ namespace Umbraco.Tests.Persistence.Repositories private EntityContainerRepository CreateContainerRepository(IDatabaseUnitOfWork unitOfWork) { - return new EntityContainerRepository(unitOfWork, CacheHelper.CreateDisabledCacheHelper(), Mock.Of(), SqlSyntax, Mock.Of(), Constants.ObjectTypes.DataTypeContainerGuid); + return new EntityContainerRepository(unitOfWork, CacheHelper.CreateDisabledCacheHelper(), Logger, SqlSyntax, MappingResolver, Constants.ObjectTypes.DataTypeContainerGuid); } [TestCase("UmbracoPreVal87-21,3,48", 3, true)] @@ -62,7 +81,7 @@ namespace Umbraco.Tests.Persistence.Repositories [Test] public void Can_Move() { - var provider = new PetaPocoUnitOfWorkProvider(Logger); + var provider = new NPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); using (var containerRepository = CreateContainerRepository(unitOfWork)) using (var repository = CreateRepository(unitOfWork)) @@ -82,7 +101,7 @@ namespace Umbraco.Tests.Persistence.Repositories repository.AddOrUpdate(dataType); unitOfWork.Commit(); - //create a + //create a var dataType2 = (IDataTypeDefinition)new DataTypeDefinition(dataType.Id, Constants.PropertyEditors.RadioButtonListAlias) { Name = "dt2" @@ -109,14 +128,14 @@ namespace Umbraco.Tests.Persistence.Repositories [Test] public void Can_Create_Container() { - var provider = new PetaPocoUnitOfWorkProvider(Logger); + var provider = new NPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); EntityContainer container; using (var containerRepository = CreateContainerRepository(unitOfWork)) { container = new EntityContainer(Constants.ObjectTypes.DataTypeGuid) { Name = "blah" }; containerRepository.AddOrUpdate(container); - unitOfWork.Commit(); + unitOfWork.Commit(); Assert.That(container.Id, Is.GreaterThan(0)); } using (var containerRepository = CreateContainerRepository(unitOfWork)) @@ -129,7 +148,7 @@ namespace Umbraco.Tests.Persistence.Repositories [Test] public void Can_Delete_Container() { - var provider = new PetaPocoUnitOfWorkProvider(Logger); + var provider = new NPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); EntityContainer container; using (var containerRepository = CreateContainerRepository(unitOfWork)) @@ -154,7 +173,7 @@ namespace Umbraco.Tests.Persistence.Repositories [Test] public void Can_Create_Container_Containing_Data_Types() { - var provider = new PetaPocoUnitOfWorkProvider(Logger); + var provider = new NPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); using (var containerRepository = CreateContainerRepository(unitOfWork)) using (var repository = CreateRepository(unitOfWork)) @@ -174,7 +193,7 @@ namespace Umbraco.Tests.Persistence.Repositories [Test] public void Can_Delete_Container_Containing_Data_Types() { - var provider = new PetaPocoUnitOfWorkProvider(Logger); + var provider = new NPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); EntityContainer container; IDataTypeDefinition dataType; @@ -187,7 +206,7 @@ namespace Umbraco.Tests.Persistence.Repositories dataType = new DataTypeDefinition(container.Id, Constants.PropertyEditors.RadioButtonListAlias) { Name = "test" }; repository.AddOrUpdate(dataType); - unitOfWork.Commit(); + unitOfWork.Commit(); } using (var containerRepository = CreateContainerRepository(unitOfWork)) using (var repository = CreateRepository(unitOfWork)) @@ -208,7 +227,7 @@ namespace Umbraco.Tests.Persistence.Repositories [Test] public void Can_Create() { - var provider = new PetaPocoUnitOfWorkProvider(Logger); + var provider = new NPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); int id; using (var repository = CreateRepository(unitOfWork)) @@ -237,7 +256,7 @@ namespace Umbraco.Tests.Persistence.Repositories public void Can_Perform_Get_On_DataTypeDefinitionRepository() { // Arrange - var provider = new PetaPocoUnitOfWorkProvider(Logger); + var provider = new NPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); using (var repository = CreateRepository(unitOfWork)) { @@ -247,16 +266,16 @@ namespace Umbraco.Tests.Persistence.Repositories // Assert Assert.That(dataTypeDefinition, Is.Not.Null); Assert.That(dataTypeDefinition.HasIdentity, Is.True); - Assert.That(dataTypeDefinition.Name, Is.EqualTo("Dropdown")); + Assert.That(dataTypeDefinition.Name, Is.EqualTo("Dropdown")); } - + } [Test] public void Can_Perform_GetAll_On_DataTypeDefinitionRepository() { // Arrange - var provider = new PetaPocoUnitOfWorkProvider(Logger); + var provider = new NPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); using (var repository = CreateRepository(unitOfWork)) { @@ -276,7 +295,7 @@ namespace Umbraco.Tests.Persistence.Repositories public void Can_Perform_GetAll_With_Params_On_DataTypeDefinitionRepository() { // Arrange - var provider = new PetaPocoUnitOfWorkProvider(Logger); + var provider = new NPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); using (var repository = CreateRepository(unitOfWork)) { @@ -296,7 +315,7 @@ namespace Umbraco.Tests.Persistence.Repositories public void Can_Perform_GetByQuery_On_DataTypeDefinitionRepository() { // Arrange - var provider = new PetaPocoUnitOfWorkProvider(Logger); + var provider = new NPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); using (var repository = CreateRepository(unitOfWork)) { @@ -316,7 +335,7 @@ namespace Umbraco.Tests.Persistence.Repositories public void Can_Perform_Count_On_DataTypeDefinitionRepository() { // Arrange - var provider = new PetaPocoUnitOfWorkProvider(Logger); + var provider = new NPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); using (var repository = CreateRepository(unitOfWork)) { @@ -334,7 +353,7 @@ namespace Umbraco.Tests.Persistence.Repositories public void Can_Perform_Add_On_DataTypeDefinitionRepository() { // Arrange - var provider = new PetaPocoUnitOfWorkProvider(Logger); + var provider = new NPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); using (var repository = CreateRepository(unitOfWork)) { @@ -361,7 +380,7 @@ namespace Umbraco.Tests.Persistence.Repositories public void Can_Perform_Update_On_DataTypeDefinitionRepository() { // Arrange - var provider = new PetaPocoUnitOfWorkProvider(Logger); + var provider = new NPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); using (var repository = CreateRepository(unitOfWork)) { @@ -395,7 +414,7 @@ namespace Umbraco.Tests.Persistence.Repositories public void Can_Perform_Delete_On_DataTypeDefinitionRepository() { // Arrange - var provider = new PetaPocoUnitOfWorkProvider(Logger); + var provider = new NPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); using (var repository = CreateRepository(unitOfWork)) { @@ -427,7 +446,7 @@ namespace Umbraco.Tests.Persistence.Repositories public void Can_Perform_Exists_On_DataTypeDefinitionRepository() { // Arrange - var provider = new PetaPocoUnitOfWorkProvider(Logger); + var provider = new NPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); using (var repository = CreateRepository(unitOfWork)) { @@ -445,7 +464,7 @@ namespace Umbraco.Tests.Persistence.Repositories [Test] public void Can_Get_Pre_Value_Collection() { - var provider = new PetaPocoUnitOfWorkProvider(Logger); + var provider = new NPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); int dtid; @@ -470,7 +489,7 @@ namespace Umbraco.Tests.Persistence.Repositories [Test] public void Can_Get_Pre_Value_As_String() { - var provider = new PetaPocoUnitOfWorkProvider(Logger); + var provider = new NPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); int dtid; @@ -495,21 +514,15 @@ namespace Umbraco.Tests.Persistence.Repositories [Test] public void Can_Get_Pre_Value_Collection_With_Cache() { - var provider = new PetaPocoUnitOfWorkProvider(Logger); + var provider = new NPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); - var cache = new CacheHelper( - new ObjectCacheRuntimeCacheProvider(), - new StaticCacheProvider(), - new StaticCacheProvider(), - new IsolatedRuntimeCache(type => new ObjectCacheRuntimeCacheProvider())); - DataTypeDefinition dtd; using (var repository = Container.GetInstance(unitOfWork)) { dtd = new DataTypeDefinition(-1, Constants.PropertyEditors.RadioButtonListAlias) { Name = "test" }; repository.AddOrUpdate(dtd); - unitOfWork.Commit(); + unitOfWork.Commit(); } DatabaseContext.Database.Insert(new DataTypePreValueDto() { DataTypeNodeId = dtd.Id, SortOrder = 0, Value = "test1" }); @@ -521,7 +534,10 @@ namespace Umbraco.Tests.Persistence.Repositories var collection = repository.GetPreValuesCollectionByDataTypeId(dtd.Id); } - var cached = cache.IsolatedRuntimeCache.GetCache().Result + // note: see CreateCacheHelper, this test uses a special cache + var cache = CacheHelper.IsolatedRuntimeCache.GetCache(); + Assert.IsTrue(cache); + var cached = cache.Result .GetCacheItemsByKeySearch(CacheKeys.DataTypePreValuesCacheKey + dtd.Id + "-"); Assert.IsNotNull(cached); @@ -532,15 +548,9 @@ namespace Umbraco.Tests.Persistence.Repositories [Test] public void Can_Get_Pre_Value_As_String_With_Cache() { - var provider = new PetaPocoUnitOfWorkProvider(Logger); + var provider = new NPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); - var cache = new CacheHelper( - new ObjectCacheRuntimeCacheProvider(), - new StaticCacheProvider(), - new StaticCacheProvider(), - new IsolatedRuntimeCache(type => new ObjectCacheRuntimeCacheProvider())); - DataTypeDefinition dtd; using (var repository = Container.GetInstance(unitOfWork)) { @@ -558,7 +568,10 @@ namespace Umbraco.Tests.Persistence.Repositories var val = repository.GetPreValueAsString(Convert.ToInt32(id)); } - var cached = cache.IsolatedRuntimeCache.GetCache().Result + // note: see CreateCacheHelper, this test uses a special cache + var cache = CacheHelper.IsolatedRuntimeCache.GetCache(); + Assert.IsTrue(cache); + var cached = cache.Result .GetCacheItemsByKeySearch(CacheKeys.DataTypePreValuesCacheKey + dtd.Id + "-"); Assert.IsNotNull(cached); diff --git a/src/Umbraco.Tests/Persistence/Repositories/DictionaryRepositoryTest.cs b/src/Umbraco.Tests/Persistence/Repositories/DictionaryRepositoryTest.cs index f0c428473f..9febecaef4 100644 --- a/src/Umbraco.Tests/Persistence/Repositories/DictionaryRepositoryTest.cs +++ b/src/Umbraco.Tests/Persistence/Repositories/DictionaryRepositoryTest.cs @@ -36,7 +36,7 @@ namespace Umbraco.Tests.Persistence.Repositories public void Can_Perform_Get_By_Key_On_DictionaryRepository() { // Arrange - var provider = new PetaPocoUnitOfWorkProvider(Logger); + var provider = new NPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); using (var repository = CreateRepository(unitOfWork)) @@ -69,7 +69,7 @@ namespace Umbraco.Tests.Persistence.Repositories public void Can_Perform_Get_By_UniqueId_On_DictionaryRepository() { // Arrange - var provider = new PetaPocoUnitOfWorkProvider(Logger); + var provider = new NPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); using (var repository = CreateRepository(unitOfWork)) @@ -102,7 +102,7 @@ namespace Umbraco.Tests.Persistence.Repositories public void Can_Perform_Get_On_DictionaryRepository() { // Arrange - var provider = new PetaPocoUnitOfWorkProvider(Logger); + var provider = new NPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); using (var repository = CreateRepository(unitOfWork)) @@ -136,7 +136,7 @@ namespace Umbraco.Tests.Persistence.Repositories public void Can_Perform_Get_On_DictionaryRepository_When_No_Language_Assigned() { // Arrange - var provider = new PetaPocoUnitOfWorkProvider(Logger); + var provider = new NPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); using (var repository = CreateRepository(unitOfWork)) @@ -163,7 +163,7 @@ namespace Umbraco.Tests.Persistence.Repositories public void Can_Perform_GetAll_On_DictionaryRepository() { // Arrange - var provider = new PetaPocoUnitOfWorkProvider(Logger); + var provider = new NPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); using (var repository = CreateRepository(unitOfWork)) { @@ -184,7 +184,7 @@ namespace Umbraco.Tests.Persistence.Repositories public void Can_Perform_GetAll_With_Params_On_DictionaryRepository() { // Arrange - var provider = new PetaPocoUnitOfWorkProvider(Logger); + var provider = new NPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); using (var repository = CreateRepository(unitOfWork)) { @@ -204,7 +204,7 @@ namespace Umbraco.Tests.Persistence.Repositories public void Can_Perform_GetByQuery_On_DictionaryRepository() { // Arrange - var provider = new PetaPocoUnitOfWorkProvider(Logger); + var provider = new NPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); using (var repository = CreateRepository(unitOfWork)) { @@ -224,7 +224,7 @@ namespace Umbraco.Tests.Persistence.Repositories public void Can_Perform_Count_On_DictionaryRepository() { // Arrange - var provider = new PetaPocoUnitOfWorkProvider(Logger); + var provider = new NPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); using (var repository = CreateRepository(unitOfWork)) { @@ -242,7 +242,7 @@ namespace Umbraco.Tests.Persistence.Repositories public void Can_Perform_Add_On_DictionaryRepository() { // Arrange - var provider = new PetaPocoUnitOfWorkProvider(Logger); + var provider = new NPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); using (var languageRepository = Container.GetInstance(unitOfWork)) using (var repository = CreateRepository(unitOfWork)) @@ -273,7 +273,7 @@ namespace Umbraco.Tests.Persistence.Repositories public void Can_Perform_Update_On_DictionaryRepository() { // Arrange - var provider = new PetaPocoUnitOfWorkProvider(Logger); + var provider = new NPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); using (var repository = CreateRepository(unitOfWork)) { @@ -300,7 +300,7 @@ namespace Umbraco.Tests.Persistence.Repositories public void Can_Perform_Update_WithNewTranslation_On_DictionaryRepository() { // Arrange - var provider = new PetaPocoUnitOfWorkProvider(Logger); + var provider = new NPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); var repository = CreateRepository(unitOfWork); @@ -328,7 +328,7 @@ namespace Umbraco.Tests.Persistence.Repositories public void Can_Perform_Delete_On_DictionaryRepository() { // Arrange - var provider = new PetaPocoUnitOfWorkProvider(Logger); + var provider = new NPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); using (var repository = CreateRepository(unitOfWork)) { @@ -349,7 +349,7 @@ namespace Umbraco.Tests.Persistence.Repositories public void Can_Perform_Exists_On_DictionaryRepository() { // Arrange - var provider = new PetaPocoUnitOfWorkProvider(Logger); + var provider = new NPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); using (var repository = CreateRepository(unitOfWork)) { diff --git a/src/Umbraco.Tests/Persistence/Repositories/DomainRepositoryTest.cs b/src/Umbraco.Tests/Persistence/Repositories/DomainRepositoryTest.cs index 1b00f0089c..c68a1fb76a 100644 --- a/src/Umbraco.Tests/Persistence/Repositories/DomainRepositoryTest.cs +++ b/src/Umbraco.Tests/Persistence/Repositories/DomainRepositoryTest.cs @@ -30,7 +30,7 @@ namespace Umbraco.Tests.Persistence.Repositories private int CreateTestData(string isoName, out ContentType ct) { - var provider = new PetaPocoUnitOfWorkProvider(Logger); + var provider = new NPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); ContentRepository contentRepo; @@ -54,7 +54,7 @@ namespace Umbraco.Tests.Persistence.Repositories [Test] public void Can_Create_And_Get_By_Id() { - var provider = new PetaPocoUnitOfWorkProvider(Logger); + var provider = new NPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); ContentType ct; @@ -89,7 +89,7 @@ namespace Umbraco.Tests.Persistence.Repositories [Test] public void Can_Create_And_Get_By_Id_Empty_lang() { - var provider = new PetaPocoUnitOfWorkProvider(Logger); + var provider = new NPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); ContentType ct; @@ -122,7 +122,7 @@ namespace Umbraco.Tests.Persistence.Repositories [Test] public void Cant_Create_Duplicate_Domain_Name() { - var provider = new PetaPocoUnitOfWorkProvider(Logger); + var provider = new NPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); ContentType ct; @@ -155,7 +155,7 @@ namespace Umbraco.Tests.Persistence.Repositories [Test] public void Can_Delete() { - var provider = new PetaPocoUnitOfWorkProvider(Logger); + var provider = new NPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); ContentType ct; @@ -190,7 +190,7 @@ namespace Umbraco.Tests.Persistence.Repositories [Test] public void Can_Update() { - var provider = new PetaPocoUnitOfWorkProvider(Logger); + var provider = new NPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); ContentType ct; @@ -242,7 +242,7 @@ namespace Umbraco.Tests.Persistence.Repositories [Test] public void Exists() { - var provider = new PetaPocoUnitOfWorkProvider(Logger); + var provider = new NPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); ContentType ct; @@ -273,7 +273,7 @@ namespace Umbraco.Tests.Persistence.Repositories [Test] public void Get_By_Name() { - var provider = new PetaPocoUnitOfWorkProvider(Logger); + var provider = new NPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); ContentType ct; @@ -304,7 +304,7 @@ namespace Umbraco.Tests.Persistence.Repositories [Test] public void Get_All() { - var provider = new PetaPocoUnitOfWorkProvider(Logger); + var provider = new NPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); ContentType ct; @@ -335,7 +335,7 @@ namespace Umbraco.Tests.Persistence.Repositories [Test] public void Get_All_Ids() { - var provider = new PetaPocoUnitOfWorkProvider(Logger); + var provider = new NPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); ContentType ct; @@ -368,7 +368,7 @@ namespace Umbraco.Tests.Persistence.Repositories [Test] public void Get_All_Without_Wildcards() { - var provider = new PetaPocoUnitOfWorkProvider(Logger); + var provider = new NPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); ContentType ct; @@ -403,7 +403,7 @@ namespace Umbraco.Tests.Persistence.Repositories [Test] public void Get_All_For_Content() { - var provider = new PetaPocoUnitOfWorkProvider(Logger); + var provider = new NPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); ContentType ct; @@ -454,7 +454,7 @@ namespace Umbraco.Tests.Persistence.Repositories [Test] public void Get_All_For_Content_Without_Wildcards() { - var provider = new PetaPocoUnitOfWorkProvider(Logger); + var provider = new NPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); ContentType ct; diff --git a/src/Umbraco.Tests/Persistence/Repositories/LanguageRepositoryTest.cs b/src/Umbraco.Tests/Persistence/Repositories/LanguageRepositoryTest.cs index bcad6e0720..9e30c9e71a 100644 --- a/src/Umbraco.Tests/Persistence/Repositories/LanguageRepositoryTest.cs +++ b/src/Umbraco.Tests/Persistence/Repositories/LanguageRepositoryTest.cs @@ -37,8 +37,9 @@ namespace Umbraco.Tests.Persistence.Repositories public void Can_Perform_Get_On_LanguageRepository() { // Arrange - var provider = new PetaPocoUnitOfWorkProvider(Logger); + var provider = new NPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); + unitOfWork.Database.EnableSqlTrace = true; using (var repository = CreateRepository(unitOfWork)) { // Act @@ -55,7 +56,7 @@ namespace Umbraco.Tests.Persistence.Repositories [Test] public void Can_Perform_Get_By_Iso_Code_On_LanguageRepository() { - var provider = new PetaPocoUnitOfWorkProvider(Logger); + var provider = new NPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); using (var repository = CreateRepository(unitOfWork)) { @@ -81,7 +82,7 @@ namespace Umbraco.Tests.Persistence.Repositories [Test] public void Can_Perform_Get_By_Culture_Name_On_LanguageRepository() { - var provider = new PetaPocoUnitOfWorkProvider(Logger); + var provider = new NPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); using (var repository = CreateRepository(unitOfWork)) { @@ -108,7 +109,7 @@ namespace Umbraco.Tests.Persistence.Repositories public void Get_WhenIdDoesntExist_ReturnsNull() { // Arrange - var provider = new PetaPocoUnitOfWorkProvider(Logger); + var provider = new NPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); using (var repository = CreateRepository(unitOfWork)) { @@ -124,7 +125,7 @@ namespace Umbraco.Tests.Persistence.Repositories public void Can_Perform_GetAll_On_LanguageRepository() { // Arrange - var provider = new PetaPocoUnitOfWorkProvider(Logger); + var provider = new NPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); using (var repository = CreateRepository(unitOfWork)) { @@ -144,7 +145,7 @@ namespace Umbraco.Tests.Persistence.Repositories public void Can_Perform_GetAll_With_Params_On_LanguageRepository() { // Arrange - var provider = new PetaPocoUnitOfWorkProvider(Logger); + var provider = new NPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); using (var repository = CreateRepository(unitOfWork)) { @@ -164,7 +165,7 @@ namespace Umbraco.Tests.Persistence.Repositories public void Can_Perform_GetByQuery_On_LanguageRepository() { // Arrange - var provider = new PetaPocoUnitOfWorkProvider(Logger); + var provider = new NPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); using (var repository = CreateRepository(unitOfWork)) { @@ -184,7 +185,7 @@ namespace Umbraco.Tests.Persistence.Repositories public void Can_Perform_Count_On_LanguageRepository() { // Arrange - var provider = new PetaPocoUnitOfWorkProvider(Logger); + var provider = new NPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); using (var repository = CreateRepository(unitOfWork)) { @@ -202,7 +203,7 @@ namespace Umbraco.Tests.Persistence.Repositories public void Can_Perform_Add_On_LanguageRepository() { // Arrange - var provider = new PetaPocoUnitOfWorkProvider(Logger); + var provider = new NPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); using (var repository = CreateRepository(unitOfWork)) { @@ -222,7 +223,7 @@ namespace Umbraco.Tests.Persistence.Repositories public void Can_Perform_Update_On_LanguageRepository() { // Arrange - var provider = new PetaPocoUnitOfWorkProvider(Logger); + var provider = new NPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); using (var repository = CreateRepository(unitOfWork)) { @@ -248,7 +249,7 @@ namespace Umbraco.Tests.Persistence.Repositories public void Can_Perform_Delete_On_LanguageRepository() { // Arrange - var provider = new PetaPocoUnitOfWorkProvider(Logger); + var provider = new NPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); using (var repository = CreateRepository(unitOfWork)) { @@ -269,7 +270,7 @@ namespace Umbraco.Tests.Persistence.Repositories public void Can_Perform_Exists_On_LanguageRepository() { // Arrange - var provider = new PetaPocoUnitOfWorkProvider(Logger); + var provider = new NPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); using (var repository = CreateRepository(unitOfWork)) { diff --git a/src/Umbraco.Tests/Persistence/Repositories/MacroRepositoryTest.cs b/src/Umbraco.Tests/Persistence/Repositories/MacroRepositoryTest.cs index 6ea233aa1a..9e4655baa3 100644 --- a/src/Umbraco.Tests/Persistence/Repositories/MacroRepositoryTest.cs +++ b/src/Umbraco.Tests/Persistence/Repositories/MacroRepositoryTest.cs @@ -30,7 +30,7 @@ namespace Umbraco.Tests.Persistence.Repositories public void Cannot_Add_Duplicate_Macros() { // Arrange - var provider = new PetaPocoUnitOfWorkProvider(Logger); + var provider = new NPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); // Act @@ -48,7 +48,7 @@ namespace Umbraco.Tests.Persistence.Repositories public void Cannot_Update_To_Duplicate_Macro_Alias() { // Arrange - var provider = new PetaPocoUnitOfWorkProvider(Logger); + var provider = new NPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); // Act @@ -66,7 +66,7 @@ namespace Umbraco.Tests.Persistence.Repositories public void Can_Instantiate_Repository() { // Arrange - var provider = new PetaPocoUnitOfWorkProvider(Logger); + var provider = new NPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); // Act @@ -81,7 +81,7 @@ namespace Umbraco.Tests.Persistence.Repositories public void Can_Perform_Get_On_Repository() { // Arrange - var provider = new PetaPocoUnitOfWorkProvider(Logger); + var provider = new NPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); using (var repository = new MacroRepository(unitOfWork, CacheHelper.CreateDisabledCacheHelper(), Mock.Of(), SqlSyntax, MappingResolver)) { @@ -111,7 +111,7 @@ namespace Umbraco.Tests.Persistence.Repositories public void Can_Perform_GetAll_On_Repository() { // Arrange - var provider = new PetaPocoUnitOfWorkProvider(Logger); + var provider = new NPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); using (var repository = new MacroRepository(unitOfWork, CacheHelper.CreateDisabledCacheHelper(), Mock.Of(), SqlSyntax, MappingResolver)) { @@ -128,7 +128,7 @@ namespace Umbraco.Tests.Persistence.Repositories public void Can_Perform_GetByQuery_On_Repository() { // Arrange - var provider = new PetaPocoUnitOfWorkProvider(Logger); + var provider = new NPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); using (var repository = new MacroRepository(unitOfWork, CacheHelper.CreateDisabledCacheHelper(), Mock.Of(), SqlSyntax, MappingResolver)) { @@ -145,7 +145,7 @@ namespace Umbraco.Tests.Persistence.Repositories public void Can_Perform_Count_On_Repository() { // Arrange - var provider = new PetaPocoUnitOfWorkProvider(Logger); + var provider = new NPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); using (var repository = new MacroRepository(unitOfWork, CacheHelper.CreateDisabledCacheHelper(), Mock.Of(), SqlSyntax, MappingResolver)) { @@ -162,7 +162,7 @@ namespace Umbraco.Tests.Persistence.Repositories public void Can_Perform_Add_On_Repository() { // Arrange - var provider = new PetaPocoUnitOfWorkProvider(Logger); + var provider = new NPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); using (var repository = new MacroRepository(unitOfWork, CacheHelper.CreateDisabledCacheHelper(), Mock.Of(), SqlSyntax, MappingResolver)) { @@ -183,7 +183,7 @@ namespace Umbraco.Tests.Persistence.Repositories public void Can_Perform_Update_On_Repository() { // Arrange - var provider = new PetaPocoUnitOfWorkProvider(Logger); + var provider = new NPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); using (var repository = new MacroRepository(unitOfWork, CacheHelper.CreateDisabledCacheHelper(), Mock.Of(), SqlSyntax, MappingResolver)) { @@ -224,7 +224,7 @@ namespace Umbraco.Tests.Persistence.Repositories public void Can_Perform_Delete_On_Repository() { // Arrange - var provider = new PetaPocoUnitOfWorkProvider(Logger); + var provider = new NPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); using (var repository = new MacroRepository(unitOfWork, CacheHelper.CreateDisabledCacheHelper(), Mock.Of(), SqlSyntax, MappingResolver)) { @@ -245,7 +245,7 @@ namespace Umbraco.Tests.Persistence.Repositories public void Can_Perform_Exists_On_Repository() { // Arrange - var provider = new PetaPocoUnitOfWorkProvider(Logger); + var provider = new NPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); using (var repository = new MacroRepository(unitOfWork, CacheHelper.CreateDisabledCacheHelper(), Mock.Of(), SqlSyntax, MappingResolver)) { @@ -263,7 +263,7 @@ namespace Umbraco.Tests.Persistence.Repositories public void Can_Add_Property_For_Macro() { // Arrange - var provider = new PetaPocoUnitOfWorkProvider(Logger); + var provider = new NPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); using (var repository = new MacroRepository(unitOfWork, CacheHelper.CreateDisabledCacheHelper(), Mock.Of(), SqlSyntax, MappingResolver)) { @@ -290,7 +290,7 @@ namespace Umbraco.Tests.Persistence.Repositories public void Can_Add_New_Macro_With_Property() { // Arrange - var provider = new PetaPocoUnitOfWorkProvider(Logger); + var provider = new NPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); using (var repository = new MacroRepository(unitOfWork, CacheHelper.CreateDisabledCacheHelper(), Mock.Of(), SqlSyntax, MappingResolver)) { @@ -315,7 +315,7 @@ namespace Umbraco.Tests.Persistence.Repositories public void Can_Remove_Macro_Property() { // Arrange - var provider = new PetaPocoUnitOfWorkProvider(Logger); + var provider = new NPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); using (var repository = new MacroRepository(unitOfWork, CacheHelper.CreateDisabledCacheHelper(), Mock.Of(), SqlSyntax, MappingResolver)) { @@ -340,7 +340,7 @@ namespace Umbraco.Tests.Persistence.Repositories public void Can_Add_Remove_Macro_Properties() { // Arrange - var provider = new PetaPocoUnitOfWorkProvider(Logger); + var provider = new NPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); using (var repository = new MacroRepository(unitOfWork, CacheHelper.CreateDisabledCacheHelper(), Mock.Of(), SqlSyntax, MappingResolver)) { @@ -371,7 +371,7 @@ namespace Umbraco.Tests.Persistence.Repositories public void Can_Update_Property_For_Macro() { // Arrange - var provider = new PetaPocoUnitOfWorkProvider(Logger); + var provider = new NPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); using (var repository = new MacroRepository(unitOfWork, CacheHelper.CreateDisabledCacheHelper(), Mock.Of(), SqlSyntax, MappingResolver)) { @@ -399,7 +399,7 @@ namespace Umbraco.Tests.Persistence.Repositories public void Can_Update_Macro_Property_Alias() { // Arrange - var provider = new PetaPocoUnitOfWorkProvider(Logger); + var provider = new NPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); using (var repository = new MacroRepository(unitOfWork, CacheHelper.CreateDisabledCacheHelper(), Mock.Of(), SqlSyntax, MappingResolver)) { @@ -428,7 +428,7 @@ namespace Umbraco.Tests.Persistence.Repositories public void CreateTestData() { - var provider = new PetaPocoUnitOfWorkProvider(Logger); + var provider = new NPocoUnitOfWorkProvider(Logger); using (var unitOfWork = provider.GetUnitOfWork()) using (var repository = new MacroRepository(unitOfWork, CacheHelper.CreateDisabledCacheHelper(), Mock.Of(), SqlSyntax, MappingResolver)) { diff --git a/src/Umbraco.Tests/Persistence/Repositories/MediaRepositoryTest.cs b/src/Umbraco.Tests/Persistence/Repositories/MediaRepositoryTest.cs index 0a53bbae7d..116dd2e582 100644 --- a/src/Umbraco.Tests/Persistence/Repositories/MediaRepositoryTest.cs +++ b/src/Umbraco.Tests/Persistence/Repositories/MediaRepositoryTest.cs @@ -27,7 +27,7 @@ namespace Umbraco.Tests.Persistence.Repositories [SetUp] public override void Initialize() - { + { base.Initialize(); CreateTestData(); @@ -44,19 +44,19 @@ namespace Umbraco.Tests.Persistence.Repositories [Test] public void Rebuild_All_Xml_Structures() { - var provider = new PetaPocoUnitOfWorkProvider(Logger); + var provider = new NPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); MediaTypeRepository mediaTypeRepository; using (var repository = CreateRepository(unitOfWork, out mediaTypeRepository)) { var mediaType = mediaTypeRepository.Get(1032); - + for (var i = 0; i < 100; i++) { var image = MockedMedia.CreateMediaImage(mediaType, -1); repository.AddOrUpdate(image); - } + } unitOfWork.Commit(); //delete all xml @@ -72,7 +72,7 @@ namespace Umbraco.Tests.Persistence.Repositories [Test] public void Rebuild_All_Xml_Structures_For_Content_Type() { - var provider = new PetaPocoUnitOfWorkProvider(Logger); + var provider = new NPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); MediaTypeRepository mediaTypeRepository; using (var repository = CreateRepository(unitOfWork, out mediaTypeRepository)) @@ -81,7 +81,7 @@ namespace Umbraco.Tests.Persistence.Repositories var imageMediaType = mediaTypeRepository.Get(1032); var fileMediaType = mediaTypeRepository.Get(1033); var folderMediaType = mediaTypeRepository.Get(1031); - + for (var i = 0; i < 30; i++) { var image = MockedMedia.CreateMediaImage(imageMediaType, -1); @@ -103,17 +103,17 @@ namespace Umbraco.Tests.Persistence.Repositories unitOfWork.Database.Execute("DELETE FROM cmsContentXml"); Assert.AreEqual(0, unitOfWork.Database.ExecuteScalar("SELECT COUNT(*) FROM cmsContentXml")); - repository.RebuildXmlStructures(media => new XElement("test"), 10, contentTypeIds: new[] {1032, 1033}); + repository.RebuildXmlStructures(media => new XElement("test"), 10, contentTypeIds: new[] { 1032, 1033 }); Assert.AreEqual(62, unitOfWork.Database.ExecuteScalar("SELECT COUNT(*) FROM cmsContentXml")); } } - + [Test] public void Can_Perform_Add_On_MediaRepository() { // Arrange - var provider = new PetaPocoUnitOfWorkProvider(Logger); + var provider = new NPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); MediaTypeRepository mediaTypeRepository; using (var repository = CreateRepository(unitOfWork, out mediaTypeRepository)) @@ -137,7 +137,7 @@ namespace Umbraco.Tests.Persistence.Repositories public void Can_Perform_Multiple_Adds_On_MediaRepository() { // Arrange - var provider = new PetaPocoUnitOfWorkProvider(Logger); + var provider = new NPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); MediaTypeRepository mediaTypeRepository; using (var repository = CreateRepository(unitOfWork, out mediaTypeRepository)) @@ -168,7 +168,7 @@ namespace Umbraco.Tests.Persistence.Repositories public void Can_Perform_Multiple_Adds_On_MediaRepository_With_RepositoryResolver() { // Arrange - var provider = new PetaPocoUnitOfWorkProvider(Logger); + var provider = new NPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); MediaTypeRepository mediaTypeRepository; using (var repository = CreateRepository(unitOfWork, out mediaTypeRepository)) @@ -199,7 +199,7 @@ namespace Umbraco.Tests.Persistence.Repositories public void Can_Verify_Fresh_Entity_Is_Not_Dirty() { // Arrange - var provider = new PetaPocoUnitOfWorkProvider(Logger); + var provider = new NPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); MediaTypeRepository mediaTypeRepository; using (var repository = CreateRepository(unitOfWork, out mediaTypeRepository)) @@ -207,7 +207,7 @@ namespace Umbraco.Tests.Persistence.Repositories // Act var media = repository.Get(NodeDto.NodeIdSeed + 1); - bool dirty = ((ICanBeDirty) media).IsDirty(); + bool dirty = ((ICanBeDirty)media).IsDirty(); // Assert Assert.That(dirty, Is.False); @@ -218,7 +218,7 @@ namespace Umbraco.Tests.Persistence.Repositories public void Can_Perform_Update_On_MediaRepository() { // Arrange - var provider = new PetaPocoUnitOfWorkProvider(Logger); + var provider = new NPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); MediaTypeRepository mediaTypeRepository; using (var repository = CreateRepository(unitOfWork, out mediaTypeRepository)) @@ -242,7 +242,7 @@ namespace Umbraco.Tests.Persistence.Repositories public void Can_Perform_Delete_On_MediaRepository() { // Arrange - var provider = new PetaPocoUnitOfWorkProvider(Logger); + var provider = new NPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); MediaTypeRepository mediaTypeRepository; using (var repository = CreateRepository(unitOfWork, out mediaTypeRepository)) @@ -266,7 +266,7 @@ namespace Umbraco.Tests.Persistence.Repositories public void Can_Perform_Get_On_MediaRepository() { // Arrange - var provider = new PetaPocoUnitOfWorkProvider(Logger); + var provider = new NPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); MediaTypeRepository mediaTypeRepository; using (var repository = CreateRepository(unitOfWork, out mediaTypeRepository)) @@ -293,7 +293,7 @@ namespace Umbraco.Tests.Persistence.Repositories public void Can_Perform_GetByQuery_On_MediaRepository() { // Arrange - var provider = new PetaPocoUnitOfWorkProvider(Logger); + var provider = new NPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); MediaTypeRepository mediaTypeRepository; using (var repository = CreateRepository(unitOfWork, out mediaTypeRepository)) @@ -311,7 +311,7 @@ namespace Umbraco.Tests.Persistence.Repositories public void Can_Perform_GetPagedResultsByQuery_ForFirstPage_On_MediaRepository() { // Arrange - var provider = new PetaPocoUnitOfWorkProvider(Logger); + var provider = new NPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); MediaTypeRepository mediaTypeRepository; using (var repository = CreateRepository(unitOfWork, out mediaTypeRepository)) @@ -319,7 +319,7 @@ namespace Umbraco.Tests.Persistence.Repositories // Act var query = new Query(SqlSyntax, MappingResolver).Where(x => x.Level == 2); long totalRecords; - var result = repository.GetPagedResultsByQuery(query, 0, 1, out totalRecords, "SortOrder", Direction.Ascending); + var result = repository.GetPagedResultsByQuery(query, 0, 1, out totalRecords, "SortOrder", Direction.Ascending, true); // Assert Assert.That(totalRecords, Is.GreaterThanOrEqualTo(2)); @@ -332,7 +332,7 @@ namespace Umbraco.Tests.Persistence.Repositories public void Can_Perform_GetPagedResultsByQuery_ForSecondPage_On_MediaRepository() { // Arrange - var provider = new PetaPocoUnitOfWorkProvider(Logger); + var provider = new NPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); MediaTypeRepository mediaTypeRepository; using (var repository = CreateRepository(unitOfWork, out mediaTypeRepository)) @@ -340,7 +340,7 @@ namespace Umbraco.Tests.Persistence.Repositories // Act var query = new Query(SqlSyntax, MappingResolver).Where(x => x.Level == 2); long totalRecords; - var result = repository.GetPagedResultsByQuery(query, 1, 1, out totalRecords, "SortOrder", Direction.Ascending); + var result = repository.GetPagedResultsByQuery(query, 1, 1, out totalRecords, "SortOrder", Direction.Ascending, true); // Assert Assert.That(totalRecords, Is.GreaterThanOrEqualTo(2)); @@ -353,7 +353,7 @@ namespace Umbraco.Tests.Persistence.Repositories public void Can_Perform_GetPagedResultsByQuery_WithSinglePage_On_MediaRepository() { // Arrange - var provider = new PetaPocoUnitOfWorkProvider(Logger); + var provider = new NPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); MediaTypeRepository mediaTypeRepository; using (var repository = CreateRepository(unitOfWork, out mediaTypeRepository)) @@ -361,7 +361,7 @@ namespace Umbraco.Tests.Persistence.Repositories // Act var query = new Query(SqlSyntax, MappingResolver).Where(x => x.Level == 2); long totalRecords; - var result = repository.GetPagedResultsByQuery(query, 0, 2, out totalRecords, "SortOrder", Direction.Ascending); + var result = repository.GetPagedResultsByQuery(query, 0, 2, out totalRecords, "SortOrder", Direction.Ascending, true); // Assert Assert.That(totalRecords, Is.GreaterThanOrEqualTo(2)); @@ -374,7 +374,7 @@ namespace Umbraco.Tests.Persistence.Repositories public void Can_Perform_GetPagedResultsByQuery_WithDescendingOrder_On_MediaRepository() { // Arrange - var provider = new PetaPocoUnitOfWorkProvider(Logger); + var provider = new NPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); MediaTypeRepository mediaTypeRepository; using (var repository = CreateRepository(unitOfWork, out mediaTypeRepository)) @@ -382,7 +382,7 @@ namespace Umbraco.Tests.Persistence.Repositories // Act var query = new Query(SqlSyntax, MappingResolver).Where(x => x.Level == 2); long totalRecords; - var result = repository.GetPagedResultsByQuery(query, 0, 1, out totalRecords, "SortOrder", Direction.Descending); + var result = repository.GetPagedResultsByQuery(query, 0, 1, out totalRecords, "SortOrder", Direction.Descending, true); // Assert Assert.That(totalRecords, Is.GreaterThanOrEqualTo(2)); @@ -395,7 +395,7 @@ namespace Umbraco.Tests.Persistence.Repositories public void Can_Perform_GetPagedResultsByQuery_WitAlternateOrder_On_MediaRepository() { // Arrange - var provider = new PetaPocoUnitOfWorkProvider(Logger); + var provider = new NPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); MediaTypeRepository mediaTypeRepository; using (var repository = CreateRepository(unitOfWork, out mediaTypeRepository)) @@ -403,7 +403,7 @@ namespace Umbraco.Tests.Persistence.Repositories // Act var query = new Query(SqlSyntax, MappingResolver).Where(x => x.Level == 2); long totalRecords; - var result = repository.GetPagedResultsByQuery(query, 0, 1, out totalRecords, "Name", Direction.Ascending); + var result = repository.GetPagedResultsByQuery(query, 0, 1, out totalRecords, "Name", Direction.Ascending, true); // Assert Assert.That(totalRecords, Is.GreaterThanOrEqualTo(2)); @@ -416,7 +416,7 @@ namespace Umbraco.Tests.Persistence.Repositories public void Can_Perform_GetPagedResultsByQuery_WithFilterMatchingSome_On_MediaRepository() { // Arrange - var provider = new PetaPocoUnitOfWorkProvider(Logger); + var provider = new NPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); MediaTypeRepository mediaTypeRepository; using (var repository = CreateRepository(unitOfWork, out mediaTypeRepository)) @@ -424,7 +424,7 @@ namespace Umbraco.Tests.Persistence.Repositories // Act var query = new Query(SqlSyntax, MappingResolver).Where(x => x.Level == 2); long totalRecords; - var result = repository.GetPagedResultsByQuery(query, 0, 1, out totalRecords, "SortOrder", Direction.Ascending, "File"); + var result = repository.GetPagedResultsByQuery(query, 0, 1, out totalRecords, "SortOrder", Direction.Ascending, true, "File"); // Assert Assert.That(totalRecords, Is.EqualTo(1)); @@ -437,7 +437,7 @@ namespace Umbraco.Tests.Persistence.Repositories public void Can_Perform_GetPagedResultsByQuery_WithFilterMatchingAll_On_MediaRepository() { // Arrange - var provider = new PetaPocoUnitOfWorkProvider(Logger); + var provider = new NPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); MediaTypeRepository mediaTypeRepository; using (var repository = CreateRepository(unitOfWork, out mediaTypeRepository)) @@ -445,7 +445,7 @@ namespace Umbraco.Tests.Persistence.Repositories // Act var query = new Query(SqlSyntax, MappingResolver).Where(x => x.Level == 2); long totalRecords; - var result = repository.GetPagedResultsByQuery(query, 0, 1, out totalRecords, "SortOrder", Direction.Ascending, "Test"); + var result = repository.GetPagedResultsByQuery(query, 0, 1, out totalRecords, "SortOrder", Direction.Ascending, true, "Test"); // Assert Assert.That(totalRecords, Is.EqualTo(2)); @@ -458,7 +458,7 @@ namespace Umbraco.Tests.Persistence.Repositories public void Can_Perform_GetAll_By_Param_Ids_On_MediaRepository() { // Arrange - var provider = new PetaPocoUnitOfWorkProvider(Logger); + var provider = new NPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); MediaTypeRepository mediaTypeRepository; using (var repository = CreateRepository(unitOfWork, out mediaTypeRepository)) @@ -478,7 +478,7 @@ namespace Umbraco.Tests.Persistence.Repositories public void Can_Perform_GetAll_On_MediaRepository() { // Arrange - var provider = new PetaPocoUnitOfWorkProvider(Logger); + var provider = new NPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); MediaTypeRepository mediaTypeRepository; using (var repository = CreateRepository(unitOfWork, out mediaTypeRepository)) @@ -498,7 +498,7 @@ namespace Umbraco.Tests.Persistence.Repositories public void Can_Perform_Exists_On_MediaRepository() { // Arrange - var provider = new PetaPocoUnitOfWorkProvider(Logger); + var provider = new NPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); MediaTypeRepository mediaTypeRepository; using (var repository = CreateRepository(unitOfWork, out mediaTypeRepository)) @@ -520,7 +520,7 @@ namespace Umbraco.Tests.Persistence.Repositories public void Can_Perform_Count_On_MediaRepository() { // Arrange - var provider = new PetaPocoUnitOfWorkProvider(Logger); + var provider = new NPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); MediaTypeRepository mediaTypeRepository; using (var repository = CreateRepository(unitOfWork, out mediaTypeRepository)) diff --git a/src/Umbraco.Tests/Persistence/Repositories/MediaTypeRepositoryTest.cs b/src/Umbraco.Tests/Persistence/Repositories/MediaTypeRepositoryTest.cs index fd7c440527..d85ff5a72e 100644 --- a/src/Umbraco.Tests/Persistence/Repositories/MediaTypeRepositoryTest.cs +++ b/src/Umbraco.Tests/Persistence/Repositories/MediaTypeRepositoryTest.cs @@ -40,7 +40,7 @@ namespace Umbraco.Tests.Persistence.Repositories [Test] public void Can_Move() { - var provider = new PetaPocoUnitOfWorkProvider(Logger); + var provider = new NPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); using (var containerRepository = CreateContainerRepository(unitOfWork)) using (var repository = CreateRepository(unitOfWork)) @@ -86,7 +86,7 @@ namespace Umbraco.Tests.Persistence.Repositories [Test] public void Can_Create_Container() { - var provider = new PetaPocoUnitOfWorkProvider(Logger); + var provider = new NPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); EntityContainer container; using (var containerRepository = CreateContainerRepository(unitOfWork)) @@ -106,7 +106,7 @@ namespace Umbraco.Tests.Persistence.Repositories [Test] public void Can_Delete_Container() { - var provider = new PetaPocoUnitOfWorkProvider(Logger); + var provider = new NPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); EntityContainer container; using (var containerRepository = CreateContainerRepository(unitOfWork)) @@ -132,7 +132,7 @@ namespace Umbraco.Tests.Persistence.Repositories [Test] public void Can_Create_Container_Containing_Media_Types() { - var provider = new PetaPocoUnitOfWorkProvider(Logger); + var provider = new NPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); using (var containerRepository = CreateContainerRepository(unitOfWork)) using (var repository = CreateRepository(unitOfWork)) @@ -153,7 +153,7 @@ namespace Umbraco.Tests.Persistence.Repositories [Test] public void Can_Delete_Container_Containing_Media_Types() { - var provider = new PetaPocoUnitOfWorkProvider(Logger); + var provider = new NPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); EntityContainer container; IMediaType contentType; @@ -189,7 +189,7 @@ namespace Umbraco.Tests.Persistence.Repositories public void Can_Perform_Add_On_MediaTypeRepository() { // Arrange - var provider = new PetaPocoUnitOfWorkProvider(Logger); + var provider = new NPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); using (var repository = CreateRepository(unitOfWork)) { @@ -212,7 +212,7 @@ namespace Umbraco.Tests.Persistence.Repositories public void Can_Perform_Update_On_MediaTypeRepository() { // Arrange - var provider = new PetaPocoUnitOfWorkProvider(Logger); + var provider = new NPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); using (var repository = CreateRepository(unitOfWork)) { @@ -249,7 +249,7 @@ namespace Umbraco.Tests.Persistence.Repositories public void Can_Perform_Delete_On_MediaTypeRepository() { // Arrange - var provider = new PetaPocoUnitOfWorkProvider(Logger); + var provider = new NPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); using (var repository = CreateRepository(unitOfWork)) { @@ -274,7 +274,7 @@ namespace Umbraco.Tests.Persistence.Repositories public void Can_Perform_Get_On_MediaTypeRepository() { // Arrange - var provider = new PetaPocoUnitOfWorkProvider(Logger); + var provider = new NPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); using (var repository = CreateRepository(unitOfWork)) { @@ -293,7 +293,7 @@ namespace Umbraco.Tests.Persistence.Repositories public void Can_Perform_Get_By_Guid_On_MediaTypeRepository() { // Arrange - var provider = new PetaPocoUnitOfWorkProvider(Logger); + var provider = new NPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); using (var repository = CreateRepository(unitOfWork)) { @@ -313,7 +313,7 @@ namespace Umbraco.Tests.Persistence.Repositories public void Can_Perform_GetAll_On_MediaTypeRepository() { // Arrange - var provider = new PetaPocoUnitOfWorkProvider(Logger); + var provider = new NPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); using (var repository = CreateRepository(unitOfWork)) { @@ -334,7 +334,7 @@ namespace Umbraco.Tests.Persistence.Repositories public void Can_Perform_GetAll_By_Guid_On_MediaTypeRepository() { // Arrange - var provider = new PetaPocoUnitOfWorkProvider(Logger); + var provider = new NPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); using (var repository = CreateRepository(unitOfWork)) { @@ -359,7 +359,7 @@ namespace Umbraco.Tests.Persistence.Repositories public void Can_Perform_Exists_On_MediaTypeRepository() { // Arrange - var provider = new PetaPocoUnitOfWorkProvider(Logger); + var provider = new NPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); using (var repository = CreateRepository(unitOfWork)) { @@ -376,7 +376,7 @@ namespace Umbraco.Tests.Persistence.Repositories public void Can_Update_MediaType_With_PropertyType_Removed() { // Arrange - var provider = new PetaPocoUnitOfWorkProvider(Logger); + var provider = new NPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); using (var repository = CreateRepository(unitOfWork)) { @@ -403,7 +403,7 @@ namespace Umbraco.Tests.Persistence.Repositories public void Can_Verify_PropertyTypes_On_Video_MediaType() { // Arrange - var provider = new PetaPocoUnitOfWorkProvider(Logger); + var provider = new NPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); using (var repository = CreateRepository(unitOfWork)) { @@ -424,7 +424,7 @@ namespace Umbraco.Tests.Persistence.Repositories public void Can_Verify_PropertyTypes_On_File_MediaType() { // Arrange - var provider = new PetaPocoUnitOfWorkProvider(Logger); + var provider = new NPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); using (var repository = CreateRepository(unitOfWork)) { diff --git a/src/Umbraco.Tests/Persistence/Repositories/MemberRepositoryTest.cs b/src/Umbraco.Tests/Persistence/Repositories/MemberRepositoryTest.cs index c47c46b1be..23796ca3ca 100644 --- a/src/Umbraco.Tests/Persistence/Repositories/MemberRepositoryTest.cs +++ b/src/Umbraco.Tests/Persistence/Repositories/MemberRepositoryTest.cs @@ -2,6 +2,7 @@ using System.Linq; using System.Xml.Linq; using Moq; +using NPoco; using NUnit.Framework; using Umbraco.Core; using Umbraco.Core.Configuration.UmbracoSettings; @@ -46,14 +47,14 @@ namespace Umbraco.Tests.Persistence.Repositories [Test] public void Rebuild_All_Xml_Structures() { - var provider = new PetaPocoUnitOfWorkProvider(Logger); + var provider = new NPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); MemberTypeRepository memberTypeRepository; MemberGroupRepository memberGroupRepository; using (var repository = CreateRepository(unitOfWork, out memberTypeRepository, out memberGroupRepository)) { var memberType1 = CreateTestMemberType(); - + for (var i = 0; i < 100; i++) { var member = MockedMember.CreateSimpleMember(memberType1, "blah" + i, "blah" + i + "@example.com", "blah", "blah" + i); @@ -74,7 +75,7 @@ namespace Umbraco.Tests.Persistence.Repositories [Test] public void Rebuild_All_Xml_Structures_For_Content_Type() { - var provider = new PetaPocoUnitOfWorkProvider(Logger); + var provider = new NPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); MemberTypeRepository memberTypeRepository; MemberGroupRepository memberGroupRepository; @@ -102,7 +103,7 @@ namespace Umbraco.Tests.Persistence.Repositories } unitOfWork.Commit(); - //delete all xml + //delete all xml unitOfWork.Database.Execute("DELETE FROM cmsContentXml"); Assert.AreEqual(0, unitOfWork.Database.ExecuteScalar("SELECT COUNT(*) FROM cmsContentXml")); @@ -117,7 +118,7 @@ namespace Umbraco.Tests.Persistence.Repositories [Test] public void MemberRepository_Can_Get_Member_By_Id() { - var provider = new PetaPocoUnitOfWorkProvider(Logger); + var provider = new NPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); MemberTypeRepository memberTypeRepository; MemberGroupRepository memberGroupRepository; @@ -135,7 +136,7 @@ namespace Umbraco.Tests.Persistence.Repositories [Test] public void Can_Get_Members_By_Ids() { - var provider = new PetaPocoUnitOfWorkProvider(Logger); + var provider = new NPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); MemberTypeRepository memberTypeRepository; MemberGroupRepository memberGroupRepository; @@ -157,7 +158,7 @@ namespace Umbraco.Tests.Persistence.Repositories [Test] public void MemberRepository_Can_Get_All_Members() { - var provider = new PetaPocoUnitOfWorkProvider(Logger); + var provider = new NPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); MemberTypeRepository memberTypeRepository; MemberGroupRepository memberGroupRepository; @@ -182,7 +183,7 @@ namespace Umbraco.Tests.Persistence.Repositories public void MemberRepository_Can_Perform_GetByQuery_With_Key() { // Arrange - var provider = new PetaPocoUnitOfWorkProvider(Logger); + var provider = new NPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); MemberTypeRepository memberTypeRepository; MemberGroupRepository memberGroupRepository; @@ -204,7 +205,7 @@ namespace Umbraco.Tests.Persistence.Repositories [Test] public void Can_Persist_Member() { - var provider = new PetaPocoUnitOfWorkProvider(Logger); + var provider = new NPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); MemberTypeRepository memberTypeRepository; MemberGroupRepository memberGroupRepository; @@ -215,19 +216,19 @@ namespace Umbraco.Tests.Persistence.Repositories var sut = repository.Get(member.Id); Assert.That(sut, Is.Not.Null); - Assert.That(sut.HasIdentity, Is.True); + Assert.That(sut.HasIdentity, Is.True); Assert.That(sut.Properties.Any(x => x.HasIdentity == false || x.Id == 0), Is.False); Assert.That(sut.Name, Is.EqualTo("Johnny Hefty")); Assert.That(sut.Email, Is.EqualTo("johnny@example.com")); Assert.That(sut.RawPasswordValue, Is.EqualTo("123")); - Assert.That(sut.Username, Is.EqualTo("hefty")); + Assert.That(sut.Username, Is.EqualTo("hefty")); } } [Test] public void New_Member_Has_Built_In_Properties_By_Default() { - var provider = new PetaPocoUnitOfWorkProvider(Logger); + var provider = new NPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); MemberTypeRepository memberTypeRepository; MemberGroupRepository memberGroupRepository; @@ -261,7 +262,7 @@ namespace Umbraco.Tests.Persistence.Repositories public void MemberRepository_Does_Not_Replace_Password_When_Null() { IMember sut; - var provider = new PetaPocoUnitOfWorkProvider(Logger); + var provider = new NPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); MemberTypeRepository memberTypeRepository; MemberGroupRepository memberGroupRepository; @@ -290,7 +291,7 @@ namespace Umbraco.Tests.Persistence.Repositories public void MemberRepository_Can_Update_Email_And_Login_When_Changed() { IMember sut; - var provider = new PetaPocoUnitOfWorkProvider(Logger); + var provider = new NPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); MemberTypeRepository memberTypeRepository; MemberGroupRepository memberGroupRepository; @@ -327,9 +328,9 @@ namespace Umbraco.Tests.Persistence.Repositories var translator = new SqlTranslator(sqlSubquery, query); var subquery = translator.Translate(); var sql = GetBaseQuery(false) - .Append(new Sql("WHERE umbracoNode.id IN (" + subquery.SQL + ")", subquery.Arguments)) - .OrderByDescending(SqlSyntax, x => x.VersionDate) - .OrderBy(SqlSyntax, x => x.SortOrder); + .Append("WHERE umbracoNode.id IN (" + subquery.SQL + ")", subquery.Arguments) + .OrderByDescending(x => x.VersionDate) + .OrderBy(x => x.SortOrder); Console.WriteLine(sql.SQL); Assert.That(sql.SQL, Is.Not.Empty); @@ -337,7 +338,7 @@ namespace Umbraco.Tests.Persistence.Repositories private IMember CreateTestMember(IMemberType memberType = null, string name = null, string email = null, string password = null, string username = null, Guid? key = null) { - var provider = new PetaPocoUnitOfWorkProvider(Logger); + var provider = new NPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); MemberTypeRepository memberTypeRepository; MemberGroupRepository memberGroupRepository; @@ -347,7 +348,7 @@ namespace Umbraco.Tests.Persistence.Repositories { memberType = MockedContentTypes.CreateSimpleMemberType(); memberTypeRepository.AddOrUpdate(memberType); - unitOfWork.Commit(); + unitOfWork.Commit(); } var member = MockedMember.CreateSimpleMember(memberType, name ?? "Johnny Hefty", email ?? "johnny@example.com", password ?? "123", username ?? "hefty", key); @@ -360,7 +361,7 @@ namespace Umbraco.Tests.Persistence.Repositories private IMemberType CreateTestMemberType(string alias = null) { - var provider = new PetaPocoUnitOfWorkProvider(Logger); + var provider = new NPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); MemberTypeRepository memberTypeRepository; MemberGroupRepository memberGroupRepository; @@ -373,22 +374,22 @@ namespace Umbraco.Tests.Persistence.Repositories } } - private Sql GetBaseQuery(bool isCount) + private Sql GetBaseQuery(bool isCount) { if (isCount) { - var sqlCount = new Sql() - .Select("COUNT(*)") - .From(SqlSyntax) - .InnerJoin(SqlSyntax).On(SqlSyntax, left => left.NodeId, right => right.NodeId) - .InnerJoin(SqlSyntax).On(SqlSyntax, left => left.NodeId, right => right.ContentTypeId) - .InnerJoin(SqlSyntax).On(SqlSyntax, left => left.NodeId, right => right.NodeId) - .InnerJoin(SqlSyntax).On(SqlSyntax, left => left.NodeId, right => right.NodeId) - .Where(SqlSyntax, x => x.NodeObjectType == NodeObjectTypeId); + var sqlCount = NPoco.Sql.BuilderFor(new SqlContext(SqlSyntax, DatabaseContext.Database)) + .SelectCount() + .From() + .InnerJoin().On(left => left.NodeId, right => right.NodeId) + .InnerJoin().On(left => left.NodeId, right => right.ContentTypeId) + .InnerJoin().On(left => left.NodeId, right => right.NodeId) + .InnerJoin().On(left => left.NodeId, right => right.NodeId) + .Where(x => x.NodeObjectType == NodeObjectTypeId); return sqlCount; } - var sql = new Sql(); + var sql = NPoco.Sql.BuilderFor(new SqlContext(SqlSyntax, DatabaseContext.Database)); sql.Select("umbracoNode.*", "cmsContent.contentType", "cmsContentType.alias AS ContentTypeAlias", "cmsContentVersion.VersionId", "cmsContentVersion.VersionDate", "cmsMember.Email", "cmsMember.LoginName", "cmsMember.Password", "cmsPropertyData.id AS PropertyDataId", "cmsPropertyData.propertytypeid", @@ -397,33 +398,33 @@ namespace Umbraco.Tests.Persistence.Repositories "cmsPropertyType.Name", "cmsPropertyType.mandatory", "cmsPropertyType.validationRegExp", "cmsPropertyType.sortOrder AS PropertyTypeSortOrder", "cmsPropertyType.propertyTypeGroupId", "cmsPropertyType.dataTypeId", "cmsDataType.propertyEditorAlias", "cmsDataType.dbType") - .From(SqlSyntax) - .InnerJoin(SqlSyntax).On(SqlSyntax, left => left.NodeId, right => right.NodeId) - .InnerJoin(SqlSyntax).On(SqlSyntax, left => left.NodeId, right => right.ContentTypeId) - .InnerJoin(SqlSyntax).On(SqlSyntax, left => left.NodeId, right => right.NodeId) - .InnerJoin(SqlSyntax).On(SqlSyntax, left => left.NodeId, right => right.NodeId) - .LeftJoin(SqlSyntax).On(SqlSyntax, left => left.ContentTypeId, right => right.ContentTypeId) - .LeftJoin(SqlSyntax).On(SqlSyntax, left => left.DataTypeId, right => right.DataTypeId) - .LeftJoin(SqlSyntax).On(SqlSyntax, left => left.PropertyTypeId, right => right.Id) + .From() + .InnerJoin().On(left => left.NodeId, right => right.NodeId) + .InnerJoin().On(left => left.NodeId, right => right.ContentTypeId) + .InnerJoin().On(left => left.NodeId, right => right.NodeId) + .InnerJoin().On(left => left.NodeId, right => right.NodeId) + .LeftJoin().On(left => left.ContentTypeId, right => right.ContentTypeId) + .LeftJoin().On(left => left.DataTypeId, right => right.DataTypeId) + .LeftJoin().On(left => left.PropertyTypeId, right => right.Id) .Append("AND cmsPropertyData.versionId = cmsContentVersion.VersionId") - .Where(SqlSyntax, x => x.NodeObjectType == NodeObjectTypeId); + .Where(x => x.NodeObjectType == NodeObjectTypeId); return sql; } - private Sql GetSubquery() + private Sql GetSubquery() { - var sql = new Sql(); + var sql = NPoco.Sql.BuilderFor(new SqlContext(SqlSyntax, DatabaseContext.Database)); sql.Select("umbracoNode.id") - .From(SqlSyntax) - .InnerJoin(SqlSyntax).On(SqlSyntax, left => left.NodeId, right => right.NodeId) - .InnerJoin(SqlSyntax).On(SqlSyntax, left => left.NodeId, right => right.ContentTypeId) - .InnerJoin(SqlSyntax).On(SqlSyntax, left => left.NodeId, right => right.NodeId) - .InnerJoin(SqlSyntax).On(SqlSyntax, left => left.NodeId, right => right.NodeId) - .LeftJoin(SqlSyntax).On(SqlSyntax, left => left.ContentTypeId, right => right.ContentTypeId) - .LeftJoin(SqlSyntax).On(SqlSyntax, left => left.DataTypeId, right => right.DataTypeId) - .LeftJoin(SqlSyntax).On(SqlSyntax, left => left.PropertyTypeId, right => right.Id) + .From() + .InnerJoin().On(left => left.NodeId, right => right.NodeId) + .InnerJoin().On(left => left.NodeId, right => right.ContentTypeId) + .InnerJoin().On(left => left.NodeId, right => right.NodeId) + .InnerJoin().On(left => left.NodeId, right => right.NodeId) + .LeftJoin().On(left => left.ContentTypeId, right => right.ContentTypeId) + .LeftJoin().On(left => left.DataTypeId, right => right.DataTypeId) + .LeftJoin().On(left => left.PropertyTypeId, right => right.Id) .Append("AND cmsPropertyData.versionId = cmsContentVersion.VersionId") - .Where(SqlSyntax, x => x.NodeObjectType == NodeObjectTypeId); + .Where(x => x.NodeObjectType == NodeObjectTypeId); return sql; } diff --git a/src/Umbraco.Tests/Persistence/Repositories/MemberTypeRepositoryTest.cs b/src/Umbraco.Tests/Persistence/Repositories/MemberTypeRepositoryTest.cs index b045aac137..9f9ff91842 100644 --- a/src/Umbraco.Tests/Persistence/Repositories/MemberTypeRepositoryTest.cs +++ b/src/Umbraco.Tests/Persistence/Repositories/MemberTypeRepositoryTest.cs @@ -38,7 +38,7 @@ namespace Umbraco.Tests.Persistence.Repositories [Test] public void Can_Persist_Member_Type() { - var provider = new PetaPocoUnitOfWorkProvider(Logger); + var provider = new NPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); using (var repository = CreateRepository(unitOfWork)) { @@ -62,7 +62,7 @@ namespace Umbraco.Tests.Persistence.Repositories [Test] public void Cannot_Persist_Member_Type_Without_Alias() { - var provider = new PetaPocoUnitOfWorkProvider(Logger); + var provider = new NPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); using (var repository = CreateRepository(unitOfWork)) { @@ -77,7 +77,7 @@ namespace Umbraco.Tests.Persistence.Repositories [Test] public void Can_Get_All_Member_Types() { - var provider = new PetaPocoUnitOfWorkProvider(Logger); + var provider = new NPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); using (var repository = CreateRepository(unitOfWork)) { @@ -101,7 +101,7 @@ namespace Umbraco.Tests.Persistence.Repositories [Test] public void Can_Get_All_Member_Types_By_Guid_Ids() { - var provider = new PetaPocoUnitOfWorkProvider(Logger); + var provider = new NPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); using (var repository = CreateRepository(unitOfWork)) { @@ -125,7 +125,7 @@ namespace Umbraco.Tests.Persistence.Repositories [Test] public void Can_Get_Member_Types_By_Guid_Id() { - var provider = new PetaPocoUnitOfWorkProvider(Logger); + var provider = new NPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); using (var repository = CreateRepository(unitOfWork)) { @@ -152,7 +152,7 @@ namespace Umbraco.Tests.Persistence.Repositories [Test] public void Can_Get_All_Members_When_No_Properties_Assigned() { - var provider = new PetaPocoUnitOfWorkProvider(Logger); + var provider = new NPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); using (var repository = CreateRepository(unitOfWork)) { @@ -179,7 +179,7 @@ namespace Umbraco.Tests.Persistence.Repositories [Test] public void Can_Get_Member_Type_By_Id() { - var provider = new PetaPocoUnitOfWorkProvider(Logger); + var provider = new NPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); using (var repository = CreateRepository(unitOfWork)) { @@ -194,7 +194,7 @@ namespace Umbraco.Tests.Persistence.Repositories [Test] public void Can_Get_Member_Type_By_Guid_Id() { - var provider = new PetaPocoUnitOfWorkProvider(Logger); + var provider = new NPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); using (var repository = CreateRepository(unitOfWork)) { @@ -209,7 +209,7 @@ namespace Umbraco.Tests.Persistence.Repositories [Test] public void Built_In_Member_Type_Properties_Are_Automatically_Added_When_Creating() { - var provider = new PetaPocoUnitOfWorkProvider(Logger); + var provider = new NPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); using (var repository = CreateRepository(unitOfWork)) { @@ -229,7 +229,7 @@ namespace Umbraco.Tests.Persistence.Repositories [Test] public void Built_In_Member_Type_Properties_Are_Not_Reused_For_Different_Member_Types() { - var provider = new PetaPocoUnitOfWorkProvider(Logger); + var provider = new NPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); using (var repository = CreateRepository(unitOfWork)) { @@ -250,7 +250,7 @@ namespace Umbraco.Tests.Persistence.Repositories public void Can_Delete_MemberType() { // Arrange - var provider = new PetaPocoUnitOfWorkProvider(Logger); + var provider = new NPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); using (var repository = CreateRepository(unitOfWork)) { diff --git a/src/Umbraco.Tests/Persistence/Repositories/NotificationsRepositoryTest.cs b/src/Umbraco.Tests/Persistence/Repositories/NotificationsRepositoryTest.cs index 4d28e909ca..071a419477 100644 --- a/src/Umbraco.Tests/Persistence/Repositories/NotificationsRepositoryTest.cs +++ b/src/Umbraco.Tests/Persistence/Repositories/NotificationsRepositoryTest.cs @@ -20,7 +20,7 @@ namespace Umbraco.Tests.Persistence.Repositories [Test] public void CreateNotification() { - var provider = new PetaPocoUnitOfWorkProvider(Logger); + var provider = new NPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); var repo = new NotificationsRepository(unitOfWork, SqlSyntax); @@ -40,7 +40,7 @@ namespace Umbraco.Tests.Persistence.Repositories [Test] public void GetUserNotifications() { - var provider = new PetaPocoUnitOfWorkProvider(Logger); + var provider = new NPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); var repo = new NotificationsRepository(unitOfWork, SqlSyntax); @@ -66,7 +66,7 @@ namespace Umbraco.Tests.Persistence.Repositories [Test] public void GetEntityNotifications() { - var provider = new PetaPocoUnitOfWorkProvider(Logger); + var provider = new NPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); var repo = new NotificationsRepository(unitOfWork, SqlSyntax); @@ -93,7 +93,7 @@ namespace Umbraco.Tests.Persistence.Repositories [Test] public void Delete_By_Entity() { - var provider = new PetaPocoUnitOfWorkProvider(Logger); + var provider = new NPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); var repo = new NotificationsRepository(unitOfWork, SqlSyntax); @@ -120,7 +120,7 @@ namespace Umbraco.Tests.Persistence.Repositories [Test] public void Delete_By_User() { - var provider = new PetaPocoUnitOfWorkProvider(Logger); + var provider = new NPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); var repo = new NotificationsRepository(unitOfWork, SqlSyntax); diff --git a/src/Umbraco.Tests/Persistence/Repositories/PublicAccessRepositoryTest.cs b/src/Umbraco.Tests/Persistence/Repositories/PublicAccessRepositoryTest.cs index db3dd297ff..1115751688 100644 --- a/src/Umbraco.Tests/Persistence/Repositories/PublicAccessRepositoryTest.cs +++ b/src/Umbraco.Tests/Persistence/Repositories/PublicAccessRepositoryTest.cs @@ -25,7 +25,7 @@ namespace Umbraco.Tests.Persistence.Repositories { var content = CreateTestData(3).ToArray(); - var provider = new PetaPocoUnitOfWorkProvider(Logger); + var provider = new NPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); using (var repo = new PublicAccessRepository(unitOfWork, CacheHelper, Logger, SqlSyntax, MappingResolver)) { @@ -54,8 +54,9 @@ namespace Umbraco.Tests.Persistence.Repositories { var content = CreateTestData(3).ToArray(); - var provider = new PetaPocoUnitOfWorkProvider(Logger); + var provider = new NPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); + unitOfWork.Database.EnableSqlTrace = true; using (var repo = new PublicAccessRepository(unitOfWork, CacheHelper, Logger, SqlSyntax, MappingResolver)) { var entry = new PublicAccessEntry(content[0], content[1], content[2], new[] @@ -87,12 +88,57 @@ namespace Umbraco.Tests.Persistence.Repositories } } + [Test] + public void Can_Add2() + { + var content = CreateTestData(3).ToArray(); + + var provider = new NPocoUnitOfWorkProvider(Logger); + var unitOfWork = provider.GetUnitOfWork(); + unitOfWork.Database.EnableSqlTrace = true; + using (var repo = new PublicAccessRepository(unitOfWork, CacheHelper, Logger, SqlSyntax, MappingResolver)) + { + var entry = new PublicAccessEntry(content[0], content[1], content[2], new[] + { + new PublicAccessRule + { + RuleValue = "test", + RuleType = "RoleName" + }, + new PublicAccessRule + { + RuleValue = "test2", + RuleType = "RoleName2" + }, + }); + repo.AddOrUpdate(entry); + unitOfWork.Commit(); + + var found = repo.GetAll().ToArray(); + + Assert.AreEqual(1, found.Length); + Assert.AreEqual(content[0].Id, found[0].ProtectedNodeId); + Assert.AreEqual(content[1].Id, found[0].LoginNodeId); + Assert.AreEqual(content[2].Id, found[0].NoAccessNodeId); + Assert.IsTrue(found[0].HasIdentity); + Assert.AreNotEqual(default(DateTime), found[0].CreateDate); + Assert.AreNotEqual(default(DateTime), found[0].UpdateDate); + Assert.AreEqual(2, found[0].Rules.Count()); + Assert.AreEqual("test", found[0].Rules.First().RuleValue); + Assert.AreEqual("RoleName", found[0].Rules.First().RuleType); + Assert.AreNotEqual(default(DateTime), found[0].Rules.First().CreateDate); + Assert.AreNotEqual(default(DateTime), found[0].Rules.First().UpdateDate); + Assert.IsTrue(found[0].Rules.First().HasIdentity); + Assert.AreEqual("test2", found[0].Rules.Skip(1).First().RuleValue); + } + } + [Test] public void Can_Update() { var content = CreateTestData(3).ToArray(); - var provider = new PetaPocoUnitOfWorkProvider(Logger); + var provider = new NPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); using (var repo = new PublicAccessRepository(unitOfWork, CacheHelper, Logger, SqlSyntax, MappingResolver)) { @@ -129,7 +175,7 @@ namespace Umbraco.Tests.Persistence.Repositories { var content = CreateTestData(3).ToArray(); - var provider = new PetaPocoUnitOfWorkProvider(Logger); + var provider = new NPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); using (var repo = new PublicAccessRepository(unitOfWork, CacheHelper, Logger, SqlSyntax, MappingResolver)) { @@ -156,7 +202,7 @@ namespace Umbraco.Tests.Persistence.Repositories { var content = CreateTestData(3).ToArray(); - var provider = new PetaPocoUnitOfWorkProvider(Logger); + var provider = new NPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); using (var repo = new PublicAccessRepository(unitOfWork, CacheHelper, Logger, SqlSyntax, MappingResolver)) { @@ -193,7 +239,7 @@ namespace Umbraco.Tests.Persistence.Repositories { var content = CreateTestData(3).ToArray(); - var provider = new PetaPocoUnitOfWorkProvider(Logger); + var provider = new NPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); using (var repo = new PublicAccessRepository(unitOfWork, CacheHelper, Logger, SqlSyntax, MappingResolver)) { @@ -236,7 +282,7 @@ namespace Umbraco.Tests.Persistence.Repositories private IEnumerable CreateTestData(int count) { - var provider = new PetaPocoUnitOfWorkProvider(Logger); + var provider = new NPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); ContentTypeRepository ctRepo; using (var repo = CreateRepository(unitOfWork, out ctRepo)) diff --git a/src/Umbraco.Tests/Persistence/Repositories/RelationRepositoryTest.cs b/src/Umbraco.Tests/Persistence/Repositories/RelationRepositoryTest.cs index 49f53bef1f..6ed8062a33 100644 --- a/src/Umbraco.Tests/Persistence/Repositories/RelationRepositoryTest.cs +++ b/src/Umbraco.Tests/Persistence/Repositories/RelationRepositoryTest.cs @@ -39,7 +39,7 @@ namespace Umbraco.Tests.Persistence.Repositories public void Can_Perform_Add_On_RelationRepository() { // Arrange - var provider = new PetaPocoUnitOfWorkProvider(Logger); + var provider = new NPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); RelationTypeRepository repositoryType; using (var repository = CreateRepository(unitOfWork, out repositoryType)) @@ -61,7 +61,7 @@ namespace Umbraco.Tests.Persistence.Repositories public void Can_Perform_Update_On_RelationRepository() { // Arrange - var provider = new PetaPocoUnitOfWorkProvider(Logger); + var provider = new NPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); RelationTypeRepository repositoryType; using (var repository = CreateRepository(unitOfWork, out repositoryType)) @@ -86,7 +86,7 @@ namespace Umbraco.Tests.Persistence.Repositories public void Can_Perform_Delete_On_RelationRepository() { // Arrange - var provider = new PetaPocoUnitOfWorkProvider(Logger); + var provider = new NPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); RelationTypeRepository repositoryType; using (var repository = CreateRepository(unitOfWork, out repositoryType)) @@ -108,7 +108,7 @@ namespace Umbraco.Tests.Persistence.Repositories public void Can_Perform_Get_On_RelationRepository() { // Arrange - var provider = new PetaPocoUnitOfWorkProvider(Logger); + var provider = new NPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); RelationTypeRepository repositoryType; using (var repository = CreateRepository(unitOfWork, out repositoryType)) @@ -130,7 +130,7 @@ namespace Umbraco.Tests.Persistence.Repositories public void Can_Perform_GetAll_On_RelationRepository() { // Arrange - var provider = new PetaPocoUnitOfWorkProvider(Logger); + var provider = new NPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); RelationTypeRepository repositoryType; using (var repository = CreateRepository(unitOfWork, out repositoryType)) @@ -151,7 +151,7 @@ namespace Umbraco.Tests.Persistence.Repositories public void Can_Perform_GetAll_With_Params_On_RelationRepository() { // Arrange - var provider = new PetaPocoUnitOfWorkProvider(Logger); + var provider = new NPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); RelationTypeRepository repositoryType; using (var repository = CreateRepository(unitOfWork, out repositoryType)) @@ -172,7 +172,7 @@ namespace Umbraco.Tests.Persistence.Repositories public void Can_Perform_Exists_On_RelationRepository() { // Arrange - var provider = new PetaPocoUnitOfWorkProvider(Logger); + var provider = new NPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); RelationTypeRepository repositoryType; using (var repository = CreateRepository(unitOfWork, out repositoryType)) @@ -192,7 +192,7 @@ namespace Umbraco.Tests.Persistence.Repositories public void Can_Perform_Count_On_RelationRepository() { // Arrange - var provider = new PetaPocoUnitOfWorkProvider(Logger); + var provider = new NPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); RelationTypeRepository repositoryType; using (var repository = CreateRepository(unitOfWork, out repositoryType)) @@ -211,7 +211,7 @@ namespace Umbraco.Tests.Persistence.Repositories public void Can_Perform_GetByQuery_On_RelationRepository() { // Arrange - var provider = new PetaPocoUnitOfWorkProvider(Logger); + var provider = new NPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); RelationTypeRepository repositoryType; using (var repository = CreateRepository(unitOfWork, out repositoryType)) @@ -233,7 +233,7 @@ namespace Umbraco.Tests.Persistence.Repositories public void Can_Delete_Content_And_Verify_Relation_Is_Removed() { // Arrange - var provider = new PetaPocoUnitOfWorkProvider(Logger); + var provider = new NPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); RelationTypeRepository repositoryType; using (var repository = CreateRepository(unitOfWork, out repositoryType)) @@ -263,7 +263,7 @@ namespace Umbraco.Tests.Persistence.Repositories var relateContent = new RelationType(new Guid(Constants.ObjectTypes.Document), new Guid("C66BA18E-EAF3-4CFF-8A22-41B16D66A972"), "relateContentOnCopy") { IsBidirectional = true, Name = "Relate Content on Copy" }; var relateContentType = new RelationType(new Guid(Constants.ObjectTypes.DocumentType), new Guid("A2CB7800-F571-4787-9638-BC48539A0EFB"), "relateContentTypeOnCopy") { IsBidirectional = true, Name = "Relate ContentType on Copy" }; - var provider = new PetaPocoUnitOfWorkProvider(Logger); + var provider = new NPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); var relationTypeRepository = new RelationTypeRepository(unitOfWork, CacheHelper.CreateDisabledCacheHelper(), Mock.Of(), SqlSyntax, MappingResolver); var relationRepository = new RelationRepository(unitOfWork, CacheHelper.CreateDisabledCacheHelper(), Mock.Of(), SqlSyntax, relationTypeRepository, MappingResolver); diff --git a/src/Umbraco.Tests/Persistence/Repositories/RelationTypeRepositoryTest.cs b/src/Umbraco.Tests/Persistence/Repositories/RelationTypeRepositoryTest.cs index cd4263df03..34817131f1 100644 --- a/src/Umbraco.Tests/Persistence/Repositories/RelationTypeRepositoryTest.cs +++ b/src/Umbraco.Tests/Persistence/Repositories/RelationTypeRepositoryTest.cs @@ -37,7 +37,7 @@ namespace Umbraco.Tests.Persistence.Repositories public void Can_Perform_Add_On_RelationTypeRepository() { // Arrange - var provider = new PetaPocoUnitOfWorkProvider(Logger); + var provider = new NPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); using (var repository = CreateRepository(unitOfWork)) { @@ -60,7 +60,7 @@ namespace Umbraco.Tests.Persistence.Repositories public void Can_Perform_Update_On_RelationTypeRepository() { // Arrange - var provider = new PetaPocoUnitOfWorkProvider(Logger); + var provider = new NPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); using (var repository = CreateRepository(unitOfWork)) { @@ -86,7 +86,7 @@ namespace Umbraco.Tests.Persistence.Repositories public void Can_Perform_Delete_On_RelationTypeRepository() { // Arrange - var provider = new PetaPocoUnitOfWorkProvider(Logger); + var provider = new NPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); using (var repository = CreateRepository(unitOfWork)) { @@ -107,7 +107,7 @@ namespace Umbraco.Tests.Persistence.Repositories public void Can_Perform_Get_On_RelationTypeRepository() { // Arrange - var provider = new PetaPocoUnitOfWorkProvider(Logger); + var provider = new NPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); using (var repository = CreateRepository(unitOfWork)) { @@ -127,7 +127,7 @@ namespace Umbraco.Tests.Persistence.Repositories public void Can_Perform_GetAll_On_RelationTypeRepository() { // Arrange - var provider = new PetaPocoUnitOfWorkProvider(Logger); + var provider = new NPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); using (var repository = CreateRepository(unitOfWork)) { @@ -147,7 +147,7 @@ namespace Umbraco.Tests.Persistence.Repositories public void Can_Perform_GetAll_With_Params_On_RelationTypeRepository() { // Arrange - var provider = new PetaPocoUnitOfWorkProvider(Logger); + var provider = new NPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); using (var repository = CreateRepository(unitOfWork)) { @@ -167,7 +167,7 @@ namespace Umbraco.Tests.Persistence.Repositories public void Can_Perform_Exists_On_RelationTypeRepository() { // Arrange - var provider = new PetaPocoUnitOfWorkProvider(Logger); + var provider = new NPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); using (var repository = CreateRepository(unitOfWork)) { @@ -186,7 +186,7 @@ namespace Umbraco.Tests.Persistence.Repositories public void Can_Perform_Count_On_RelationTypeRepository() { // Arrange - var provider = new PetaPocoUnitOfWorkProvider(Logger); + var provider = new NPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); using (var repository = CreateRepository(unitOfWork)) { @@ -204,7 +204,7 @@ namespace Umbraco.Tests.Persistence.Repositories public void Can_Perform_GetByQuery_On_RelationTypeRepository() { // Arrange - var provider = new PetaPocoUnitOfWorkProvider(Logger); + var provider = new NPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); using (var repository = CreateRepository(unitOfWork)) { @@ -233,7 +233,7 @@ namespace Umbraco.Tests.Persistence.Repositories var relateContent = new RelationType(new Guid(Constants.ObjectTypes.Document), new Guid("C66BA18E-EAF3-4CFF-8A22-41B16D66A972"), "relateContentOnCopy") { IsBidirectional = true, Name = "Relate Content on Copy" }; var relateContentType = new RelationType(new Guid(Constants.ObjectTypes.DocumentType), new Guid("A2CB7800-F571-4787-9638-BC48539A0EFB"), "relateContentTypeOnCopy") { IsBidirectional = true, Name = "Relate ContentType on Copy" }; - var provider = new PetaPocoUnitOfWorkProvider(Logger); + var provider = new NPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); var repository = new RelationTypeRepository(unitOfWork, CacheHelper.CreateDisabledCacheHelper(), Mock.Of(), SqlSyntax, MappingResolver); diff --git a/src/Umbraco.Tests/Persistence/Repositories/ServerRegistrationRepositoryTest.cs b/src/Umbraco.Tests/Persistence/Repositories/ServerRegistrationRepositoryTest.cs index cf5b0e9a3e..8ddb8d45f1 100644 --- a/src/Umbraco.Tests/Persistence/Repositories/ServerRegistrationRepositoryTest.cs +++ b/src/Umbraco.Tests/Persistence/Repositories/ServerRegistrationRepositoryTest.cs @@ -39,7 +39,7 @@ namespace Umbraco.Tests.Persistence.Repositories public void Cannot_Add_Duplicate_Server_Identities() { // Arrange - var provider = new PetaPocoUnitOfWorkProvider(Logger); + var provider = new NPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); // Act @@ -57,7 +57,7 @@ namespace Umbraco.Tests.Persistence.Repositories public void Cannot_Update_To_Duplicate_Server_Identities() { // Arrange - var provider = new PetaPocoUnitOfWorkProvider(Logger); + var provider = new NPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); // Act @@ -75,14 +75,14 @@ namespace Umbraco.Tests.Persistence.Repositories public void Can_Instantiate_Repository() { // Arrange - var provider = new PetaPocoUnitOfWorkProvider(Logger); + var provider = new NPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); // Act using (var repository = CreateRepository(unitOfWork)) { // Assert - Assert.That(repository, Is.Not.Null); + Assert.That(repository, Is.Not.Null); } } @@ -90,7 +90,7 @@ namespace Umbraco.Tests.Persistence.Repositories public void Can_Perform_Get_On_Repository() { // Arrange - var provider = new PetaPocoUnitOfWorkProvider(Logger); + var provider = new NPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); using (var repository = CreateRepository(unitOfWork)) { @@ -100,17 +100,17 @@ namespace Umbraco.Tests.Persistence.Repositories // Assert Assert.That(server, Is.Not.Null); Assert.That(server.HasIdentity, Is.True); - Assert.That(server.ServerAddress, Is.EqualTo("http://localhost")); + Assert.That(server.ServerAddress, Is.EqualTo("http://localhost")); } - + } [Test] public void Can_Perform_GetAll_On_Repository() { // Arrange - var provider = new PetaPocoUnitOfWorkProvider(Logger); + var provider = new NPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); using (var repository = CreateRepository(unitOfWork)) { @@ -118,9 +118,9 @@ namespace Umbraco.Tests.Persistence.Repositories var servers = repository.GetAll(); // Assert - Assert.That(servers.Count(), Is.EqualTo(3)); + Assert.That(servers.Count(), Is.EqualTo(3)); } - + } // queries are not supported due to in-memory caching @@ -129,7 +129,7 @@ namespace Umbraco.Tests.Persistence.Repositories //public void Can_Perform_GetByQuery_On_Repository() //{ // // Arrange - // var provider = new PetaPocoUnitOfWorkProvider(Logger); + // var provider = new NPocoUnitOfWorkProvider(Logger); // var unitOfWork = provider.GetUnitOfWork(); // using (var repository = CreateRepository(unitOfWork)) // { @@ -138,7 +138,7 @@ namespace Umbraco.Tests.Persistence.Repositories // var result = repository.GetByQuery(query); // // Assert - // Assert.AreEqual(1, result.Count()); + // Assert.AreEqual(1, result.Count()); // } //} @@ -146,7 +146,7 @@ namespace Umbraco.Tests.Persistence.Repositories //public void Can_Perform_Count_On_Repository() //{ // // Arrange - // var provider = new PetaPocoUnitOfWorkProvider(Logger); + // var provider = new NPocoUnitOfWorkProvider(Logger); // var unitOfWork = provider.GetUnitOfWork(); // using (var repository = CreateRepository(unitOfWork)) // { @@ -155,7 +155,7 @@ namespace Umbraco.Tests.Persistence.Repositories // int count = repository.Count(query); // // Assert - // Assert.That(count, Is.EqualTo(2)); + // Assert.That(count, Is.EqualTo(2)); // } //} @@ -163,7 +163,7 @@ namespace Umbraco.Tests.Persistence.Repositories public void Can_Perform_Add_On_Repository() { // Arrange - var provider = new PetaPocoUnitOfWorkProvider(Logger); + var provider = new NPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); using (var repository = CreateRepository(unitOfWork)) { @@ -174,15 +174,15 @@ namespace Umbraco.Tests.Persistence.Repositories // Assert Assert.That(server.HasIdentity, Is.True); - Assert.That(server.Id, Is.EqualTo(4));//With 3 existing entries the Id should be 4 - } + Assert.That(server.Id, Is.EqualTo(4));//With 3 existing entries the Id should be 4 + } } [Test] public void Can_Perform_Update_On_Repository() { // Arrange - var provider = new PetaPocoUnitOfWorkProvider(Logger); + var provider = new NPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); using (var repository = CreateRepository(unitOfWork)) { @@ -199,15 +199,15 @@ namespace Umbraco.Tests.Persistence.Repositories // Assert Assert.That(serverUpdated, Is.Not.Null); Assert.That(serverUpdated.ServerAddress, Is.EqualTo("https://umbraco.com")); - Assert.That(serverUpdated.IsActive, Is.EqualTo(true)); - } + Assert.That(serverUpdated.IsActive, Is.EqualTo(true)); + } } [Test] public void Can_Perform_Delete_On_Repository() { // Arrange - var provider = new PetaPocoUnitOfWorkProvider(Logger); + var provider = new NPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); using (var repository = CreateRepository(unitOfWork)) { @@ -220,15 +220,15 @@ namespace Umbraco.Tests.Persistence.Repositories var exists = repository.Exists(3); // Assert - Assert.That(exists, Is.False); - } + Assert.That(exists, Is.False); + } } [Test] public void Can_Perform_Exists_On_Repository() { // Arrange - var provider = new PetaPocoUnitOfWorkProvider(Logger); + var provider = new NPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); using (var repository = CreateRepository(unitOfWork)) { @@ -238,7 +238,7 @@ namespace Umbraco.Tests.Persistence.Repositories // Assert Assert.That(exists, Is.True); - Assert.That(doesntExist, Is.False); + Assert.That(doesntExist, Is.False); } } @@ -250,7 +250,7 @@ namespace Umbraco.Tests.Persistence.Repositories public void CreateTestData() { - var provider = new PetaPocoUnitOfWorkProvider(Logger); + var provider = new NPocoUnitOfWorkProvider(Logger); using (var unitOfWork = provider.GetUnitOfWork()) using (var repository = CreateRepository(unitOfWork)) { diff --git a/src/Umbraco.Tests/Persistence/Repositories/TagRepositoryTest.cs b/src/Umbraco.Tests/Persistence/Repositories/TagRepositoryTest.cs index a71191236b..011bf49a21 100644 --- a/src/Umbraco.Tests/Persistence/Repositories/TagRepositoryTest.cs +++ b/src/Umbraco.Tests/Persistence/Repositories/TagRepositoryTest.cs @@ -43,7 +43,7 @@ namespace Umbraco.Tests.Persistence.Repositories public void Can_Perform_Add_On_Repository() { // Arrange - var provider = new PetaPocoUnitOfWorkProvider(Logger); + var provider = new NPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); using (var repository = CreateRepository(unitOfWork)) { @@ -66,7 +66,7 @@ namespace Umbraco.Tests.Persistence.Repositories public void Can_Perform_Multiple_Adds_On_Repository() { // Arrange - var provider = new PetaPocoUnitOfWorkProvider(Logger); + var provider = new NPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); using (var repository = CreateRepository(unitOfWork)) { @@ -99,7 +99,7 @@ namespace Umbraco.Tests.Persistence.Repositories [Test] public void Can_Create_Tag_Relations() { - var provider = new PetaPocoUnitOfWorkProvider(Logger); + var provider = new NPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); ContentTypeRepository contentTypeRepository; using (var contentRepository = CreateContentRepository(unitOfWork, out contentTypeRepository)) @@ -131,7 +131,7 @@ namespace Umbraco.Tests.Persistence.Repositories [Test] public void Can_Append_Tag_Relations() { - var provider = new PetaPocoUnitOfWorkProvider(Logger); + var provider = new NPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); ContentTypeRepository contentTypeRepository; using (var contentRepository = CreateContentRepository(unitOfWork, out contentTypeRepository)) @@ -172,7 +172,7 @@ namespace Umbraco.Tests.Persistence.Repositories [Test] public void Can_Replace_Tag_Relations() { - var provider = new PetaPocoUnitOfWorkProvider(Logger); + var provider = new NPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); ContentTypeRepository contentTypeRepository; using (var contentRepository = CreateContentRepository(unitOfWork, out contentTypeRepository)) @@ -216,7 +216,7 @@ namespace Umbraco.Tests.Persistence.Repositories [Test] public void Can_Merge_Tag_Relations() { - var provider = new PetaPocoUnitOfWorkProvider(Logger); + var provider = new NPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); ContentTypeRepository contentTypeRepository; using (var contentRepository = CreateContentRepository(unitOfWork, out contentTypeRepository)) @@ -258,7 +258,7 @@ namespace Umbraco.Tests.Persistence.Repositories [Test] public void Can_Clear_Tag_Relations() { - var provider = new PetaPocoUnitOfWorkProvider(Logger); + var provider = new NPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); ContentTypeRepository contentTypeRepository; using (var contentRepository = CreateContentRepository(unitOfWork, out contentTypeRepository)) @@ -296,7 +296,7 @@ namespace Umbraco.Tests.Persistence.Repositories [Test] public void Can_Remove_Specific_Tags_From_Property() { - var provider = new PetaPocoUnitOfWorkProvider(Logger); + var provider = new NPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); ContentTypeRepository contentTypeRepository; using (var contentRepository = CreateContentRepository(unitOfWork, out contentTypeRepository)) @@ -342,7 +342,7 @@ namespace Umbraco.Tests.Persistence.Repositories [Test] public void Can_Get_Tags_For_Content_By_Id() { - var provider = new PetaPocoUnitOfWorkProvider(Logger); + var provider = new NPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); ContentTypeRepository contentTypeRepository; using (var contentRepository = CreateContentRepository(unitOfWork, out contentTypeRepository)) @@ -389,7 +389,7 @@ namespace Umbraco.Tests.Persistence.Repositories [Test] public void Can_Get_Tags_For_Content_By_Key() { - var provider = new PetaPocoUnitOfWorkProvider(Logger); + var provider = new NPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); ContentTypeRepository contentTypeRepository; using (var contentRepository = CreateContentRepository(unitOfWork, out contentTypeRepository)) @@ -436,7 +436,7 @@ namespace Umbraco.Tests.Persistence.Repositories [Test] public void Can_Get_All() { - var provider = new PetaPocoUnitOfWorkProvider(Logger); + var provider = new NPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); ContentTypeRepository contentTypeRepository; using (var contentRepository = CreateContentRepository(unitOfWork, out contentTypeRepository)) @@ -473,7 +473,7 @@ namespace Umbraco.Tests.Persistence.Repositories [Test] public void Can_Get_All_With_Ids() { - var provider = new PetaPocoUnitOfWorkProvider(Logger); + var provider = new NPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); ContentTypeRepository contentTypeRepository; using (var contentRepository = CreateContentRepository(unitOfWork, out contentTypeRepository)) @@ -515,7 +515,7 @@ namespace Umbraco.Tests.Persistence.Repositories [Test] public void Can_Get_Tags_For_Content_For_Group() { - var provider = new PetaPocoUnitOfWorkProvider(Logger); + var provider = new NPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); ContentTypeRepository contentTypeRepository; using (var contentRepository = CreateContentRepository(unitOfWork, out contentTypeRepository)) @@ -561,7 +561,7 @@ namespace Umbraco.Tests.Persistence.Repositories [Test] public void Can_Get_Tags_For_Property_By_Id() { - var provider = new PetaPocoUnitOfWorkProvider(Logger); + var provider = new NPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); ContentTypeRepository contentTypeRepository; using (var contentRepository = CreateContentRepository(unitOfWork, out contentTypeRepository)) @@ -608,7 +608,7 @@ namespace Umbraco.Tests.Persistence.Repositories [Test] public void Can_Get_Tags_For_Property_By_Key() { - var provider = new PetaPocoUnitOfWorkProvider(Logger); + var provider = new NPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); ContentTypeRepository contentTypeRepository; using (var contentRepository = CreateContentRepository(unitOfWork, out contentTypeRepository)) @@ -655,7 +655,7 @@ namespace Umbraco.Tests.Persistence.Repositories [Test] public void Can_Get_Tags_For_Property_For_Group() { - var provider = new PetaPocoUnitOfWorkProvider(Logger); + var provider = new NPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); ContentTypeRepository contentTypeRepository; using (var contentRepository = CreateContentRepository(unitOfWork, out contentTypeRepository)) @@ -704,7 +704,7 @@ namespace Umbraco.Tests.Persistence.Repositories [Test] public void Can_Get_Tags_For_Entity_Type() { - var provider = new PetaPocoUnitOfWorkProvider(Logger); + var provider = new NPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); MediaTypeRepository mediaTypeRepository; ContentTypeRepository contentTypeRepository; @@ -766,7 +766,7 @@ namespace Umbraco.Tests.Persistence.Repositories [Test] public void Can_Get_Tags_For_Entity_Type_For_Group() { - var provider = new PetaPocoUnitOfWorkProvider(Logger); + var provider = new NPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); MediaTypeRepository mediaTypeRepository; ContentTypeRepository contentTypeRepository; @@ -823,7 +823,7 @@ namespace Umbraco.Tests.Persistence.Repositories [Test] public void Cascade_Deletes_Tag_Relations() { - var provider = new PetaPocoUnitOfWorkProvider(Logger); + var provider = new NPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); ContentTypeRepository contentTypeRepository; using (var contentRepository = CreateContentRepository(unitOfWork, out contentTypeRepository)) @@ -864,7 +864,7 @@ namespace Umbraco.Tests.Persistence.Repositories [Test] public void Can_Get_Tagged_Entities_For_Tag_Group() { - var provider = new PetaPocoUnitOfWorkProvider(Logger); + var provider = new NPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); MediaTypeRepository mediaTypeRepository; ContentTypeRepository contentTypeRepository; @@ -951,7 +951,7 @@ namespace Umbraco.Tests.Persistence.Repositories [Test] public void Can_Get_Tagged_Entities_For_Tag() { - var provider = new PetaPocoUnitOfWorkProvider(Logger); + var provider = new NPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); MediaTypeRepository mediaTypeRepository; ContentTypeRepository contentTypeRepository; diff --git a/src/Umbraco.Tests/Persistence/Repositories/TaskRepositoryTest.cs b/src/Umbraco.Tests/Persistence/Repositories/TaskRepositoryTest.cs index 87138d15bf..33c961fcab 100644 --- a/src/Umbraco.Tests/Persistence/Repositories/TaskRepositoryTest.cs +++ b/src/Umbraco.Tests/Persistence/Repositories/TaskRepositoryTest.cs @@ -16,7 +16,7 @@ namespace Umbraco.Tests.Persistence.Repositories [Test] public void Can_Delete() { - var provider = new PetaPocoUnitOfWorkProvider(Logger); + var provider = new NPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); using (var repo = new TaskRepository(unitOfWork, CacheHelper, Logger, SqlSyntax, MappingResolver)) { @@ -43,7 +43,7 @@ namespace Umbraco.Tests.Persistence.Repositories [Test] public void Can_Add() { - var provider = new PetaPocoUnitOfWorkProvider(Logger); + var provider = new NPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); using (var repo = new TaskRepository(unitOfWork, CacheHelper, Logger, SqlSyntax, MappingResolver)) { @@ -75,7 +75,7 @@ namespace Umbraco.Tests.Persistence.Repositories [Test] public void Can_Update() { - var provider = new PetaPocoUnitOfWorkProvider(Logger); + var provider = new NPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); using (var repo = new TaskRepository(unitOfWork, CacheHelper, Logger, SqlSyntax, MappingResolver)) { @@ -111,7 +111,7 @@ namespace Umbraco.Tests.Persistence.Repositories [Test] public void Get_By_Id() { - var provider = new PetaPocoUnitOfWorkProvider(Logger); + var provider = new NPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); using (var repo = new TaskRepository(unitOfWork, CacheHelper, Logger, SqlSyntax, MappingResolver)) { @@ -139,7 +139,7 @@ namespace Umbraco.Tests.Persistence.Repositories { CreateTestData(false, 20); - var provider = new PetaPocoUnitOfWorkProvider(Logger); + var provider = new NPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); using (var repo = new TaskRepository(unitOfWork, CacheHelper, Logger, SqlSyntax, MappingResolver)) { @@ -154,7 +154,7 @@ namespace Umbraco.Tests.Persistence.Repositories CreateTestData(false, 10); CreateTestData(true, 5); - var provider = new PetaPocoUnitOfWorkProvider(Logger); + var provider = new NPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); using (var repo = new TaskRepository(unitOfWork, CacheHelper, Logger, SqlSyntax, MappingResolver)) { @@ -169,7 +169,7 @@ namespace Umbraco.Tests.Persistence.Repositories CreateTestData(false, 10, -20); CreateTestData(false, 5, -21); - var provider = new PetaPocoUnitOfWorkProvider(Logger); + var provider = new NPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); using (var repo = new TaskRepository(unitOfWork, CacheHelper, Logger, SqlSyntax, MappingResolver)) { @@ -184,7 +184,7 @@ namespace Umbraco.Tests.Persistence.Repositories CreateTestData(false, 10); CreateTestData(true, 5); - var provider = new PetaPocoUnitOfWorkProvider(Logger); + var provider = new NPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); using (var repo = new TaskRepository(unitOfWork, CacheHelper, Logger, SqlSyntax, MappingResolver)) { @@ -195,7 +195,7 @@ namespace Umbraco.Tests.Persistence.Repositories private void CreateTestData(bool closed, int count, int entityId = -1) { - var provider = new PetaPocoUnitOfWorkProvider(Logger); + var provider = new NPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); using (var repo = new TaskRepository(unitOfWork, CacheHelper, Logger, SqlSyntax, MappingResolver)) { diff --git a/src/Umbraco.Tests/Persistence/Repositories/TaskTypeRepositoryTest.cs b/src/Umbraco.Tests/Persistence/Repositories/TaskTypeRepositoryTest.cs index bceb8d54d7..23f2957f16 100644 --- a/src/Umbraco.Tests/Persistence/Repositories/TaskTypeRepositoryTest.cs +++ b/src/Umbraco.Tests/Persistence/Repositories/TaskTypeRepositoryTest.cs @@ -15,7 +15,7 @@ namespace Umbraco.Tests.Persistence.Repositories [Test] public void Can_Delete() { - var provider = new PetaPocoUnitOfWorkProvider(Logger); + var provider = new NPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); var taskType = new TaskType("asdfasdf"); using (var repo = new TaskRepository(unitOfWork, CacheHelper, Logger, SqlSyntax, MappingResolver)) diff --git a/src/Umbraco.Tests/Persistence/Repositories/TemplateRepositoryTest.cs b/src/Umbraco.Tests/Persistence/Repositories/TemplateRepositoryTest.cs index 931425ae7f..9b726e2184 100644 --- a/src/Umbraco.Tests/Persistence/Repositories/TemplateRepositoryTest.cs +++ b/src/Umbraco.Tests/Persistence/Repositories/TemplateRepositoryTest.cs @@ -47,7 +47,7 @@ namespace Umbraco.Tests.Persistence.Repositories public void Can_Instantiate_Repository() { // Arrange - var provider = new PetaPocoUnitOfWorkProvider(Logger); + var provider = new NPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); // Act @@ -64,7 +64,7 @@ namespace Umbraco.Tests.Persistence.Repositories public void Can_Perform_Add_MasterPage_Detect_Content() { // Arrange - var provider = new PetaPocoUnitOfWorkProvider(Logger); + var provider = new NPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); using (var repository = CreateRepository(unitOfWork)) { @@ -87,7 +87,7 @@ namespace Umbraco.Tests.Persistence.Repositories public void Can_Perform_Add_MasterPage_With_Default_Content() { // Arrange - var provider = new PetaPocoUnitOfWorkProvider(Logger); + var provider = new NPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); using (var repository = CreateRepository(unitOfWork, Mock.Of(x => x.DefaultRenderingEngine == RenderingEngine.WebForms))) { @@ -113,7 +113,7 @@ namespace Umbraco.Tests.Persistence.Repositories public void Can_Perform_Add_MasterPage_With_Default_Content_With_Parent() { // Arrange - var provider = new PetaPocoUnitOfWorkProvider(Logger); + var provider = new NPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); using (var repository = CreateRepository(unitOfWork, Mock.Of(x => x.DefaultRenderingEngine == RenderingEngine.WebForms))) { @@ -142,7 +142,7 @@ namespace Umbraco.Tests.Persistence.Repositories public void Can_Perform_Add_View() { // Arrange - var provider = new PetaPocoUnitOfWorkProvider(Logger); + var provider = new NPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); using (var repository = CreateRepository(unitOfWork)) { @@ -162,7 +162,7 @@ namespace Umbraco.Tests.Persistence.Repositories public void Can_Perform_Add_View_With_Default_Content() { // Arrange - var provider = new PetaPocoUnitOfWorkProvider(Logger); + var provider = new NPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); using (var repository = CreateRepository(unitOfWork)) { @@ -188,7 +188,7 @@ namespace Umbraco.Tests.Persistence.Repositories public void Can_Perform_Add_View_With_Default_Content_With_Parent() { // Arrange - var provider = new PetaPocoUnitOfWorkProvider(Logger); + var provider = new NPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); using (var repository = CreateRepository(unitOfWork)) { @@ -216,7 +216,7 @@ namespace Umbraco.Tests.Persistence.Repositories public void Can_Perform_Add_Unique_Alias() { // Arrange - var provider = new PetaPocoUnitOfWorkProvider(Logger); + var provider = new NPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); using (var repository = CreateRepository(unitOfWork)) { @@ -245,7 +245,7 @@ namespace Umbraco.Tests.Persistence.Repositories public void Can_Perform_Update_Unique_Alias() { // Arrange - var provider = new PetaPocoUnitOfWorkProvider(Logger); + var provider = new NPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); using (var repository = CreateRepository(unitOfWork)) { @@ -280,7 +280,7 @@ namespace Umbraco.Tests.Persistence.Repositories public void Can_Perform_Update_MasterPage() { // Arrange - var provider = new PetaPocoUnitOfWorkProvider(Logger); + var provider = new NPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); using (var repository = CreateRepository(unitOfWork)) { @@ -310,7 +310,7 @@ namespace Umbraco.Tests.Persistence.Repositories public void Can_Perform_Update_View() { // Arrange - var provider = new PetaPocoUnitOfWorkProvider(Logger); + var provider = new NPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); using (var repository = CreateRepository(unitOfWork)) { @@ -340,7 +340,7 @@ namespace Umbraco.Tests.Persistence.Repositories public void Can_Perform_Delete_MasterPage() { // Arrange - var provider = new PetaPocoUnitOfWorkProvider(Logger); + var provider = new NPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); using (var repository = CreateRepository(unitOfWork)) { @@ -369,7 +369,7 @@ namespace Umbraco.Tests.Persistence.Repositories public void Can_Perform_Delete_View() { // Arrange - var provider = new PetaPocoUnitOfWorkProvider(Logger); + var provider = new NPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); using (var repository = CreateRepository(unitOfWork)) { @@ -398,7 +398,7 @@ namespace Umbraco.Tests.Persistence.Repositories public void Can_Perform_Delete_When_Assigned_To_Doc() { // Arrange - var provider = new PetaPocoUnitOfWorkProvider(Logger); + var provider = new NPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); using (var templateRepository = CreateRepository(unitOfWork)) @@ -443,7 +443,7 @@ namespace Umbraco.Tests.Persistence.Repositories public void Can_Perform_Delete_On_Nested_Templates() { // Arrange - var provider = new PetaPocoUnitOfWorkProvider(Logger); + var provider = new NPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); using (var repository = CreateRepository(unitOfWork)) { @@ -484,7 +484,7 @@ namespace Umbraco.Tests.Persistence.Repositories public void Can_Get_Template_Tree() { // Arrange - var provider = new PetaPocoUnitOfWorkProvider(Logger); + var provider = new NPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); using (var repository = CreateRepository(unitOfWork)) { @@ -510,7 +510,7 @@ namespace Umbraco.Tests.Persistence.Repositories public void Can_Get_All() { // Arrange - var provider = new PetaPocoUnitOfWorkProvider(Logger); + var provider = new NPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); using (var repository = CreateRepository(unitOfWork)) { @@ -537,7 +537,7 @@ namespace Umbraco.Tests.Persistence.Repositories public void Can_Get_Children() { // Arrange - var provider = new PetaPocoUnitOfWorkProvider(Logger); + var provider = new NPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); using (var repository = CreateRepository(unitOfWork)) { @@ -561,7 +561,7 @@ namespace Umbraco.Tests.Persistence.Repositories public void Can_Get_Children_At_Root() { // Arrange - var provider = new PetaPocoUnitOfWorkProvider(Logger); + var provider = new NPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); using (var repository = CreateRepository(unitOfWork)) { @@ -582,7 +582,7 @@ namespace Umbraco.Tests.Persistence.Repositories public void Can_Get_Descendants() { // Arrange - var provider = new PetaPocoUnitOfWorkProvider(Logger); + var provider = new NPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); using (var repository = CreateRepository(unitOfWork)) { @@ -606,7 +606,7 @@ namespace Umbraco.Tests.Persistence.Repositories public void Path_Is_Set_Correctly_On_Creation() { // Arrange - var provider = new PetaPocoUnitOfWorkProvider(Logger); + var provider = new NPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); using (var repository = CreateRepository(unitOfWork)) { @@ -670,7 +670,7 @@ namespace Umbraco.Tests.Persistence.Repositories public void Path_Is_Set_Correctly_On_Update() { // Arrange - var provider = new PetaPocoUnitOfWorkProvider(Logger); + var provider = new NPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); using (var repository = CreateRepository(unitOfWork)) { diff --git a/src/Umbraco.Tests/Persistence/Repositories/UserRepositoryTest.cs b/src/Umbraco.Tests/Persistence/Repositories/UserRepositoryTest.cs index 4569e63959..8d0bbdff77 100644 --- a/src/Umbraco.Tests/Persistence/Repositories/UserRepositoryTest.cs +++ b/src/Umbraco.Tests/Persistence/Repositories/UserRepositoryTest.cs @@ -44,7 +44,7 @@ namespace Umbraco.Tests.Persistence.Repositories public void Can_Perform_Add_On_UserRepository() { // Arrange - var provider = new PetaPocoUnitOfWorkProvider(Logger); + var provider = new NPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); UserTypeRepository userTypeRepository; using (var repository = CreateRepository(unitOfWork, out userTypeRepository)) @@ -65,7 +65,7 @@ namespace Umbraco.Tests.Persistence.Repositories public void Can_Perform_Multiple_Adds_On_UserRepository() { // Arrange - var provider = new PetaPocoUnitOfWorkProvider(Logger); + var provider = new NPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); UserTypeRepository userTypeRepository; using (var repository = CreateRepository(unitOfWork, out userTypeRepository)) @@ -90,7 +90,7 @@ namespace Umbraco.Tests.Persistence.Repositories public void Can_Verify_Fresh_Entity_Is_Not_Dirty() { // Arrange - var provider = new PetaPocoUnitOfWorkProvider(Logger); + var provider = new NPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); UserTypeRepository userTypeRepository; using (var repository = CreateRepository(unitOfWork, out userTypeRepository)) @@ -112,7 +112,7 @@ namespace Umbraco.Tests.Persistence.Repositories public void Can_Perform_Update_On_UserRepository() { // Arrange - var provider = new PetaPocoUnitOfWorkProvider(Logger); + var provider = new NPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); UserTypeRepository userTypeRepository; using (var repository = CreateRepository(unitOfWork, out userTypeRepository)) @@ -162,7 +162,7 @@ namespace Umbraco.Tests.Persistence.Repositories public void Can_Perform_Delete_On_UserRepository() { // Arrange - var provider = new PetaPocoUnitOfWorkProvider(Logger); + var provider = new NPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); UserTypeRepository userTypeRepository; using (var repository = CreateRepository(unitOfWork, out userTypeRepository)) @@ -193,7 +193,7 @@ namespace Umbraco.Tests.Persistence.Repositories //public void Can_Perform_Delete_On_UserRepository_With_Permissions_Assigned() //{ // // Arrange - // var provider = new PetaPocoUnitOfWorkProvider(Logger); + // var provider = new NPocoUnitOfWorkProvider(Logger); // var unitOfWork = provider.GetUnitOfWork(); // UserTypeRepository userTypeRepository; //using (var repository = CreateRepository(unitOfWork, out userTypeRepository)) @@ -223,7 +223,7 @@ namespace Umbraco.Tests.Persistence.Repositories public void Can_Perform_Get_On_UserRepository() { // Arrange - var provider = new PetaPocoUnitOfWorkProvider(Logger); + var provider = new NPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); UserTypeRepository userTypeRepository; using (var repository = CreateRepository(unitOfWork, out userTypeRepository)) @@ -244,7 +244,7 @@ namespace Umbraco.Tests.Persistence.Repositories public void Can_Perform_GetByQuery_On_UserRepository() { // Arrange - var provider = new PetaPocoUnitOfWorkProvider(Logger); + var provider = new NPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); UserTypeRepository userTypeRepository; using (var repository = CreateRepository(unitOfWork, out userTypeRepository)) @@ -264,7 +264,7 @@ namespace Umbraco.Tests.Persistence.Repositories public void Can_Perform_GetAll_By_Param_Ids_On_UserRepository() { // Arrange - var provider = new PetaPocoUnitOfWorkProvider(Logger); + var provider = new NPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); UserTypeRepository userTypeRepository; using (var repository = CreateRepository(unitOfWork, out userTypeRepository)) @@ -285,7 +285,7 @@ namespace Umbraco.Tests.Persistence.Repositories public void Can_Perform_GetAll_On_UserRepository() { // Arrange - var provider = new PetaPocoUnitOfWorkProvider(Logger); + var provider = new NPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); UserTypeRepository userTypeRepository; using (var repository = CreateRepository(unitOfWork, out userTypeRepository)) @@ -306,7 +306,7 @@ namespace Umbraco.Tests.Persistence.Repositories public void Can_Perform_Exists_On_UserRepository() { // Arrange - var provider = new PetaPocoUnitOfWorkProvider(Logger); + var provider = new NPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); UserTypeRepository userTypeRepository; using (var repository = CreateRepository(unitOfWork, out userTypeRepository)) @@ -325,7 +325,7 @@ namespace Umbraco.Tests.Persistence.Repositories public void Can_Perform_Count_On_UserRepository() { // Arrange - var provider = new PetaPocoUnitOfWorkProvider(Logger); + var provider = new NPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); UserTypeRepository userTypeRepository; using (var repository = CreateRepository(unitOfWork, out userTypeRepository)) @@ -345,7 +345,7 @@ namespace Umbraco.Tests.Persistence.Repositories public void Can_Remove_Section_For_User() { // Arrange - var provider = new PetaPocoUnitOfWorkProvider(Logger); + var provider = new NPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); UserTypeRepository userTypeRepository; using (var repository = CreateRepository(unitOfWork, out userTypeRepository)) @@ -380,7 +380,7 @@ namespace Umbraco.Tests.Persistence.Repositories public void Can_Add_Section_For_User() { // Arrange - var provider = new PetaPocoUnitOfWorkProvider(Logger); + var provider = new NPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); UserTypeRepository userTypeRepository; using (var repository = CreateRepository(unitOfWork, out userTypeRepository)) @@ -424,7 +424,7 @@ namespace Umbraco.Tests.Persistence.Repositories public void Can_Update_Section_For_User() { // Arrange - var provider = new PetaPocoUnitOfWorkProvider(Logger); + var provider = new NPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); UserTypeRepository userTypeRepository; using (var repository = CreateRepository(unitOfWork, out userTypeRepository)) @@ -452,7 +452,7 @@ namespace Umbraco.Tests.Persistence.Repositories public void Get_Users_Assigned_To_Section() { // Arrange - var provider = new PetaPocoUnitOfWorkProvider(Logger); + var provider = new NPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); UserTypeRepository userTypeRepository; using (var repository = CreateRepository(unitOfWork, out userTypeRepository)) @@ -469,7 +469,7 @@ namespace Umbraco.Tests.Persistence.Repositories var users = repository.GetUsersAssignedToSection("test"); - // Assert + // Assert Assert.AreEqual(2, users.Count()); var names = users.Select(x => x.Username).ToArray(); Assert.IsTrue(names.Contains("TestUser1")); @@ -481,11 +481,11 @@ namespace Umbraco.Tests.Persistence.Repositories public void Default_User_Permissions_Based_On_User_Type() { // Arrange - var provider = new PetaPocoUnitOfWorkProvider(Logger); + var provider = new NPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); using (var utRepo = new UserTypeRepository(unitOfWork, CacheHelper.CreateDisabledCacheHelper(), Logger, SqlSyntax, MappingResolver)) using (var repository = new UserRepository(unitOfWork, CacheHelper.CreateDisabledCacheHelper(), Logger, SqlSyntax, utRepo, MappingResolver)) - { + { // Act var user1 = MockedUser.CreateUser(CreateAndCommitUserType(), "1", "test", "media"); @@ -532,7 +532,7 @@ namespace Umbraco.Tests.Persistence.Repositories private IUserType CreateAndCommitUserType() { - var provider = new PetaPocoUnitOfWorkProvider(Logger); + var provider = new NPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); using (var repository = new UserTypeRepository(unitOfWork, CacheHelper.CreateDisabledCacheHelper(), Logger, SqlSyntax, MappingResolver)) { diff --git a/src/Umbraco.Tests/Persistence/Repositories/UserTypeRepositoryTest.cs b/src/Umbraco.Tests/Persistence/Repositories/UserTypeRepositoryTest.cs index d3bc64ba4f..012d5c4f0b 100644 --- a/src/Umbraco.Tests/Persistence/Repositories/UserTypeRepositoryTest.cs +++ b/src/Umbraco.Tests/Persistence/Repositories/UserTypeRepositoryTest.cs @@ -39,7 +39,7 @@ namespace Umbraco.Tests.Persistence.Repositories public void Can_Perform_Add_On_UserTypeRepository() { // Arrange - var provider = new PetaPocoUnitOfWorkProvider(Logger); + var provider = new NPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); using (var repository = CreateRepository(unitOfWork)) { @@ -59,7 +59,7 @@ namespace Umbraco.Tests.Persistence.Repositories public void Can_Perform_Multiple_Adds_On_UserTypeRepository() { // Arrange - var provider = new PetaPocoUnitOfWorkProvider(Logger); + var provider = new NPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); using (var repository = CreateRepository(unitOfWork)) { @@ -83,7 +83,7 @@ namespace Umbraco.Tests.Persistence.Repositories public void Can_Verify_Fresh_Entity_Is_Not_Dirty() { // Arrange - var provider = new PetaPocoUnitOfWorkProvider(Logger); + var provider = new NPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); using (var repository = CreateRepository(unitOfWork)) { @@ -104,7 +104,7 @@ namespace Umbraco.Tests.Persistence.Repositories public void Can_Perform_Update_On_UserTypeRepository() { // Arrange - var provider = new PetaPocoUnitOfWorkProvider(Logger); + var provider = new NPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); using (var repository = CreateRepository(unitOfWork)) { @@ -131,7 +131,7 @@ namespace Umbraco.Tests.Persistence.Repositories public void Can_Perform_Delete_On_UserTypeRepository() { // Arrange - var provider = new PetaPocoUnitOfWorkProvider(Logger); + var provider = new NPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); using (var repository = CreateRepository(unitOfWork)) { @@ -161,7 +161,7 @@ namespace Umbraco.Tests.Persistence.Repositories public void Can_Perform_Get_On_UserTypeRepository() { // Arrange - var provider = new PetaPocoUnitOfWorkProvider(Logger); + var provider = new NPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); using (var repository = CreateRepository(unitOfWork)) { @@ -186,7 +186,7 @@ namespace Umbraco.Tests.Persistence.Repositories public void Can_Perform_GetByQuery_On_UserTypeRepository() { // Arrange - var provider = new PetaPocoUnitOfWorkProvider(Logger); + var provider = new NPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); using (var repository = CreateRepository(unitOfWork)) { @@ -205,7 +205,7 @@ namespace Umbraco.Tests.Persistence.Repositories public void Can_Perform_GetAll_By_Param_Ids_On_UserTypeRepository() { // Arrange - var provider = new PetaPocoUnitOfWorkProvider(Logger); + var provider = new NPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); using (var repository = CreateRepository(unitOfWork)) { @@ -225,7 +225,7 @@ namespace Umbraco.Tests.Persistence.Repositories public void Can_Perform_GetAll_On_UserTypeRepository() { // Arrange - var provider = new PetaPocoUnitOfWorkProvider(Logger); + var provider = new NPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); using (var repository = CreateRepository(unitOfWork)) { @@ -245,7 +245,7 @@ namespace Umbraco.Tests.Persistence.Repositories public void Can_Perform_Exists_On_UserTypeRepository() { // Arrange - var provider = new PetaPocoUnitOfWorkProvider(Logger); + var provider = new NPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); using (var repository = CreateRepository(unitOfWork)) { @@ -263,7 +263,7 @@ namespace Umbraco.Tests.Persistence.Repositories public void Can_Perform_Count_On_UserTypeRepository() { // Arrange - var provider = new PetaPocoUnitOfWorkProvider(Logger); + var provider = new NPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); using (var repository = CreateRepository(unitOfWork)) { diff --git a/src/Umbraco.Tests/Persistence/SqlCeTableByTableTest.cs b/src/Umbraco.Tests/Persistence/SqlCeTableByTableTest.cs index e637e98183..7b9a67a607 100644 --- a/src/Umbraco.Tests/Persistence/SqlCeTableByTableTest.cs +++ b/src/Umbraco.Tests/Persistence/SqlCeTableByTableTest.cs @@ -1,6 +1,7 @@ using System; using System.IO; using Moq; +using NPoco; using NUnit.Framework; using Umbraco.Core; using Umbraco.Core.Cache; @@ -49,7 +50,7 @@ namespace Umbraco.Tests.Persistence [Test] public void Can_Create_umbracoNode_Table() { - using (Transaction transaction = DatabaseContext.Database.GetTransaction()) + using (var transaction = DatabaseContext.Database.GetTransaction()) { DatabaseSchemaHelper.CreateTable(); @@ -60,7 +61,7 @@ namespace Umbraco.Tests.Persistence [Test] public void Can_Create_umbracoAccess_Table() { - using (Transaction transaction = DatabaseContext.Database.GetTransaction()) + using (var transaction = DatabaseContext.Database.GetTransaction()) { DatabaseSchemaHelper.CreateTable(); DatabaseSchemaHelper.CreateTable(); @@ -72,7 +73,7 @@ namespace Umbraco.Tests.Persistence [Test] public void Can_Create_umbracoAccessRule_Table() { - using (Transaction transaction = DatabaseContext.Database.GetTransaction()) + using (var transaction = DatabaseContext.Database.GetTransaction()) { DatabaseSchemaHelper.CreateTable(); DatabaseSchemaHelper.CreateTable(); @@ -86,7 +87,7 @@ namespace Umbraco.Tests.Persistence public void Can_Create_cmsContentType2ContentType_Table() { - using (Transaction transaction = DatabaseContext.Database.GetTransaction()) + using (var transaction = DatabaseContext.Database.GetTransaction()) { DatabaseSchemaHelper.CreateTable(); DatabaseSchemaHelper.CreateTable(); @@ -99,7 +100,7 @@ namespace Umbraco.Tests.Persistence public void Can_Create_cmsContentTypeAllowedContentType_Table() { - using (Transaction transaction = DatabaseContext.Database.GetTransaction()) + using (var transaction = DatabaseContext.Database.GetTransaction()) { DatabaseSchemaHelper.CreateTable(); DatabaseSchemaHelper.CreateTable(); @@ -113,7 +114,7 @@ namespace Umbraco.Tests.Persistence public void Can_Create_cmsContentType_Table() { - using (Transaction transaction = DatabaseContext.Database.GetTransaction()) + using (var transaction = DatabaseContext.Database.GetTransaction()) { DatabaseSchemaHelper.CreateTable(); DatabaseSchemaHelper.CreateTable(); @@ -126,7 +127,7 @@ namespace Umbraco.Tests.Persistence public void Can_Create_cmsContentVersion_Table() { - using (Transaction transaction = DatabaseContext.Database.GetTransaction()) + using (var transaction = DatabaseContext.Database.GetTransaction()) { DatabaseSchemaHelper.CreateTable(); DatabaseSchemaHelper.CreateTable(); @@ -141,7 +142,7 @@ namespace Umbraco.Tests.Persistence public void Can_Create_cmsContentXml_Table() { - using (Transaction transaction = DatabaseContext.Database.GetTransaction()) + using (var transaction = DatabaseContext.Database.GetTransaction()) { DatabaseSchemaHelper.CreateTable(); DatabaseSchemaHelper.CreateTable(); @@ -156,7 +157,7 @@ namespace Umbraco.Tests.Persistence public void Can_Create_cmsDataType_Table() { - using (Transaction transaction = DatabaseContext.Database.GetTransaction()) + using (var transaction = DatabaseContext.Database.GetTransaction()) { DatabaseSchemaHelper.CreateTable(); DatabaseSchemaHelper.CreateTable(); @@ -169,7 +170,7 @@ namespace Umbraco.Tests.Persistence public void Can_Create_cmsDataTypePreValues_Table() { - using (Transaction transaction = DatabaseContext.Database.GetTransaction()) + using (var transaction = DatabaseContext.Database.GetTransaction()) { DatabaseSchemaHelper.CreateTable(); DatabaseSchemaHelper.CreateTable(); @@ -183,7 +184,7 @@ namespace Umbraco.Tests.Persistence public void Can_Create_cmsDictionary_Table() { - using (Transaction transaction = DatabaseContext.Database.GetTransaction()) + using (var transaction = DatabaseContext.Database.GetTransaction()) { DatabaseSchemaHelper.CreateTable(); @@ -195,7 +196,7 @@ namespace Umbraco.Tests.Persistence public void Can_Create_cmsLanguageText_Table() { - using (Transaction transaction = DatabaseContext.Database.GetTransaction()) + using (var transaction = DatabaseContext.Database.GetTransaction()) { DatabaseSchemaHelper.CreateTable(); DatabaseSchemaHelper.CreateTable(); @@ -209,7 +210,7 @@ namespace Umbraco.Tests.Persistence public void Can_Create_cmsTemplate_Table() { - using (Transaction transaction = DatabaseContext.Database.GetTransaction()) + using (var transaction = DatabaseContext.Database.GetTransaction()) { DatabaseSchemaHelper.CreateTable(); DatabaseSchemaHelper.CreateTable(); @@ -222,7 +223,7 @@ namespace Umbraco.Tests.Persistence public void Can_Create_cmsDocument_Table() { - using (Transaction transaction = DatabaseContext.Database.GetTransaction()) + using (var transaction = DatabaseContext.Database.GetTransaction()) { DatabaseSchemaHelper.CreateTable(); DatabaseSchemaHelper.CreateTable(); @@ -238,7 +239,7 @@ namespace Umbraco.Tests.Persistence public void Can_Create_cmsDocumentType_Table() { - using (Transaction transaction = DatabaseContext.Database.GetTransaction()) + using (var transaction = DatabaseContext.Database.GetTransaction()) { DatabaseSchemaHelper.CreateTable(); DatabaseSchemaHelper.CreateTable(); @@ -253,7 +254,7 @@ namespace Umbraco.Tests.Persistence public void Can_Create_umbracoDomains_Table() { - using (Transaction transaction = DatabaseContext.Database.GetTransaction()) + using (var transaction = DatabaseContext.Database.GetTransaction()) { DatabaseSchemaHelper.CreateTable(); DatabaseSchemaHelper.CreateTable(); @@ -266,7 +267,7 @@ namespace Umbraco.Tests.Persistence public void Can_Create_umbracoLanguage_Table() { - using (Transaction transaction = DatabaseContext.Database.GetTransaction()) + using (var transaction = DatabaseContext.Database.GetTransaction()) { DatabaseSchemaHelper.CreateTable(); @@ -278,7 +279,7 @@ namespace Umbraco.Tests.Persistence public void Can_Create_umbracoLog_Table() { - using (Transaction transaction = DatabaseContext.Database.GetTransaction()) + using (var transaction = DatabaseContext.Database.GetTransaction()) { DatabaseSchemaHelper.CreateTable(); @@ -290,7 +291,7 @@ namespace Umbraco.Tests.Persistence public void Can_Create_cmsMacro_Table() { - using (Transaction transaction = DatabaseContext.Database.GetTransaction()) + using (var transaction = DatabaseContext.Database.GetTransaction()) { DatabaseSchemaHelper.CreateTable(); @@ -302,7 +303,7 @@ namespace Umbraco.Tests.Persistence public void Can_Create_cmsMember_Table() { - using (Transaction transaction = DatabaseContext.Database.GetTransaction()) + using (var transaction = DatabaseContext.Database.GetTransaction()) { DatabaseSchemaHelper.CreateTable(); DatabaseSchemaHelper.CreateTable(); @@ -317,7 +318,7 @@ namespace Umbraco.Tests.Persistence public void Can_Create_cmsMember2MemberGroup_Table() { - using (Transaction transaction = DatabaseContext.Database.GetTransaction()) + using (var transaction = DatabaseContext.Database.GetTransaction()) { DatabaseSchemaHelper.CreateTable(); DatabaseSchemaHelper.CreateTable(); @@ -333,7 +334,7 @@ namespace Umbraco.Tests.Persistence public void Can_Create_cmsMemberType_Table() { - using (Transaction transaction = DatabaseContext.Database.GetTransaction()) + using (var transaction = DatabaseContext.Database.GetTransaction()) { DatabaseSchemaHelper.CreateTable(); DatabaseSchemaHelper.CreateTable(); @@ -347,7 +348,7 @@ namespace Umbraco.Tests.Persistence public void Can_Create_cmsPreviewXml_Table() { - using (Transaction transaction = DatabaseContext.Database.GetTransaction()) + using (var transaction = DatabaseContext.Database.GetTransaction()) { DatabaseSchemaHelper.CreateTable(); DatabaseSchemaHelper.CreateTable(); @@ -363,7 +364,7 @@ namespace Umbraco.Tests.Persistence public void Can_Create_cmsPropertyData_Table() { - using (Transaction transaction = DatabaseContext.Database.GetTransaction()) + using (var transaction = DatabaseContext.Database.GetTransaction()) { DatabaseSchemaHelper.CreateTable(); DatabaseSchemaHelper.CreateTable(); @@ -380,7 +381,7 @@ namespace Umbraco.Tests.Persistence public void Can_Create_cmsPropertyType_Table() { - using (Transaction transaction = DatabaseContext.Database.GetTransaction()) + using (var transaction = DatabaseContext.Database.GetTransaction()) { DatabaseSchemaHelper.CreateTable(); DatabaseSchemaHelper.CreateTable(); @@ -396,7 +397,7 @@ namespace Umbraco.Tests.Persistence public void Can_Create_cmsPropertyTypeGroup_Table() { - using (Transaction transaction = DatabaseContext.Database.GetTransaction()) + using (var transaction = DatabaseContext.Database.GetTransaction()) { DatabaseSchemaHelper.CreateTable(); DatabaseSchemaHelper.CreateTable(); @@ -410,7 +411,7 @@ namespace Umbraco.Tests.Persistence public void Can_Create_umbracoRelation_Table() { - using (Transaction transaction = DatabaseContext.Database.GetTransaction()) + using (var transaction = DatabaseContext.Database.GetTransaction()) { DatabaseSchemaHelper.CreateTable(); DatabaseSchemaHelper.CreateTable(); @@ -424,7 +425,7 @@ namespace Umbraco.Tests.Persistence public void Can_Create_umbracoRelationType_Table() { - using (Transaction transaction = DatabaseContext.Database.GetTransaction()) + using (var transaction = DatabaseContext.Database.GetTransaction()) { DatabaseSchemaHelper.CreateTable(); @@ -436,7 +437,7 @@ namespace Umbraco.Tests.Persistence public void Can_Create_cmsStylesheet_Table() { - using (Transaction transaction = DatabaseContext.Database.GetTransaction()) + using (var transaction = DatabaseContext.Database.GetTransaction()) { DatabaseSchemaHelper.CreateTable(); DatabaseSchemaHelper.CreateTable(); @@ -449,7 +450,7 @@ namespace Umbraco.Tests.Persistence public void Can_Create_cmsStylesheetProperty_Table() { - using (Transaction transaction = DatabaseContext.Database.GetTransaction()) + using (var transaction = DatabaseContext.Database.GetTransaction()) { DatabaseSchemaHelper.CreateTable(); DatabaseSchemaHelper.CreateTable(); @@ -462,7 +463,7 @@ namespace Umbraco.Tests.Persistence public void Can_Create_cmsTags_Table() { - using (Transaction transaction = DatabaseContext.Database.GetTransaction()) + using (var transaction = DatabaseContext.Database.GetTransaction()) { DatabaseSchemaHelper.CreateTable(); @@ -474,7 +475,7 @@ namespace Umbraco.Tests.Persistence public void Can_Create_cmsTagRelationship_Table() { - using (Transaction transaction = DatabaseContext.Database.GetTransaction()) + using (var transaction = DatabaseContext.Database.GetTransaction()) { DatabaseSchemaHelper.CreateTable(); DatabaseSchemaHelper.CreateTable(); @@ -494,7 +495,7 @@ namespace Umbraco.Tests.Persistence public void Can_Create_cmsTask_Table() { - using (Transaction transaction = DatabaseContext.Database.GetTransaction()) + using (var transaction = DatabaseContext.Database.GetTransaction()) { DatabaseSchemaHelper.CreateTable(); DatabaseSchemaHelper.CreateTable(); @@ -510,7 +511,7 @@ namespace Umbraco.Tests.Persistence public void Can_Create_cmsTaskType_Table() { - using (Transaction transaction = DatabaseContext.Database.GetTransaction()) + using (var transaction = DatabaseContext.Database.GetTransaction()) { DatabaseSchemaHelper.CreateTable(); @@ -522,7 +523,7 @@ namespace Umbraco.Tests.Persistence public void Can_Create_umbracoDeployDependency_Table() { - using (Transaction transaction = DatabaseContext.Database.GetTransaction()) + using (var transaction = DatabaseContext.Database.GetTransaction()) { DatabaseSchemaHelper.CreateTable(); DatabaseSchemaHelper.CreateTable(); @@ -535,7 +536,7 @@ namespace Umbraco.Tests.Persistence public void Can_Create_umbracoDeployChecksum_Table() { - using (Transaction transaction = DatabaseContext.Database.GetTransaction()) + using (var transaction = DatabaseContext.Database.GetTransaction()) { DatabaseSchemaHelper.CreateTable(); @@ -547,7 +548,7 @@ namespace Umbraco.Tests.Persistence public void Can_Create_umbracoUser_Table() { - using (Transaction transaction = DatabaseContext.Database.GetTransaction()) + using (var transaction = DatabaseContext.Database.GetTransaction()) { DatabaseSchemaHelper.CreateTable(); DatabaseSchemaHelper.CreateTable(); @@ -560,7 +561,7 @@ namespace Umbraco.Tests.Persistence public void Can_Create_umbracoUserType_Table() { - using (Transaction transaction = DatabaseContext.Database.GetTransaction()) + using (var transaction = DatabaseContext.Database.GetTransaction()) { DatabaseSchemaHelper.CreateTable(); @@ -572,7 +573,7 @@ namespace Umbraco.Tests.Persistence public void Can_Create_umbracoUser2app_Table() { - using (Transaction transaction = DatabaseContext.Database.GetTransaction()) + using (var transaction = DatabaseContext.Database.GetTransaction()) { DatabaseSchemaHelper.CreateTable(); DatabaseSchemaHelper.CreateTable(); @@ -586,7 +587,7 @@ namespace Umbraco.Tests.Persistence public void Can_Create_umbracoUser2NodeNotify_Table() { - using (Transaction transaction = DatabaseContext.Database.GetTransaction()) + using (var transaction = DatabaseContext.Database.GetTransaction()) { DatabaseSchemaHelper.CreateTable(); DatabaseSchemaHelper.CreateTable(); @@ -601,7 +602,7 @@ namespace Umbraco.Tests.Persistence public void Can_Create_umbracoUser2NodePermission_Table() { - using (Transaction transaction = DatabaseContext.Database.GetTransaction()) + using (var transaction = DatabaseContext.Database.GetTransaction()) { DatabaseSchemaHelper.CreateTable(); DatabaseSchemaHelper.CreateTable(); diff --git a/src/Umbraco.Tests/Persistence/SyntaxProvider/SqlCeSyntaxProviderTests.cs b/src/Umbraco.Tests/Persistence/SyntaxProvider/SqlCeSyntaxProviderTests.cs index b5ae4a5ed5..7951df2dc6 100644 --- a/src/Umbraco.Tests/Persistence/SyntaxProvider/SqlCeSyntaxProviderTests.cs +++ b/src/Umbraco.Tests/Persistence/SyntaxProvider/SqlCeSyntaxProviderTests.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using NPoco; using NUnit.Framework; using Umbraco.Core; using Umbraco.Core.Models.Rdbms; @@ -20,17 +21,15 @@ namespace Umbraco.Tests.Persistence.SyntaxProvider [Test] public void Can_Generate_Delete_SubQuery_Statement() { - var sqlSyntax = new SqlCeSyntaxProvider(); - var mediaObjectType = Guid.Parse(Constants.ObjectTypes.Media); - var subQuery = new Sql() + var subQuery = Sql() .Select("DISTINCT cmsContentXml.nodeId") - .From(sqlSyntax) - .InnerJoin(sqlSyntax) - .On(sqlSyntax, left => left.NodeId, right => right.NodeId) - .Where(sqlSyntax, dto => dto.NodeObjectType == mediaObjectType); + .From() + .InnerJoin() + .On(left => left.NodeId, right => right.NodeId) + .Where(dto => dto.NodeObjectType == mediaObjectType); - var sqlOutput = sqlSyntax.GetDeleteSubquery("cmsContentXml", "nodeId", subQuery); + var sqlOutput = SqlContext.SqlSyntax.GetDeleteSubquery("cmsContentXml", "nodeId", subQuery); Assert.AreEqual(@"DELETE FROM [cmsContentXml] WHERE [nodeId] IN (SELECT [nodeId] FROM (SELECT DISTINCT cmsContentXml.nodeId FROM [cmsContentXml] @@ -47,15 +46,13 @@ WHERE (([umbracoNode].[nodeObjectType] = @0))) x)".Replace(Environment.NewLine, [Test] public void Can_Generate_Create_Table_Statement() { - var sqlSyntax = new SqlCeSyntaxProvider(); - var type = typeof (NodeDto); - var definition = DefinitionFactory.GetTableDefinition(type, sqlSyntax); + var definition = DefinitionFactory.GetTableDefinition(type, SqlContext.SqlSyntax); - string create = sqlSyntax.Format(definition); - string primaryKey = sqlSyntax.FormatPrimaryKey(definition); - var indexes = sqlSyntax.Format(definition.Indexes); - var keys = sqlSyntax.Format(definition.ForeignKeys); + string create = SqlContext.SqlSyntax.Format(definition); + string primaryKey = SqlContext.SqlSyntax.FormatPrimaryKey(definition); + var indexes = SqlContext.SqlSyntax.Format(definition.Indexes); + var keys = SqlContext.SqlSyntax.Format(definition.ForeignKeys); Console.WriteLine(create); Console.WriteLine(primaryKey); @@ -142,7 +139,6 @@ WHERE (([umbracoNode].[nodeObjectType] = @0))) x)".Replace(Environment.NewLine, TableName = "TheTable", SchemaName = "dbo" }; - } - + } } } \ No newline at end of file diff --git a/src/Umbraco.Tests/Plugins/PluginManagerTests.cs b/src/Umbraco.Tests/Plugins/PluginManagerTests.cs index 975259fe32..b8f5e305a6 100644 --- a/src/Umbraco.Tests/Plugins/PluginManagerTests.cs +++ b/src/Umbraco.Tests/Plugins/PluginManagerTests.cs @@ -263,7 +263,7 @@ namespace Umbraco.Tests.Plugins public void Resolves_Assigned_Mappers() { var foundTypes1 = _manager.ResolveAssignedMapperTypes(); - Assert.AreEqual(28, foundTypes1.Count()); + Assert.AreEqual(29, foundTypes1.Count()); // 29 classes in the solution implement BaseMapper } [Test] @@ -277,14 +277,14 @@ namespace Umbraco.Tests.Plugins public void Resolves_Actions() { var actions = _manager.ResolveActions(); - Assert.AreEqual(37, actions.Count()); + Assert.AreEqual(36, actions.Count()); // 36 classes in the solution implement IAction } [Test] public void Resolves_Trees() { var trees = _manager.ResolveTrees(); - Assert.AreEqual(39, trees.Count()); + Assert.AreEqual(8, trees.Count()); // 8 classes in the solution implement BaseTree } [Test] diff --git a/src/Umbraco.Tests/Plugins/TypeFinderTests.cs b/src/Umbraco.Tests/Plugins/TypeFinderTests.cs index be2a462cfe..d2161bdfe5 100644 --- a/src/Umbraco.Tests/Plugins/TypeFinderTests.cs +++ b/src/Umbraco.Tests/Plugins/TypeFinderTests.cs @@ -19,6 +19,7 @@ using Umbraco.Core; using Umbraco.Core.IO; using umbraco.DataLayer; using umbraco.uicontrols; +using Umbraco.Web; using Umbraco.Web.Models.Trees; using Umbraco.Web.Trees; @@ -73,17 +74,29 @@ namespace Umbraco.Tests.Plugins var typesFound = TypeFinder.FindClassesOfType(_assemblies); var originalTypesFound = TypeFinderOriginal.FindClassesOfType(_assemblies); - Assert.AreEqual(originalTypesFound.Count(), typesFound.Count()); - Assert.AreEqual(9, typesFound.Count()); - Assert.AreEqual(9, originalTypesFound.Count()); + foreach (var type in typesFound) + Console.WriteLine(type); + Console.WriteLine(); + foreach (var type in originalTypesFound) + Console.WriteLine(type); + + // 6 classes in _assemblies implement IApplicationEventHandler + Assert.AreEqual(6, typesFound.Count()); + + // however, + // Umbraco.Core.Profiling.WebProfiler is internal and is not returned by TypeFinderOriginal, + // that's a known issue of the legacy type finder, so we have to tweak the count here. + Assert.AreEqual(5, originalTypesFound.Count()); } [Test] public void Find_Classes_With_Attribute() { var typesFound = TypeFinder.FindClassesWithAttribute(_assemblies); - //TODO: Fix this with the correct count - Assert.AreEqual(1, typesFound.Count()); + Assert.AreEqual(0, typesFound.Count()); // 0 classes in _assemblies are marked with [Tree] + + typesFound = TypeFinder.FindClassesWithAttribute(new[] { typeof (UmbracoContext).Assembly }); + Assert.AreEqual(23, typesFound.Count()); // 23 classes in Umbraco.Web are marked with [Tree] } [Ignore] diff --git a/src/Umbraco.Tests/PropertyEditors/ColorListValidatorTest.cs b/src/Umbraco.Tests/PropertyEditors/ColorListValidatorTest.cs index 900b8399e7..a6ef28a40e 100644 --- a/src/Umbraco.Tests/PropertyEditors/ColorListValidatorTest.cs +++ b/src/Umbraco.Tests/PropertyEditors/ColorListValidatorTest.cs @@ -3,6 +3,7 @@ using Moq; using NUnit.Framework; using Newtonsoft.Json.Linq; using Umbraco.Core.Logging; +using Umbraco.Core.Services; using Umbraco.Web.PropertyEditors; namespace Umbraco.Tests.PropertyEditors @@ -14,7 +15,7 @@ namespace Umbraco.Tests.PropertyEditors public void Only_Tests_On_JArray() { var validator = new ColorListPreValueEditor.ColorListValidator(); - var result = validator.Validate("hello", null, new ColorPickerPropertyEditor(Mock.Of())); + var result = validator.Validate("hello", null, new ColorPickerPropertyEditor(Mock.Of(), Mock.Of())); Assert.AreEqual(0, result.Count()); } @@ -22,7 +23,7 @@ namespace Umbraco.Tests.PropertyEditors public void Only_Tests_On_JArray_Of_Item_JObject() { var validator = new ColorListPreValueEditor.ColorListValidator(); - var result = validator.Validate(new JArray("hello", "world"), null, new ColorPickerPropertyEditor(Mock.Of())); + var result = validator.Validate(new JArray("hello", "world"), null, new ColorPickerPropertyEditor(Mock.Of(), Mock.Of())); Assert.AreEqual(0, result.Count()); } @@ -35,7 +36,7 @@ namespace Umbraco.Tests.PropertyEditors JObject.FromObject(new { value = "zxcvzxcvxzcv" }), JObject.FromObject(new { value = "ABC" }), JObject.FromObject(new { value = "1234567" })), - null, new ColorPickerPropertyEditor(Mock.Of())); + null, new ColorPickerPropertyEditor(Mock.Of(), Mock.Of())); Assert.AreEqual(2, result.Count()); } } diff --git a/src/Umbraco.Tests/PropertyEditors/EnsureUniqueValuesValidatorTest.cs b/src/Umbraco.Tests/PropertyEditors/EnsureUniqueValuesValidatorTest.cs index c24aa65846..bd50d92a94 100644 --- a/src/Umbraco.Tests/PropertyEditors/EnsureUniqueValuesValidatorTest.cs +++ b/src/Umbraco.Tests/PropertyEditors/EnsureUniqueValuesValidatorTest.cs @@ -3,6 +3,7 @@ using Moq; using NUnit.Framework; using Newtonsoft.Json.Linq; using Umbraco.Core.Logging; +using Umbraco.Core.Services; using Umbraco.Web.PropertyEditors; namespace Umbraco.Tests.PropertyEditors @@ -14,7 +15,7 @@ namespace Umbraco.Tests.PropertyEditors public void Only_Tests_On_JArray() { var validator = new ValueListPreValueEditor.EnsureUniqueValuesValidator(); - var result = validator.Validate("hello", null, new ColorPickerPropertyEditor(Mock.Of())); + var result = validator.Validate("hello", null, new ColorPickerPropertyEditor(Mock.Of(), Mock.Of())); Assert.AreEqual(0, result.Count()); } @@ -22,7 +23,7 @@ namespace Umbraco.Tests.PropertyEditors public void Only_Tests_On_JArray_Of_Item_JObject() { var validator = new ValueListPreValueEditor.EnsureUniqueValuesValidator(); - var result = validator.Validate(new JArray("hello", "world"), null, new ColorPickerPropertyEditor(Mock.Of())); + var result = validator.Validate(new JArray("hello", "world"), null, new ColorPickerPropertyEditor(Mock.Of(), Mock.Of())); Assert.AreEqual(0, result.Count()); } @@ -30,7 +31,7 @@ namespace Umbraco.Tests.PropertyEditors public void Allows_Unique_Values() { var validator = new ValueListPreValueEditor.EnsureUniqueValuesValidator(); - var result = validator.Validate(new JArray(JObject.FromObject(new { value = "hello" }), JObject.FromObject(new { value = "world" })), null, new ColorPickerPropertyEditor(Mock.Of())); + var result = validator.Validate(new JArray(JObject.FromObject(new { value = "hello" }), JObject.FromObject(new { value = "world" })), null, new ColorPickerPropertyEditor(Mock.Of(), Mock.Of())); Assert.AreEqual(0, result.Count()); } @@ -39,7 +40,7 @@ namespace Umbraco.Tests.PropertyEditors { var validator = new ValueListPreValueEditor.EnsureUniqueValuesValidator(); var result = validator.Validate(new JArray(JObject.FromObject(new { value = "hello" }), JObject.FromObject(new { value = "hello" })), - null, new ColorPickerPropertyEditor(Mock.Of())); + null, new ColorPickerPropertyEditor(Mock.Of(), Mock.Of())); Assert.AreEqual(1, result.Count()); } @@ -52,7 +53,7 @@ namespace Umbraco.Tests.PropertyEditors JObject.FromObject(new { value = "hello" }), JObject.FromObject(new { value = "world" }), JObject.FromObject(new { value = "world" })), - null, new ColorPickerPropertyEditor(Mock.Of())); + null, new ColorPickerPropertyEditor(Mock.Of(), Mock.Of())); Assert.AreEqual(2, result.Count()); } } diff --git a/src/Umbraco.Tests/PropertyEditors/MultiValuePropertyEditorTests.cs b/src/Umbraco.Tests/PropertyEditors/MultiValuePropertyEditorTests.cs index 42b9d174df..6fe7259b92 100644 --- a/src/Umbraco.Tests/PropertyEditors/MultiValuePropertyEditorTests.cs +++ b/src/Umbraco.Tests/PropertyEditors/MultiValuePropertyEditorTests.cs @@ -1,10 +1,21 @@ using System; using System.Collections.Generic; +using System.ComponentModel; +using System.Globalization; +using System.Linq; using Moq; using NUnit.Framework; +using Umbraco.Core; +using Umbraco.Core.Logging; using Umbraco.Core.Models; +using Umbraco.Core.Persistence; +using Umbraco.Core.Persistence.SqlSyntax; +using Umbraco.Core.Persistence.UnitOfWork; +using Umbraco.Core.Profiling; using Umbraco.Core.PropertyEditors; +using Umbraco.Core.Publishing; using Umbraco.Core.Services; +using Umbraco.Core.Strings; using Umbraco.Web.PropertyEditors; namespace Umbraco.Tests.PropertyEditors @@ -88,6 +99,22 @@ namespace Umbraco.Tests.PropertyEditors [Test] public void DropDownPreValueEditor_Format_Data_For_Editor() { + // editor wants ApplicationContext.Current.Services.TextService + // (that should be fixed with proper injection) + var logger = Mock.Of(); + var textService = new Mock(); + textService.Setup(x => x.Localize(It.IsAny(), It.IsAny(), It.IsAny>())).Returns("blah"); + var appContext = new ApplicationContext( + new DatabaseContext(Mock.Of(), logger, new SqlSyntaxProviders(Enumerable.Empty())), + new ServiceContext( + localizedTextService: textService.Object + ), + Mock.Of(), + new ProfilingLogger(logger, Mock.Of())) + { + IsReady = true + }; + ApplicationContext.Current = appContext; var defaultVals = new Dictionary(); var persisted = new PreValueCollection(new Dictionary @@ -97,7 +124,7 @@ namespace Umbraco.Tests.PropertyEditors {"item3", new PreValue(3, "Item 3")} }); - var editor = new ValueListPreValueEditor(); + var editor = new ValueListPreValueEditor(Mock.Of()); var result = editor.ConvertDbToEditor(defaultVals, persisted); diff --git a/src/Umbraco.Tests/Routing/RenderRouteHandlerTests.cs b/src/Umbraco.Tests/Routing/RenderRouteHandlerTests.cs index 8faa22ae25..4b750b6894 100644 --- a/src/Umbraco.Tests/Routing/RenderRouteHandlerTests.cs +++ b/src/Umbraco.Tests/Routing/RenderRouteHandlerTests.cs @@ -46,7 +46,7 @@ namespace Umbraco.Tests.Routing UmbracoApiControllerResolver.Current = new UmbracoApiControllerResolver( new ActivatorServiceProvider(), Logger, PluginManager.Current.ResolveUmbracoApiControllers()); - ShortStringHelperResolver.Current = new ShortStringHelperResolver(new LegacyShortStringHelper()); + ShortStringHelperResolver.Current = new ShortStringHelperResolver(new DefaultShortStringHelper(SettingsForTests.GetDefault())); base.FreezeResolution(); } diff --git a/src/Umbraco.Tests/Services/ContentServicePerformanceTest.cs b/src/Umbraco.Tests/Services/ContentServicePerformanceTest.cs index 3523b61943..19b52c55a8 100644 --- a/src/Umbraco.Tests/Services/ContentServicePerformanceTest.cs +++ b/src/Umbraco.Tests/Services/ContentServicePerformanceTest.cs @@ -145,7 +145,7 @@ namespace Umbraco.Tests.Services var pages = MockedContent.CreateTextpageContent(contentType, -1, 100); ServiceContext.ContentService.Save(pages, 0); - var provider = new PetaPocoUnitOfWorkProvider(Logger); + var provider = new NPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); using (var tRepository = new TemplateRepository(unitOfWork, DisabledCache, Logger, SqlSyntax, Mock.Of(), Mock.Of(), Mock.Of(), MappingResolver)) @@ -177,7 +177,7 @@ namespace Umbraco.Tests.Services var pages = MockedContent.CreateTextpageContent(contentType, -1, 1000); ServiceContext.ContentService.Save(pages, 0); - var provider = new PetaPocoUnitOfWorkProvider(Logger); + var provider = new NPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); using (var tRepository = new TemplateRepository(unitOfWork, DisabledCache, Logger, SqlSyntax, Mock.Of(), Mock.Of(), Mock.Of(), MappingResolver)) using (var tagRepo = new TagRepository(unitOfWork, DisabledCache, Logger, SqlSyntax, MappingResolver)) @@ -206,7 +206,7 @@ namespace Umbraco.Tests.Services var pages = MockedContent.CreateTextpageContent(contentType, -1, 100); ServiceContext.ContentService.Save(pages, 0); - var provider = new PetaPocoUnitOfWorkProvider(Logger); + var provider = new NPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); using (var tRepository = new TemplateRepository(unitOfWork, DisabledCache, Logger, SqlSyntax, Mock.Of(), Mock.Of(), Mock.Of(), MappingResolver)) @@ -240,7 +240,7 @@ namespace Umbraco.Tests.Services var pages = MockedContent.CreateTextpageContent(contentType, -1, 1000); ServiceContext.ContentService.Save(pages, 0); - var provider = new PetaPocoUnitOfWorkProvider(Logger); + var provider = new NPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); using (var tRepository = new TemplateRepository(unitOfWork, DisabledCache, Logger, SqlSyntax, Mock.Of(), Mock.Of(), Mock.Of(), MappingResolver)) using (var tagRepo = new TagRepository(unitOfWork, DisabledCache, Logger, SqlSyntax, MappingResolver)) diff --git a/src/Umbraco.Tests/Services/ContentServiceTests.cs b/src/Umbraco.Tests/Services/ContentServiceTests.cs index 1346812c2f..5dea7521c0 100644 --- a/src/Umbraco.Tests/Services/ContentServiceTests.cs +++ b/src/Umbraco.Tests/Services/ContentServiceTests.cs @@ -745,7 +745,7 @@ namespace Umbraco.Tests.Services var content = contentService.GetById(NodeDto.NodeIdSeed + 1); bool published = contentService.Publish(content, 0); - var provider = new PetaPocoUnitOfWorkProvider(Logger); + var provider = new NPocoUnitOfWorkProvider(Logger); var uow = provider.GetUnitOfWork(); Assert.IsTrue(uow.Database.Exists(content.Id)); @@ -807,7 +807,7 @@ namespace Umbraco.Tests.Services } var allContent = rootContent.Concat(rootContent.SelectMany(x => x.Descendants())); //for testing we need to clear out the contentXml table so we can see if it worked - var provider = new PetaPocoUnitOfWorkProvider(Logger); + var provider = new NPocoUnitOfWorkProvider(Logger); using (var uow = provider.GetUnitOfWork()) { uow.Database.TruncateTable(SqlSyntax, "cmsContentXml"); @@ -841,7 +841,7 @@ namespace Umbraco.Tests.Services } var allContent = rootContent.Concat(rootContent.SelectMany(x => x.Descendants())).ToList(); //for testing we need to clear out the contentXml table so we can see if it worked - var provider = new PetaPocoUnitOfWorkProvider(Logger); + var provider = new NPocoUnitOfWorkProvider(Logger); using (var uow = provider.GetUnitOfWork()) { @@ -1331,8 +1331,10 @@ namespace Umbraco.Tests.Services [Test] public void Can_Save_Lazy_Content() - { - var unitOfWork = PetaPocoUnitOfWorkProvider.CreateUnitOfWork(Logger); + { + var databaseFactory = new DefaultDatabaseFactory(Umbraco.Core.Configuration.GlobalSettings.UmbracoConnectionName, Logger); + var provider = new NPocoUnitOfWorkProvider(databaseFactory); + var unitOfWork = provider.GetUnitOfWork(); var contentType = ServiceContext.ContentTypeService.GetContentType("umbTextpage"); var root = ServiceContext.ContentService.GetById(NodeDto.NodeIdSeed + 1); @@ -1447,7 +1449,7 @@ namespace Umbraco.Tests.Services contentService.Save(content); - var provider = new PetaPocoUnitOfWorkProvider(Logger); + var provider = new NPocoUnitOfWorkProvider(Logger); using (var uow = provider.GetUnitOfWork()) { @@ -1471,7 +1473,7 @@ namespace Umbraco.Tests.Services contentService.Save(content); - var provider = new PetaPocoUnitOfWorkProvider(Logger); + var provider = new NPocoUnitOfWorkProvider(Logger); using (var uow = provider.GetUnitOfWork()) { diff --git a/src/Umbraco.Tests/Services/Importing/PackageImportTests.cs b/src/Umbraco.Tests/Services/Importing/PackageImportTests.cs index f506933631..c69efed5d8 100644 --- a/src/Umbraco.Tests/Services/Importing/PackageImportTests.cs +++ b/src/Umbraco.Tests/Services/Importing/PackageImportTests.cs @@ -147,15 +147,20 @@ namespace Umbraco.Tests.Services.Importing var xml = XElement.Parse(strXml); var element = xml.Descendants("Templates").First(); var packagingService = ServiceContext.PackagingService; + var init = ServiceContext.FileService.GetTemplates().Count(); // Act var templates = packagingService.ImportTemplates(element); var numberOfTemplates = (from doc in element.Elements("Template") select doc).Count(); + var allTemplates = ServiceContext.FileService.GetTemplates(); // Assert Assert.That(templates, Is.Not.Null); Assert.That(templates.Any(), Is.True); Assert.That(templates.Count(), Is.EqualTo(numberOfTemplates)); + + Assert.AreEqual(init + numberOfTemplates, allTemplates.Count()); + Assert.IsTrue(allTemplates.All(x => x.Content.Contains("UmbracoTemplatePage"))); } [Test] diff --git a/src/Umbraco.Tests/Services/MacroServiceTests.cs b/src/Umbraco.Tests/Services/MacroServiceTests.cs index 7267568025..7a6f68ff40 100644 --- a/src/Umbraco.Tests/Services/MacroServiceTests.cs +++ b/src/Umbraco.Tests/Services/MacroServiceTests.cs @@ -25,7 +25,7 @@ namespace Umbraco.Tests.Services { base.CreateTestData(); - var provider = new PetaPocoUnitOfWorkProvider(Logger); + var provider = new NPocoUnitOfWorkProvider(Logger); using (var unitOfWork = provider.GetUnitOfWork()) using (var repository = new MacroRepository(unitOfWork, CacheHelper.CreateDisabledCacheHelper(), Mock.Of(), SqlSyntax, MappingResolver)) { diff --git a/src/Umbraco.Tests/Services/MediaServiceTests.cs b/src/Umbraco.Tests/Services/MediaServiceTests.cs index 12d4b4b0aa..35c2a9d1b9 100644 --- a/src/Umbraco.Tests/Services/MediaServiceTests.cs +++ b/src/Umbraco.Tests/Services/MediaServiceTests.cs @@ -90,7 +90,7 @@ namespace Umbraco.Tests.Services mediaService.Save(media); - var provider = new PetaPocoUnitOfWorkProvider(Logger); + var provider = new NPocoUnitOfWorkProvider(Logger); var uow = provider.GetUnitOfWork(); Assert.IsTrue(uow.Database.Exists(media.Id)); diff --git a/src/Umbraco.Tests/Services/MemberServiceTests.cs b/src/Umbraco.Tests/Services/MemberServiceTests.cs index 17b4e3499c..3e7a59a228 100644 --- a/src/Umbraco.Tests/Services/MemberServiceTests.cs +++ b/src/Umbraco.Tests/Services/MemberServiceTests.cs @@ -1,5 +1,6 @@ using System; using System.Linq; +using NPoco; using NUnit.Framework; using Umbraco.Core; using Umbraco.Core.Events; @@ -1017,12 +1018,12 @@ namespace Umbraco.Tests.Services result.LastLoginDate.TruncateTo(DateTimeExtensions.DateTruncate.Second)); //now ensure the col is correct - var sql = new Sql().Select("cmsPropertyData.*") - .From(SqlSyntax) - .InnerJoin(SqlSyntax) - .On(SqlSyntax, dto => dto.PropertyTypeId, dto => dto.Id) - .Where(SqlSyntax, dto => dto.NodeId == member.Id) - .Where(SqlSyntax, dto => dto.Alias == Constants.Conventions.Member.LastLoginDate); + var sql = NPoco.Sql.BuilderFor(new SqlContext(SqlSyntax, DatabaseContext.Database)).Select("cmsPropertyData.*") + .From() + .InnerJoin() + .On(dto => dto.PropertyTypeId, dto => dto.Id) + .Where(dto => dto.NodeId == member.Id) + .Where(dto => dto.Alias == Constants.Conventions.Member.LastLoginDate); var colResult = DatabaseContext.Database.Fetch(sql); @@ -1056,7 +1057,7 @@ namespace Umbraco.Tests.Services var customMember = MockedMember.CreateSimpleMember(memberType, "hello", "hello@test.com", "hello", "hello"); ServiceContext.MemberService.Save(customMember); - var provider = new PetaPocoUnitOfWorkProvider(Logger); + var provider = new NPocoUnitOfWorkProvider(Logger); using (var uow = provider.GetUnitOfWork()) { diff --git a/src/Umbraco.Tests/Services/PerformanceTests.cs b/src/Umbraco.Tests/Services/PerformanceTests.cs index f92866d81f..b362ff3597 100644 --- a/src/Umbraco.Tests/Services/PerformanceTests.cs +++ b/src/Umbraco.Tests/Services/PerformanceTests.cs @@ -6,6 +6,7 @@ using System.Globalization; using System.Linq; using System.Threading; using System.Xml.Linq; +using NPoco; using NUnit.Framework; using Umbraco.Core; using Umbraco.Core.Models; @@ -286,8 +287,8 @@ namespace Umbraco.Tests.Services DatabaseContext.Database.BulkInsertRecords(SqlSyntax, nodes); //re-get the nodes with ids - var sql = new Sql(); - sql.Select("*").From(SqlSyntax).Where(SqlSyntax, x => x.NodeObjectType == customObjectType); + var sql = NPoco.Sql.BuilderFor(new SqlContext(SqlSyntax, DatabaseContext.Database)); + sql.SelectAll().From().Where(x => x.NodeObjectType == customObjectType); nodes = DatabaseContext.Database.Fetch(sql); //create the cmsContent data, each with a new content type id (so we can query on it later if needed) diff --git a/src/Umbraco.Tests/Services/ThreadSafetyServiceTest.cs b/src/Umbraco.Tests/Services/ThreadSafetyServiceTest.cs index da7a1079ed..e25892224c 100644 --- a/src/Umbraco.Tests/Services/ThreadSafetyServiceTest.cs +++ b/src/Umbraco.Tests/Services/ThreadSafetyServiceTest.cs @@ -24,7 +24,7 @@ namespace Umbraco.Tests.Services [TestFixture, RequiresSTA] public class ThreadSafetyServiceTest : BaseDatabaseFactoryTest { - private PerThreadPetaPocoUnitOfWorkProvider _uowProvider; + private PerThreadNPocoUnitOfWorkProvider _uowProvider; private PerThreadDatabaseFactory _dbFactory; [SetUp] @@ -47,9 +47,9 @@ namespace Umbraco.Tests.Services //global Database object but this is NOT how it should work in the web world or in any multi threaded scenario. //we need a new Database object for each thread. var repositoryFactory = new RepositoryFactory(SqlSyntax, Container); - _uowProvider = new PerThreadPetaPocoUnitOfWorkProvider(_dbFactory); + _uowProvider = new PerThreadNPocoUnitOfWorkProvider(_dbFactory); var evtMsgs = new TransientMessagesFactory(); - ApplicationContext.Services = new ServiceContext( + ApplicationContext.Services = ServiceContextHelper.GetServiceContext( repositoryFactory, _uowProvider, new FileUnitOfWorkProvider(), @@ -254,11 +254,11 @@ namespace Umbraco.Tests.Services /// /// Creates a UOW with a Database object per thread /// - internal class PerThreadPetaPocoUnitOfWorkProvider : DisposableObject, IDatabaseUnitOfWorkProvider + internal class PerThreadNPocoUnitOfWorkProvider : DisposableObject, IDatabaseUnitOfWorkProvider { private readonly PerThreadDatabaseFactory _dbFactory; - public PerThreadPetaPocoUnitOfWorkProvider(PerThreadDatabaseFactory dbFactory) + public PerThreadNPocoUnitOfWorkProvider(PerThreadDatabaseFactory dbFactory) { _dbFactory = dbFactory; } @@ -267,7 +267,7 @@ namespace Umbraco.Tests.Services { //Create or get a database instance for this thread. var db = _dbFactory.CreateDatabase(); - return new PetaPocoUnitOfWork(db); + return new NPocoUnitOfWork(db); } protected override void DisposeResources() diff --git a/src/Umbraco.Tests/Services/UserServiceTests.cs b/src/Umbraco.Tests/Services/UserServiceTests.cs index a9ebc159ec..6b522efddd 100644 --- a/src/Umbraco.Tests/Services/UserServiceTests.cs +++ b/src/Umbraco.Tests/Services/UserServiceTests.cs @@ -4,12 +4,9 @@ using System.Security.Cryptography; using System.Text; using NUnit.Framework; using Umbraco.Core.Models.Membership; -using Umbraco.Core.Services; using Umbraco.Tests.TestHelpers.Entities; using Umbraco.Core.Persistence.Querying; -using Umbraco.Core.Services; using Umbraco.Tests.TestHelpers; -using Umbraco.Tests.TestHelpers.Entities; using Umbraco.Web._Legacy.Actions; namespace Umbraco.Tests.Services @@ -397,9 +394,10 @@ namespace Umbraco.Tests.Services var user1 = ServiceContext.UserService.CreateUserWithIdentity("test1", "test1@test.com", userType); - var result1 = ServiceContext.UserService.GetUserById((int)user1.Id); + var result1 = ServiceContext.UserService.GetUserById(user1.Id); //expect 2 sections by default - Assert.AreEqual(2, result1.AllowedSections.Count()); + // 3: see commit eb59d33 + Assert.AreEqual(3, result1.AllowedSections.Count()); //adds some allowed sections user1.AddAllowedSection("test1"); @@ -408,9 +406,9 @@ namespace Umbraco.Tests.Services user1.AddAllowedSection("test4"); ServiceContext.UserService.Save(user1); - result1 = ServiceContext.UserService.GetUserById((int)user1.Id); - //expect 6 sections including the two default sections - Assert.AreEqual(6, result1.AllowedSections.Count()); + result1 = ServiceContext.UserService.GetUserById(user1.Id); + //expect 7 sections including the two default sections + Assert.AreEqual(7, result1.AllowedSections.Count()); //simulate clearing the sections foreach (var s in user1.AllowedSections) @@ -424,7 +422,7 @@ namespace Umbraco.Tests.Services //assert //re-get - result1 = ServiceContext.UserService.GetUserById((int)user1.Id); + result1 = ServiceContext.UserService.GetUserById(user1.Id); Assert.AreEqual(2, result1.AllowedSections.Count()); } @@ -547,7 +545,7 @@ namespace Umbraco.Tests.Services Assert.That(updatedItem.StartMediaId, Is.EqualTo(originalUser.StartMediaId)); Assert.That(updatedItem.Email, Is.EqualTo(originalUser.Email)); Assert.That(updatedItem.Username, Is.EqualTo(originalUser.Username)); - Assert.That(updatedItem.AllowedSections.Count(), Is.EqualTo(2)); + Assert.That(updatedItem.AllowedSections.Count(), Is.EqualTo(3)); // 3: see commit eb59d33 } } } diff --git a/src/Umbraco.Tests/Strings/CmsHelperCasingTests.cs b/src/Umbraco.Tests/Strings/CmsHelperCasingTests.cs index 77682661b2..dc39650baa 100644 --- a/src/Umbraco.Tests/Strings/CmsHelperCasingTests.cs +++ b/src/Umbraco.Tests/Strings/CmsHelperCasingTests.cs @@ -30,19 +30,6 @@ namespace Umbraco.Tests.Strings Assert.AreEqual(expected, output); } - [TestCase("thisIsTheEnd", "This Is The End")] - [TestCase("th", "Th")] - [TestCase("t", "t")] - [TestCase("thisis", "Thisis")] - [TestCase("ThisIsTheEnd", "This Is The End")] - [TestCase("WhoIsNumber6InTheVillage", "Who Is Number6In The Village")] // we're happy to reproduce the issue - public void CompatibleLegacyReplacement(string input, string expected) - { - var helper = new LegacyShortStringHelper(); - var output = input.Length < 2 ? input : helper.SplitPascalCasing(input, ' ').ToFirstUpperInvariant(); - Assert.AreEqual(expected, output); - } - [TestCase("thisIsTheEnd", "This Is The End")] [TestCase("th", "Th")] [TestCase("t", "t")] diff --git a/src/Umbraco.Tests/Strings/LegacyShortStringHelperTests.cs b/src/Umbraco.Tests/Strings/LegacyShortStringHelperTests.cs deleted file mode 100644 index 073b7add49..0000000000 --- a/src/Umbraco.Tests/Strings/LegacyShortStringHelperTests.cs +++ /dev/null @@ -1,358 +0,0 @@ -using System.Collections.Generic; -using System.Linq; -using NUnit.Framework; -using Umbraco.Core.Strings; -using Umbraco.Tests.TestHelpers; - -namespace Umbraco.Tests.Strings -{ - [TestFixture] - public class LegacyShortStringHelperTests - { - private LegacyShortStringHelper _helper; - - [SetUp] - public void Setup() - { - var config = SettingsForTests.GetDefault(); - SettingsForTests.ConfigureSettings(config); - _helper = new LegacyShortStringHelper(); - } - - [TearDown] - public void TearDown() - { - } - - - #region Cases - [TestCase("foo", "foo")] - [TestCase(" foo ", "Foo")] - [TestCase("Foo", "Foo")] - [TestCase("FoO", "FoO")] - [TestCase("FoO bar", "FoOBar")] - [TestCase("FoO bar NIL", "FoOBarNIL")] - [TestCase("FoO 33bar 22NIL", "FoO33bar22NIL")] - [TestCase("FoO 33bar 22NI", "FoO33bar22NI")] - [TestCase("0foo", "foo")] - [TestCase("2foo bar", "fooBar")] - [TestCase("9FOO", "FOO")] - [TestCase("foo-BAR", "foo-BAR")] - [TestCase("foo-BA-dang", "foo-BA-dang")] - [TestCase("foo_BAR", "foo_BAR")] - [TestCase("foo'BAR", "fooBAR")] - [TestCase("sauté dans l'espace", "sauteDansLespace", IgnoreReason = "non-supported non-ascii chars")] - [TestCase("foo\"\"bar", "foobar")] - [TestCase("-foo-", "-foo-")] - [TestCase("_foo_", "_foo_")] - [TestCase("spécial", "special", IgnoreReason = "non-supported non-ascii chars")] - [TestCase("brô dëk ", "broDek", IgnoreReason = "non-supported non-ascii chars")] - [TestCase("1235brô dëk ", "broDek", IgnoreReason = "non-supported non-ascii chars")] - [TestCase("汉#字*/漢?字", "")] - [TestCase("aa DB cd EFG X KLMN OP qrst", "aaDBCdEFGXKLMNOPQrst")] - [TestCase("AA db cd EFG X KLMN OP qrst", "AADbCdEFGXKLMNOPQrst")] - [TestCase("AAA db cd EFG X KLMN OP qrst", "AAADbCdEFGXKLMNOPQrst")] - [TestCase("4 ways selector", "WaysSelector")] - [TestCase("WhatIfWeDoItAgain", "WhatIfWeDoItAgain")] - [TestCase("whatIfWeDoItAgain", "whatIfWeDoItAgain")] - [TestCase("WhatIfWEDOITAgain", "WhatIfWEDOITAgain")] - [TestCase("WhatIfWe doItAgain", "WhatIfWeDoItAgain")] - #endregion - public void CleanStringForSafeAlias(string input, string expected) - { - // NOTE legacy CleanStringForSafeAlias has issues w/some cases - // -> ignore test cases - // also, some aliases are strange... how can "-foo-" be a valid alias? - var output = _helper.CleanStringForSafeAlias(input); - Assert.AreEqual(expected, output); - } - - #region Cases - [TestCase("Tab 1", "tab1")] - [TestCase("Home - Page", "homePage")] - [TestCase("Home.Page", "homePage")] - [TestCase("Shannon's Document Type", "shannonsDocumentType")] // look, lowercase s and the end of shannons - [TestCase("!BADDLY nam-ed Document Type", "baddlyNamEdDocumentType")] - [TestCase("i %Want!thisTo end up In Proper@case", "iWantThisToEndUpInProperCase")] - [TestCase("Räksmörgås %%$£¤¤¤§ kéKé", "raksmorgasKeKe", IgnoreReason = "non-supported non-ascii chars")] - [TestCase("TRii", "tRii")] - [TestCase("**TRii", "tRii")] - [TestCase("trII", "trII")] - [TestCase("**trII", "trII")] - [TestCase("trIIX", "trIIX")] - [TestCase("**trIIX", "trIIX")] - #endregion - public void LegacyCleanStringForUmbracoAlias(string input, string expected) - { - // NOTE ToUmbracoAlias has issues w/non-ascii, and a few other things - // -> ignore test cases - // also all those tests should, in theory, fail because removeSpaces is false by default - var output = _helper.LegacyCleanStringForUmbracoAlias(input); - Assert.AreEqual(expected, output); - } - - #region Cases - [TestCase("Home Page", "home-page")] - [TestCase("Shannon's Home Page!", "shannons-home-page!")] - [TestCase("#Someones's Twitter $h1z%n", "someoness-twitter-$h1zn")] - [TestCase("Räksmörgås", "raeksmoergaas")] - [TestCase("'em guys-over there, are#goin' a \"little\"bit crazy eh!! :)", "em-guys-over-there,-aregoin-a-littlebit-crazy-eh!!-)")] - [TestCase("汉#字*/漢?字", "汉字star漢字")] - [TestCase("Réalösk fix bran#lo'sk", "realosk-fix-bran-lo-sk", IgnoreReason = "cannot handle it")] - #endregion - public void LegacyFormatUrl(string input, string expected) - { - // NOTE CleanStringForUrlSegment has issues with a few cases - // -> ignore test cases - // also some results are a bit strange... - var output = _helper.LegacyFormatUrl(input); - Assert.AreEqual(expected, output); - - // NOTE: not testing the overload with culture - // in legacy, they are the same - } - - #region Cases - [TestCase("Home Page", "home-page", true, true, false)] - [TestCase("Shannon's Home Page!", "shannons-home-page", true, true, false)] - [TestCase("#Someones's Twitter $h1z%n", "someoness-twitter-h1zn", true, true, false)] - [TestCase("Räksmörgås", "rksmrgs", true, true, false)] - [TestCase("'em guys-over there, are#goin' a \"little\"bit crazy eh!! :)", "em-guys-over-there-aregoin-a-littlebit-crazy-eh", true, true, false)] - [TestCase("汉#字*/漢?字", "", true, true, false)] - [TestCase("汉#字*/漢?字", "汉字漢字", true, false, false)] - [TestCase("汉#字*/漢?字", "%e6%b1%89%e5%ad%97%e6%bc%a2%e5%ad%97", true, false, true)] - [TestCase("Réalösk fix bran#lo'sk", "realosk-fix-bran-lo-sk", true, true, false, IgnoreReason = "cannot handle it")] - #endregion - public void LegacyToUrlAlias(string input, string expected, bool replaceDoubleDashes, bool stripNonAscii, bool urlEncode) - { - var replacements = new Dictionary - { - {" ", "-"}, - {"\"", ""}, - {""", ""}, - {"@", ""}, - {"%", ""}, - {".", ""}, - {";", ""}, - {"/", ""}, - {":", ""}, - {"#", ""}, - {"+", ""}, - {"*", ""}, - {"&", ""}, - {"?", ""} - }; - - // NOTE CleanStringForUrlSegment has issues with a few cases - // -> ignore test cases - // also some results are a bit strange... - var output = _helper.LegacyToUrlAlias(input, replacements, replaceDoubleDashes, stripNonAscii, urlEncode); - Assert.AreEqual(expected, output); - - // NOTE: not testing the overload with culture - // in legacy, they are the same - } - - #region Cases - [TestCase("Tab 1", "tab1", CleanStringType.CamelCase)] - [TestCase("Home - Page", "homePage", CleanStringType.CamelCase)] - [TestCase("Shannon's document type", "shannon'sDocumentType", CleanStringType.CamelCase)] - [TestCase("This is the FIRSTTIME of TheDay.", "ThisistheFIRSTTIMEofTheDay", CleanStringType.Unchanged)] - [TestCase("Sépàyô lüx.", "Sepayolux", CleanStringType.Unchanged, IgnoreReason = "non-supported non-ascii chars")] - [TestCase("This is the FIRSTTIME of TheDay.", "ThisIsTheFIRSTTIMEOfTheDay", CleanStringType.PascalCase)] - [TestCase("This is the FIRSTTIME of TheDay.", "thisIsTheFIRSTTIMEOfTheDay", CleanStringType.CamelCase)] - #endregion - public void LegacyConvertStringCase(string input, string expected, CleanStringType caseType) - { - // NOTE LegacyConvertStringCase has issues with a few cases - // -> ignore test cases - // also it removes symbols, etc... except the quote? - var output = _helper.LegacyConvertStringCase(input, caseType); - Assert.AreEqual(expected, output); - } - - #region Cases - [TestCase("ThisIsTheEndMyFriend", "This Is The End My Friend")] - [TestCase("ThisIsTHEEndMyFriend", "This Is THE End My Friend")] - [TestCase("THISIsTHEEndMyFriend", "THIS Is THE End My Friend")] - [TestCase("This33I33sThe33EndMyFriend", "This33 I33s The33 End My Friend", IgnoreReason = "fails")] - [TestCase("ThisIsTHEEndMyFriendX", "This Is THE End My Friend X")] - [TestCase("ThisIsTHEEndMyFriendXYZ", "This Is THE End My Friend XYZ")] - [TestCase("ThisIsTHEEndMyFriendXYZt", "This Is THE End My Friend XY Zt")] - [TestCase("UneÉlévationÀPartir", "Une Élévation À Partir", IgnoreReason = "non-supported non-ascii chars")] - #endregion - public void SplitPascalCasing(string input, string expected) - { - // NOTE legacy SplitPascalCasing has issues w/some cases - // -> ignore test cases - var output = _helper.SplitPascalCasing(input, ' '); - Assert.AreEqual(expected, output); - } - - #region Cases - [TestCase("foo", "foo")] - [TestCase(" foo ", "foo")] - [TestCase("Foo", "foo")] - [TestCase("FoO", "foO")] - [TestCase("FoO bar", "foOBar")] - [TestCase("FoO bar NIL", "foOBarNil")] - [TestCase("FoO 33bar 22NIL", "foO33bar22Nil")] - [TestCase("FoO 33bar 22NI", "foO33bar22NI")] - [TestCase("0foo", "foo")] - [TestCase("2foo bar", "fooBar")] - [TestCase("9FOO", "foo")] - [TestCase("foo-BAR", "fooBar")] - [TestCase("foo-BA-dang", "fooBADang")] - [TestCase("foo_BAR", "fooBar")] - [TestCase("foo'BAR", "fooBar")] - [TestCase("sauté dans l'espace", "sauteDansLEspace")] - [TestCase("foo\"\"bar", "fooBar")] - [TestCase("-foo-", "foo")] - [TestCase("_foo_", "foo")] - [TestCase("spécial", "special")] - [TestCase("brô dëk ", "broDek")] - [TestCase("1235brô dëk ", "broDek")] - [TestCase("汉#字*/漢?字", "")] - [TestCase("aa DB cd EFG X KLMN OP qrst", "aaDBCdEfgXKlmnOPQrst")] - [TestCase("AA db cd EFG X KLMN OP qrst", "aaDbCdEfgXKlmnOPQrst")] - [TestCase("AAA db cd EFG X KLMN OP qrst", "aaaDbCdEfgXKlmnOPQrst")] - #endregion - public void CleanStringToAscii(string input, string expected) - { - var output = _helper.CleanString(input, CleanStringType.Ascii | CleanStringType.CamelCase); - // legacy does nothing - Assert.AreEqual(input, output); - } - - #region Cases - [TestCase("1235brô dëK tzARlan ban123!pOo", "brodeKtzARlanban123pOo", CleanStringType.Unchanged)] - [TestCase(" 1235brô dëK tzARlan ban123!pOo ", "brodeKtzARlanban123pOo", CleanStringType.Unchanged)] - [TestCase("1235brô dëK tzARlan ban123!pOo", "BroDeKTzARLanBan123POo", CleanStringType.PascalCase)] - [TestCase("1235brô dëK tzARlan ban123!pOo", "broDeKTzARLanBan123POo", CleanStringType.CamelCase)] - [TestCase("1235brô dëK tzARlan ban123!pOo", "BRODEKTZARLANBAN123POO", CleanStringType.UpperCase)] - [TestCase("1235brô dëK tzARlan ban123!pOo", "brodektzarlanban123poo", CleanStringType.LowerCase)] - [TestCase("aa DB cd EFG X KLMN OP qrst", "aaDBCdEfgXKlmnOPQrst", CleanStringType.CamelCase)] - [TestCase("aaa DB cd EFG X KLMN OP qrst", "aaaDBCdEfgXKlmnOPQrst", CleanStringType.CamelCase)] - [TestCase("aa DB cd EFG X KLMN OP qrst", "AaDBCdEfgXKlmnOPQrst", CleanStringType.PascalCase)] - [TestCase("aaa DB cd EFG X KLMN OP qrst", "AaaDBCdEfgXKlmnOPQrst", CleanStringType.PascalCase)] - [TestCase("AA db cd EFG X KLMN OP qrst", "aaDbCdEfgXKlmnOPQrst", CleanStringType.CamelCase)] - [TestCase("AAA db cd EFG X KLMN OP qrst", "aaaDbCdEfgXKlmnOPQrst", CleanStringType.CamelCase)] - [TestCase("AA db cd EFG X KLMN OP qrst", "AADbCdEfgXKlmnOPQrst", CleanStringType.PascalCase)] - [TestCase("AAA db cd EFG X KLMN OP qrst", "AaaDbCdEfgXKlmnOPQrst", CleanStringType.PascalCase)] - [TestCase("We store some HTML in the DB for performance", "WeStoreSomeHtmlInTheDBForPerformance", CleanStringType.PascalCase)] - [TestCase("We store some HTML in the DB for performance", "weStoreSomeHtmlInTheDBForPerformance", CleanStringType.CamelCase)] - [TestCase("X is true", "XIsTrue", CleanStringType.PascalCase)] - [TestCase("X is true", "xIsTrue", CleanStringType.CamelCase)] - [TestCase("IO are slow", "IOAreSlow", CleanStringType.PascalCase)] - [TestCase("IO are slow", "ioAreSlow", CleanStringType.CamelCase)] - [TestCase("RAM is fast", "RamIsFast", CleanStringType.PascalCase)] - [TestCase("RAM is fast", "ramIsFast", CleanStringType.CamelCase)] - [TestCase("Tab 1", "tab1", CleanStringType.CamelCase)] - [TestCase("Home - Page", "homePage", CleanStringType.CamelCase)] - [TestCase("Shannon's Document Type", "shannonsDocumentType", CleanStringType.CamelCase)] - [TestCase("!BADDLY nam-ed Document Type", "baddlyNamEdDocumentType", CleanStringType.CamelCase)] - [TestCase(" !BADDLY nam-ed Document Type", "BADDLYnamedDocumentType", CleanStringType.Unchanged)] - [TestCase("!BADDLY nam-ed Document Type", "BaddlyNamEdDocumentType", CleanStringType.PascalCase)] - [TestCase("i %Want!thisTo end up In Proper@case", "IWantThisToEndUpInProperCase", CleanStringType.PascalCase)] - [TestCase("Räksmörgås %%$£¤¤¤§ kéKé", "raksmorgasKeKe", CleanStringType.CamelCase)] - [TestCase("Räksmörgås %%$£¤¤¤§ kéKé", "RaksmorgasKeKe", CleanStringType.PascalCase)] - [TestCase("Räksmörgås %%$£¤¤¤§ kéKé", "RaksmorgaskeKe", CleanStringType.Unchanged)] - [TestCase("TRii", "TRii", CleanStringType.Unchanged)] - [TestCase("**TRii", "TRii", CleanStringType.Unchanged)] - [TestCase("TRii", "trIi", CleanStringType.CamelCase)] - [TestCase("**TRii", "trIi", CleanStringType.CamelCase)] - [TestCase("TRii", "TRIi", CleanStringType.PascalCase)] - [TestCase("**TRii", "TRIi", CleanStringType.PascalCase)] - [TestCase("trII", "trII", CleanStringType.Unchanged)] - [TestCase("**trII", "trII", CleanStringType.Unchanged)] - [TestCase("trII", "trII", CleanStringType.CamelCase)] - [TestCase("**trII", "trII", CleanStringType.CamelCase)] - [TestCase("trII", "TrII", CleanStringType.PascalCase)] - [TestCase("**trII", "TrII", CleanStringType.PascalCase)] - [TestCase("trIIX", "trIix", CleanStringType.CamelCase)] - [TestCase("**trIIX", "trIix", CleanStringType.CamelCase)] - [TestCase("trIIX", "TrIix", CleanStringType.PascalCase)] - [TestCase("**trIIX", "TrIix", CleanStringType.PascalCase)] - #endregion - public void CleanStringToAsciiWithCase(string input, string expected, CleanStringType caseType) - { - var output = _helper.CleanString(input, caseType | CleanStringType.Ascii); - // legacy does nothing - Assert.AreEqual(input, output); - } - - #region Cases - [TestCase("1235brô dëK tzARlan ban123!pOo", "bro de K tz AR lan ban123 p Oo", ' ', CleanStringType.Unchanged)] - [TestCase(" 1235brô dëK tzARlan ban123!pOo ", "bro de K tz AR lan ban123 p Oo", ' ', CleanStringType.Unchanged)] - [TestCase("1235brô dëK tzARlan ban123!pOo", "Bro De K Tz AR Lan Ban123 P Oo", ' ', CleanStringType.PascalCase)] - [TestCase("1235brô dëK tzARlan ban123!pOo", "Bro De K Tz AR Lan Ban123 P Oo", ' ', CleanStringType.PascalCase)] - [TestCase("1235brô dëK tzARlan ban123!pOo", "bro De K Tz AR Lan Ban123 P Oo", ' ', CleanStringType.CamelCase)] - [TestCase("1235brô dëK tzARlan ban123!pOo", "bro-De-K-Tz-AR-Lan-Ban123-P-Oo", '-', CleanStringType.CamelCase)] - [TestCase("1235brô dëK tzARlan ban123!pOo", "BRO-DE-K-TZ-AR-LAN-BAN123-P-OO", '-', CleanStringType.UpperCase)] - [TestCase("1235brô dëK tzARlan ban123!pOo", "bro-de-k-tz-ar-lan-ban123-p-oo", '-', CleanStringType.LowerCase)] - [TestCase("Tab 1", "tab 1", ' ', CleanStringType.CamelCase)] - [TestCase("Home - Page", "home Page", ' ', CleanStringType.CamelCase)] - [TestCase("Shannon's Document Type", "shannons Document Type", ' ', CleanStringType.CamelCase)] - [TestCase("!BADDLY nam-ed Document Type", "baddly Nam Ed Document Type", ' ', CleanStringType.CamelCase)] - [TestCase(" !BADDLY nam-ed Document Type", "BADDLY nam ed Document Type", ' ', CleanStringType.Unchanged)] - [TestCase("!BADDLY nam-ed Document Type", "Baddly Nam Ed Document Type", ' ', CleanStringType.PascalCase)] - [TestCase("i %Want!thisTo end up In Proper@case", "I Want This To End Up In Proper Case", ' ', CleanStringType.PascalCase)] - [TestCase("Räksmörgås %%$£¤¤¤§ kéKé", "raksmorgas Ke Ke", ' ', CleanStringType.CamelCase)] - [TestCase("Räksmörgås %%$£¤¤¤§ kéKé", "Raksmorgas Ke Ke", ' ', CleanStringType.PascalCase)] - [TestCase("Räksmörgås %%$£¤¤¤§ kéKé", "Raksmorgas ke Ke", ' ', CleanStringType.Unchanged)] - #endregion - public void CleanStringToAsciiWithCaseAndSeparator(string input, string expected, char separator, CleanStringType caseType) - { - var output = _helper.CleanString(input, caseType | CleanStringType.Ascii, separator); - // legacy does nothing - Assert.AreEqual(input, output); - } - - [Test] // can't do cases with an IDictionary - public void ReplaceManyWithCharMap() - { - const string input = "télévisiön tzvâr ßup   pof"; - const string expected = "television tzvar ssup pof"; - IDictionary replacements = new Dictionary - { - { "é", "e" }, - { "ö", "o" }, - { "â", "a" }, - { "ß", "ss" }, - { " ", " " }, - }; - var output = _helper.ReplaceMany(input, replacements); - Assert.AreEqual(expected, output); - } - - #region Cases - [TestCase("val$id!ate|this|str'ing", "$!'", '-', "val-id-ate|this|str-ing")] - [TestCase("val$id!ate|this|str'ing", "$!'", '*', "val*id*ate|this|str*ing")] - #endregion - public void ReplaceManyByOneChar(string input, string toReplace, char replacement, string expected) - { - var output = _helper.ReplaceMany(input, toReplace.ToArray(), replacement); - Assert.AreEqual(expected, output); - } - - #region Cases - [TestCase("foo.txt", "foo.txt")] - [TestCase("foo", "foo", IgnoreReason = "fails when no extension")] - [TestCase(".txt", ".txt")] - [TestCase("nag*dog/poo:xit.txt", "nag-dog-poo-xit.txt")] - [TestCase("the dog is in the house.txt", "the-dog-is-in-the-house.txt")] - [TestCase("nil.nil.nil.txt", "nilnilnil.txt")] // because of chars map - [TestCase("taradabum", "taradabum", IgnoreReason = "fails when no extension")] - [TestCase("tara$$da:b/u - { - {" ", "-"}, - {"\"", ""}, - {""", ""}, - {"@", ""}, - {"%", ""}, - {".", ""}, - {";", ""}, - {"/", ""}, - {":", ""}, - {"#", ""}, - {"+", ""}, - {"*", ""}, - {"&", ""}, - {"?", ""} - }; - - var name1 = "Home Page"; - var name2 = "Shannon's Home Page!"; - var name3 = "#Someones's Twitter $h1z%n"; - var name4 = "Räksmörgås"; - var name5 = "'em guys-over there, are#goin' a \"little\"bit crazy eh!! :)"; - var name6 = "汉#字*/漢?字"; - - var url1 = name1.ToUrlSegment(); - var url2 = name2.ToUrlSegment(); - var url3 = name3.ToUrlSegment(); - var url4 = name4.ToUrlSegment(); - var url5 = name5.ToUrlSegment(); - var url6 = name6.ToUrlSegment(); - var url7 = name6.ToUrlSegment(); - var url8 = name6.ToUrlSegment(); - - Assert.AreEqual("home-page", url1); - Assert.AreEqual("shannons-home-page", url2); - Assert.AreEqual("someoness-twitter-h1zn", url3); - Assert.AreEqual("rksmrgs", url4); - Assert.AreEqual("em-guys-over-there-aregoin-a-littlebit-crazy-eh", url5); - Assert.AreEqual("", url6); - Assert.AreEqual("汉字漢字", url7); - Assert.AreEqual("%e6%b1%89%e5%ad%97%e6%bc%a2%e5%ad%97", url8); - - } - - [TestCase] - public void StringExtensions_To_Camel_Case() - { - //Arrange - - var name1 = "Tab 1"; - var name2 = "Home - Page"; - var name3 = "Shannon's document type"; - - //Act - - var camelCase1 = name1.ToCleanString(CleanStringType.CamelCase); - var camelCase2 = name2.ToCleanString(CleanStringType.CamelCase); - var camelCase3 = name3.ToCleanString(CleanStringType.CamelCase); - - //Assert - - Assert.AreEqual("tab1", camelCase1); - Assert.AreEqual("homePage", camelCase2); - Assert.AreEqual("shannon'sDocumentType", camelCase3); - } - - [TestCase] - public void StringExtensions_To_Entity_Alias() - { - //Arrange - - var name1 = "Tab 1"; - var name2 = "Home - Page"; - var name3 = "Shannon's Document Type"; - var name4 = "!BADDLY nam-ed Document Type"; - var name5 = "i %Want!thisTo end up In Proper@case"; - - //Act - - var alias1 = name1.ToSafeAlias(); - var alias2 = name2.ToSafeAlias(); - var alias3 = name3.ToSafeAlias(); - var alias4 = name4.ToSafeAlias(); - var alias5 = name5.ToSafeAlias(/*StringAliasCaseType.PascalCase*/); - - //Assert - - Assert.AreEqual("tab1", alias1); - Assert.AreEqual("homePage", alias2); - Assert.AreEqual("shannonsDocumentType", alias3); - Assert.AreEqual("baddlyNamEdDocumentType", alias4); - - // disable: does not support PascalCase anymore - //Assert.AreEqual("IWantThisToEndUpInProperCase", alias5); - } - - } -} diff --git a/src/Umbraco.Tests/TestHelpers/BaseDatabaseFactoryTest.cs b/src/Umbraco.Tests/TestHelpers/BaseDatabaseFactoryTest.cs index e0ed618da2..2276f73a04 100644 --- a/src/Umbraco.Tests/TestHelpers/BaseDatabaseFactoryTest.cs +++ b/src/Umbraco.Tests/TestHelpers/BaseDatabaseFactoryTest.cs @@ -39,7 +39,7 @@ namespace Umbraco.Tests.TestHelpers { /// /// Use this abstract class for tests that requires a Sql Ce database populated with the umbraco db schema. - /// The PetaPoco Database class should be used through the . + /// The NPoco Database class should be used through the . /// [TestFixture, RequiresSTA] public abstract class BaseDatabaseFactoryTest : BaseUmbracoApplicationTest @@ -86,20 +86,20 @@ namespace Umbraco.Tests.TestHelpers } protected override void SetupApplicationContext() - { + { var dbFactory = new DefaultDatabaseFactory( GetDbConnectionString(), GetDbProviderName(), Logger); - + var evtMsgs = new TransientMessagesFactory(); _appContext = new ApplicationContext( //assign the db context new DatabaseContext(dbFactory, Logger, SqlSyntax, "System.Data.SqlServerCe.4.0"), //assign the service context - new ServiceContext( + ServiceContextHelper.GetServiceContext( Container.GetInstance(), - new PetaPocoUnitOfWorkProvider(dbFactory), + new NPocoUnitOfWorkProvider(dbFactory), new FileUnitOfWorkProvider(), new PublishingStrategy(evtMsgs, Logger), CacheHelper, @@ -149,7 +149,7 @@ namespace Umbraco.Tests.TestHelpers ///
protected virtual string GetDbConnectionString() { - return @"Datasource=|DataDirectory|UmbracoPetaPocoTests.sdf;Flush Interval=1;"; + return @"Datasource=|DataDirectory|UmbracoNPocoTests.sdf;Flush Interval=1;"; } /// @@ -168,7 +168,7 @@ namespace Umbraco.Tests.TestHelpers Core.Configuration.GlobalSettings.UmbracoConnectionName, GetDbConnectionString()); - _dbPath = string.Concat(path, "\\UmbracoPetaPocoTests.sdf"); + _dbPath = string.Concat(path, "\\UmbracoNPocoTests.sdf"); //create a new database file if // - is the first test in the session @@ -181,7 +181,7 @@ namespace Umbraco.Tests.TestHelpers || (DatabaseTestBehavior == DatabaseBehavior.NewDbFileAndSchemaPerTest || DatabaseTestBehavior == DatabaseBehavior.EmptyDbFilePerTest) || (_isFirstTestInFixture && DatabaseTestBehavior == DatabaseBehavior.NewDbFileAndSchemaPerFixture)) { - + using (ProfilingLogger.TraceDuration("Remove database file")) { RemoveDatabaseFile(ex => @@ -210,7 +210,7 @@ namespace Umbraco.Tests.TestHelpers } } - + /// /// sets up resolvers before resolution is frozen @@ -256,7 +256,7 @@ namespace Umbraco.Tests.TestHelpers //Create the umbraco database and its base data schemaHelper.CreateDatabaseSchema(_appContext); - //close the connections, we're gonna read this baby in as a byte array so we don't have to re-initialize the + //close the connections, we're gonna read this baby in as a byte array so we don't have to re-initialize the // damn db for each test CloseDbConnections(); @@ -291,7 +291,7 @@ namespace Umbraco.Tests.TestHelpers private void CloseDbConnections() { - //Ensure that any database connections from a previous test is disposed. + //Ensure that any database connections from a previous test is disposed. //This is really just double safety as its also done in the TearDown. if (ApplicationContext != null && DatabaseContext != null && DatabaseContext.Database != null) DatabaseContext.Database.Dispose(); @@ -332,7 +332,7 @@ namespace Umbraco.Tests.TestHelpers string path = TestHelper.CurrentAssemblyDirectory; try { - string filePath = string.Concat(path, "\\UmbracoPetaPocoTests.sdf"); + string filePath = string.Concat(path, "\\UmbracoNPocoTests.sdf"); if (File.Exists(filePath)) { File.Delete(filePath); @@ -368,7 +368,7 @@ namespace Umbraco.Tests.TestHelpers doc.LoadXml(GetXmlContent(templateId)); return doc; }); - + PublishedContentCache.UnitTesting = true; var httpContext = GetHttpContextFactory(url, routeData).HttpContext; @@ -398,7 +398,7 @@ namespace Umbraco.Tests.TestHelpers protected virtual string GetXmlContent(int templateId) { return @" - @@ -411,7 +411,7 @@ namespace Umbraco.Tests.TestHelpers 1 This is some content]]> - + diff --git a/src/Umbraco.Tests/TestHelpers/BaseUmbracoApplicationTest.cs b/src/Umbraco.Tests/TestHelpers/BaseUmbracoApplicationTest.cs index e6065e780d..8db672f59c 100644 --- a/src/Umbraco.Tests/TestHelpers/BaseUmbracoApplicationTest.cs +++ b/src/Umbraco.Tests/TestHelpers/BaseUmbracoApplicationTest.cs @@ -70,7 +70,7 @@ namespace Umbraco.Tests.TestHelpers SetupApplicationContext(); - InitializeMappers(); + InitializeMappers(); FreezeResolution(); @@ -80,7 +80,7 @@ namespace Umbraco.Tests.TestHelpers public override void TearDown() { base.TearDown(); - + //reset settings SettingsForTests.Reset(); UmbracoContext.Current = null; @@ -97,9 +97,10 @@ namespace Umbraco.Tests.TestHelpers protected virtual void ConfigureContainer() { + // oh no! should not use a container in unit tests? var settings = SettingsForTests.GetDefault(); - //register mappers + //register mappers Container.RegisterFrom(); Container.RegisterFrom(); @@ -109,7 +110,7 @@ namespace Umbraco.Tests.TestHelpers //Default Datalayer/Repositories/SQL/Database/etc... Container.RegisterFrom(); - //register basic stuff that might need to be there for some container resolvers to work, we can + //register basic stuff that might need to be there for some container resolvers to work, we can // add more to this in base classes in resolution freezing Container.RegisterSingleton(factory => Logger); Container.Register(factory => CacheHelper); @@ -127,8 +128,12 @@ namespace Umbraco.Tests.TestHelpers Container.RegisterSingleton(factory => Mock.Of(), "PartialViewFileSystem"); Container.RegisterSingleton(factory => Mock.Of(), "PartialViewMacroFileSystem"); Container.RegisterSingleton(factory => Mock.Of(), "StylesheetFileSystem"); - Container.RegisterSingleton(factory => Mock.Of(), "MasterpageFileSystem"); - Container.RegisterSingleton(factory => Mock.Of(), "ViewFileSystem"); + + // need real file systems here as templates content is on-disk only + //Container.RegisterSingleton(factory => Mock.Of(), "MasterpageFileSystem"); + //Container.RegisterSingleton(factory => Mock.Of(), "ViewFileSystem"); + Container.RegisterSingleton(factory => new PhysicalFileSystem("Views", "/views"), "ViewFileSystem"); + Container.RegisterSingleton(factory => new PhysicalFileSystem("MasterPages", "/masterpages"), "MasterpageFileSystem"); } private static readonly object Locker = new object(); @@ -173,7 +178,7 @@ namespace Umbraco.Tests.TestHelpers } /// - /// 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. /// @@ -193,30 +198,35 @@ namespace Umbraco.Tests.TestHelpers } } - protected virtual void SetupCacheHelper() + private void SetupCacheHelper() { - CacheHelper = CacheHelper.CreateDisabledCacheHelper(); + CacheHelper = CreateCacheHelper(); + } + + protected virtual CacheHelper CreateCacheHelper() + { + return CacheHelper.CreateDisabledCacheHelper(); } /// /// Inheritors can override this if they wish to create a custom application context /// protected virtual void SetupApplicationContext() - { + { var evtMsgs = new TransientMessagesFactory(); ApplicationContext.Current = new ApplicationContext( //assign the db context new DatabaseContext(new DefaultDatabaseFactory(Core.Configuration.GlobalSettings.UmbracoConnectionName, Logger), Logger, SqlSyntax, "System.Data.SqlServerCe.4.0"), //assign the service context - new ServiceContext( - Container.GetInstance(), - new PetaPocoUnitOfWorkProvider(Logger), + ServiceContextHelper.GetServiceContext( + Container.GetInstance(), + new NPocoUnitOfWorkProvider(Logger), new FileUnitOfWorkProvider(), - new PublishingStrategy(evtMsgs, Logger), - CacheHelper, - Logger, - evtMsgs, + new PublishingStrategy(evtMsgs, Logger), + CacheHelper, + Logger, + evtMsgs, Enumerable.Empty()), CacheHelper, ProfilingLogger) @@ -241,7 +251,6 @@ namespace Umbraco.Tests.TestHelpers Assembly.Load("Umbraco.Core"), Assembly.Load("umbraco"), Assembly.Load("Umbraco.Tests"), - Assembly.Load("businesslogic"), Assembly.Load("cms"), Assembly.Load("controls"), } @@ -269,7 +278,7 @@ namespace Umbraco.Tests.TestHelpers protected ProfilingLogger ProfilingLogger { get; private set; } protected CacheHelper CacheHelper { get; private set; } - //I know tests shouldn't use IoC, but for all these tests inheriting from this class are integration tests + //I know tests shouldn't use IoC, but for all these tests inheriting from this class are integration tests // and the number of these will hopefully start getting greatly reduced now that most things are mockable. internal IServiceContainer Container { get; private set; } diff --git a/src/Umbraco.Tests/TestHelpers/BaseUsingSqlCeSyntax.cs b/src/Umbraco.Tests/TestHelpers/BaseUsingSqlCeSyntax.cs index f1ff37bbb6..c88df8ba4f 100644 --- a/src/Umbraco.Tests/TestHelpers/BaseUsingSqlCeSyntax.cs +++ b/src/Umbraco.Tests/TestHelpers/BaseUsingSqlCeSyntax.cs @@ -1,5 +1,6 @@ using LightInject; using Moq; +using NPoco; using NUnit.Framework; using Umbraco.Core; using Umbraco.Core.Cache; @@ -9,28 +10,31 @@ using Umbraco.Core.Persistence.Mappers; using Umbraco.Core.Persistence.SqlSyntax; using Umbraco.Core.Profiling; using Umbraco.Core.DependencyInjection; +using Umbraco.Core.Persistence; namespace Umbraco.Tests.TestHelpers { [TestFixture] public abstract class BaseUsingSqlCeSyntax { - protected virtual SqlCeSyntaxProvider SqlSyntax - { - get { return new SqlCeSyntaxProvider(); } - } - private MappingResolver _mappingResolver; - protected IMappingResolver MappingResolver + + protected IMappingResolver MappingResolver => _mappingResolver; + + protected SqlContext SqlContext { get; private set; } + + protected Sql Sql() { - get { return _mappingResolver; } + return NPoco.Sql.BuilderFor(SqlContext); } [SetUp] public virtual void Initialize() { + var sqlSyntax = new SqlCeSyntaxProvider(); + var container = new ServiceContainer(); - container.RegisterSingleton(factory => SqlSyntax); + container.RegisterSingleton(factory => sqlSyntax); container.RegisterSingleton(factory => Mock.Of()); container.RegisterSingleton(factory => Mock.Of()); @@ -43,6 +47,10 @@ namespace Umbraco.Tests.TestHelpers logger, false); + var mappers = new MapperCollection { new PocoMapper() }; + var pocoDataFactory = new FluentPocoDataFactory((type, iPocoDataFactory) => new PocoDataBuilder(type, mappers).Init()); + SqlContext = new SqlContext(sqlSyntax, pocoDataFactory, DatabaseType.SQLCe); + Resolution.Freeze(); SetUp(); } diff --git a/src/Umbraco.Tests/TestHelpers/ServiceContextHelper.cs b/src/Umbraco.Tests/TestHelpers/ServiceContextHelper.cs new file mode 100644 index 0000000000..468c4b19b3 --- /dev/null +++ b/src/Umbraco.Tests/TestHelpers/ServiceContextHelper.cs @@ -0,0 +1,136 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using Umbraco.Core; +using Umbraco.Core.Events; +using Umbraco.Core.IO; +using Umbraco.Core.Logging; +using Umbraco.Core.Persistence; +using Umbraco.Core.Persistence.UnitOfWork; +using Umbraco.Core.Publishing; +using Umbraco.Core.Services; +using Umbraco.Core.Strings; +using Umbraco.Web.Services; + +namespace Umbraco.Tests.TestHelpers +{ + class ServiceContextHelper + { + //NOTE: Should be used sparingly for integration tests only - for unit tests you can just mock the services to be passed to the + // ctor of the ServiceContext. + public static ServiceContext GetServiceContext(RepositoryFactory repositoryFactory, + IDatabaseUnitOfWorkProvider dbUnitOfWorkProvider, + IUnitOfWorkProvider fileUnitOfWorkProvider, + IPublishingStrategy publishingStrategy, + CacheHelper cache, + ILogger logger, + IEventMessagesFactory eventMessagesFactory, + IEnumerable urlSegmentProviders) + { + if (repositoryFactory == null) throw new ArgumentNullException(nameof(repositoryFactory)); + if (dbUnitOfWorkProvider == null) throw new ArgumentNullException(nameof(dbUnitOfWorkProvider)); + if (fileUnitOfWorkProvider == null) throw new ArgumentNullException(nameof(fileUnitOfWorkProvider)); + if (publishingStrategy == null) throw new ArgumentNullException(nameof(publishingStrategy)); + if (cache == null) throw new ArgumentNullException(nameof(cache)); + if (logger == null) throw new ArgumentNullException(nameof(logger)); + if (eventMessagesFactory == null) throw new ArgumentNullException(nameof(eventMessagesFactory)); + + var provider = dbUnitOfWorkProvider; + var fileProvider = fileUnitOfWorkProvider; + + var migrationEntryService = new Lazy(() => new MigrationEntryService(provider, repositoryFactory, logger, eventMessagesFactory)); + var externalLoginService = new Lazy(() => new ExternalLoginService(provider, repositoryFactory, logger, eventMessagesFactory)); + var publicAccessService = new Lazy(() => new PublicAccessService(provider, repositoryFactory, logger, eventMessagesFactory)); + var taskService = new Lazy(() => new TaskService(provider, repositoryFactory, logger, eventMessagesFactory)); + var domainService = new Lazy(() => new DomainService(provider, repositoryFactory, logger, eventMessagesFactory)); + var auditService = new Lazy(() => new AuditService(provider, repositoryFactory, logger, eventMessagesFactory)); + + var localizedTextService = new Lazy(() => new LocalizedTextService( + new Lazy(() => + { + var mainLangFolder = new DirectoryInfo(IOHelper.MapPath(SystemDirectories.Umbraco + "/config/lang/")); + var appPlugins = new DirectoryInfo(IOHelper.MapPath(SystemDirectories.AppPlugins)); + var configLangFolder = new DirectoryInfo(IOHelper.MapPath(SystemDirectories.Config + "/lang/")); + + var pluginLangFolders = appPlugins.Exists == false + ? Enumerable.Empty() + : appPlugins.GetDirectories() + .SelectMany(x => x.GetDirectories("Lang")) + .SelectMany(x => x.GetFiles("*.xml", SearchOption.TopDirectoryOnly)) + .Where(x => Path.GetFileNameWithoutExtension(x.FullName).Length == 5) + .Select(x => new LocalizedTextServiceSupplementaryFileSource(x, false)); + + //user defined langs that overwrite the default, these should not be used by plugin creators + var userLangFolders = configLangFolder.Exists == false + ? Enumerable.Empty() + : configLangFolder + .GetFiles("*.user.xml", SearchOption.TopDirectoryOnly) + .Where(x => Path.GetFileNameWithoutExtension(x.FullName).Length == 10) + .Select(x => new LocalizedTextServiceSupplementaryFileSource(x, true)); + + return new LocalizedTextServiceFileSources( + logger, + cache.RuntimeCache, + mainLangFolder, + pluginLangFolders.Concat(userLangFolders)); + + }), + logger)); + + var userService = new Lazy(() => new UserService(provider, repositoryFactory, logger, eventMessagesFactory)); + var dataTypeService = new Lazy(() => new DataTypeService(provider, repositoryFactory, logger, eventMessagesFactory)); + var contentService = new Lazy(() => new ContentService(provider, repositoryFactory, logger, eventMessagesFactory, publishingStrategy, dataTypeService.Value, userService.Value, urlSegmentProviders)); + var notificationService = new Lazy(() => new NotificationService(provider, userService.Value, contentService.Value, repositoryFactory, logger)); + var serverRegistrationService = new Lazy(() => new ServerRegistrationService(provider, repositoryFactory, logger, eventMessagesFactory)); + var memberGroupService = new Lazy(() => new MemberGroupService(provider, repositoryFactory, logger, eventMessagesFactory)); + var memberService = new Lazy(() => new MemberService(provider, repositoryFactory, logger, eventMessagesFactory, memberGroupService.Value, dataTypeService.Value)); + var mediaService = new Lazy(() => new MediaService(provider, repositoryFactory, logger, eventMessagesFactory, dataTypeService.Value, userService.Value, urlSegmentProviders)); + var contentTypeService = new Lazy(() => new ContentTypeService(provider, repositoryFactory, logger, eventMessagesFactory, contentService.Value, mediaService.Value)); + var fileService = new Lazy(() => new FileService(fileProvider, provider, repositoryFactory, logger, eventMessagesFactory)); + var localizationService = new Lazy(() => new LocalizationService(provider, repositoryFactory, logger, eventMessagesFactory)); + + var memberTypeService = new Lazy(() => new MemberTypeService(provider, repositoryFactory, logger, eventMessagesFactory, memberService.Value)); + var entityService = new Lazy(() => new EntityService( + provider, repositoryFactory, logger, eventMessagesFactory, + contentService.Value, contentTypeService.Value, mediaService.Value, dataTypeService.Value, memberService.Value, memberTypeService.Value, + //TODO: Consider making this an isolated cache instead of using the global one + cache.RuntimeCache)); + + var macroService = new Lazy(() => new MacroService(provider, repositoryFactory, logger, eventMessagesFactory)); + var packagingService = new Lazy(() => new PackagingService(logger, contentService.Value, contentTypeService.Value, mediaService.Value, macroService.Value, dataTypeService.Value, fileService.Value, localizationService.Value, entityService.Value, userService.Value, repositoryFactory, provider, urlSegmentProviders)); + var relationService = new Lazy(() => new RelationService(provider, repositoryFactory, logger, eventMessagesFactory, entityService.Value)); + var treeService = new Lazy(() => new ApplicationTreeService(logger, cache)); + var tagService = new Lazy(() => new TagService(provider, repositoryFactory, logger, eventMessagesFactory)); + var sectionService = new Lazy(() => new SectionService(userService.Value, treeService.Value, provider, cache)); + + return new ServiceContext( + migrationEntryService, + publicAccessService, + taskService, + domainService, + auditService, + localizedTextService, + tagService, + contentService, + userService, + memberService, + mediaService, + contentTypeService, + dataTypeService, + fileService, + localizationService, + packagingService, + serverRegistrationService, + entityService, + relationService, + treeService, + sectionService, + macroService, + memberTypeService, + memberGroupService, + notificationService, + externalLoginService); + } + } +} diff --git a/src/Umbraco.Tests/Umbraco.Tests.csproj b/src/Umbraco.Tests/Umbraco.Tests.csproj index 8a50f648f0..ee8aa696f2 100644 --- a/src/Umbraco.Tests/Umbraco.Tests.csproj +++ b/src/Umbraco.Tests/Umbraco.Tests.csproj @@ -134,6 +134,10 @@ ..\packages\Newtonsoft.Json.8.0.3\lib\net45\Newtonsoft.Json.dll True + + ..\packages\NPoco.3.1.0-u005\lib\net45\NPoco.dll + True + False ..\packages\NUnit.2.6.2\lib\nunit.framework.dll @@ -217,6 +221,7 @@ + @@ -237,6 +242,7 @@ + @@ -335,7 +341,7 @@ - + @@ -384,9 +390,7 @@ - - @@ -445,7 +449,7 @@ - + diff --git a/src/Umbraco.Tests/packages.config b/src/Umbraco.Tests/packages.config index 88dbd6f6ac..63c131688c 100644 --- a/src/Umbraco.Tests/packages.config +++ b/src/Umbraco.Tests/packages.config @@ -20,6 +20,7 @@ + diff --git a/src/Umbraco.Web.UI.Client/lib/umbraco/LegacyUmbClientMgr.js b/src/Umbraco.Web.UI.Client/lib/umbraco/LegacyUmbClientMgr.js index 06d6c11c71..71e7afec12 100644 --- a/src/Umbraco.Web.UI.Client/lib/umbraco/LegacyUmbClientMgr.js +++ b/src/Umbraco.Web.UI.Client/lib/umbraco/LegacyUmbClientMgr.js @@ -106,6 +106,9 @@ Umbraco.Sys.registerNamespace("Umbraco.Application"); treeService.clearCache(); }); }, + childNodeCreated: function() { + //no-op, just needs to be here for legacy reasons + }, reloadActionNode: function () { angularHelper.safeApply($rootScope, function() { var currentMenuNode = appState.getMenuState("currentNode"); @@ -187,20 +190,6 @@ Umbraco.Sys.registerNamespace("Umbraco.Application"); var actions = { openDashboard : function(section){ navService.changeSection(section); - }, - actionDisable: function () { - localizationService.localize("defaultdialogs_confirmdisable").then(function (txtConfirmDisable) { - var currentMenuNode = UmbClientMgr.mainTree().getActionNode(); - if (currentMenuNode) { - if (confirm(txtConfirmDisable + ' "' + UmbClientMgr.mainTree().getActionNode().nodeName + '"?\n\n')) { - angularHelper.safeApply($rootScope, function () { - userResource.disableUser(currentMenuNode.nodeId).then(function () { - UmbClientMgr.mainTree().syncTree("-1," + currentMenuNode.nodeId, true); - }); - }); - } - } - }); } }; diff --git a/src/Umbraco.Web.UI.Client/src/common/directives/components/umbmediagrid.directive.js b/src/Umbraco.Web.UI.Client/src/common/directives/components/umbmediagrid.directive.js index 2e95b0c96b..7d2da34988 100644 --- a/src/Umbraco.Web.UI.Client/src/common/directives/components/umbmediagrid.directive.js +++ b/src/Umbraco.Web.UI.Client/src/common/directives/components/umbmediagrid.directive.js @@ -118,6 +118,13 @@ Use this directive to generate a thumbnail grid of media items. var item = scope.items[i]; setItemData(item); setOriginalSize(item, itemMaxHeight); + + // remove non images when onlyImages is set to true + if(scope.onlyImages === "true" && !item.isFolder && !item.thumbnail){ + scope.items.splice(i, 1); + i--; + } + } if (scope.items.length > 0) { @@ -265,7 +272,8 @@ Use this directive to generate a thumbnail grid of media items. itemMaxWidth: "@", itemMaxHeight: "@", itemMinWidth: "@", - itemMinHeight: "@" + itemMinHeight: "@", + onlyImages: "@" }, link: link }; diff --git a/src/Umbraco.Web.UI.Client/src/common/directives/components/umbtable.directive.js b/src/Umbraco.Web.UI.Client/src/common/directives/components/umbtable.directive.js index fe80d915da..bf593397b6 100644 --- a/src/Umbraco.Web.UI.Client/src/common/directives/components/umbtable.directive.js +++ b/src/Umbraco.Web.UI.Client/src/common/directives/components/umbtable.directive.js @@ -1,71 +1,71 @@ -(function() { - 'use strict'; - - function TableDirective() { - - function link(scope, el, attr, ctrl) { - - scope.clickItem = function(item, $event) { - if(scope.onClick) { - scope.onClick(item); - $event.stopPropagation(); - } - }; - - scope.selectItem = function(item, $index, $event) { - if(scope.onSelect) { - scope.onSelect(item, $index, $event); - $event.stopPropagation(); - } - }; - - scope.selectAll = function($event) { - if(scope.onSelectAll) { - scope.onSelectAll($event); - } - }; - - scope.isSelectedAll = function() { - if(scope.onSelectedAll && scope.items && scope.items.length > 0) { - return scope.onSelectedAll(); - } - }; - - scope.isSortDirection = function (col, direction) { - if (scope.onSortingDirection) { - return scope.onSortingDirection(col, direction); - } - }; - - scope.sort = function(field, allow) { - if(scope.onSort) { - scope.onSort(field, allow); - } - }; - - } - - var directive = { - restrict: 'E', - replace: true, - templateUrl: 'views/components/umb-table.html', - scope: { - items: '=', - itemProperties: '=', - allowSelectAll: '=', - onSelect: '=', - onClick: '=', - onSelectAll: '=', - onSelectedAll: '=', - onSortingDirection: '=', - onSort: '=' - }, - link: link - }; - - return directive; - } - - angular.module('umbraco.directives').directive('umbTable', TableDirective); - -})(); +(function () { + 'use strict'; + + function TableDirective() { + + function link(scope, el, attr, ctrl) { + + scope.clickItem = function (item, $event) { + if (scope.onClick) { + scope.onClick(item); + $event.stopPropagation(); + } + }; + + scope.selectItem = function (item, $index, $event) { + if (scope.onSelect) { + scope.onSelect(item, $index, $event); + $event.stopPropagation(); + } + }; + + scope.selectAll = function ($event) { + if (scope.onSelectAll) { + scope.onSelectAll($event); + } + }; + + scope.isSelectedAll = function () { + if (scope.onSelectedAll && scope.items && scope.items.length > 0) { + return scope.onSelectedAll(); + } + }; + + scope.isSortDirection = function (col, direction) { + if (scope.onSortingDirection) { + return scope.onSortingDirection(col, direction); + } + }; + + scope.sort = function (field, allow, isSystem) { + if (scope.onSort) { + scope.onSort(field, allow, isSystem); + } + }; + + } + + var directive = { + restrict: 'E', + replace: true, + templateUrl: 'views/components/umb-table.html', + scope: { + items: '=', + itemProperties: '=', + allowSelectAll: '=', + onSelect: '=', + onClick: '=', + onSelectAll: '=', + onSelectedAll: '=', + onSortingDirection: '=', + onSort: '=' + }, + link: link + }; + + return directive; + } + + angular.module('umbraco.directives').directive('umbTable', TableDirective); + +})(); diff --git a/src/Umbraco.Web.UI.Client/src/common/resources/auth.resource.js b/src/Umbraco.Web.UI.Client/src/common/resources/auth.resource.js index f32602bda6..20ebaa10c0 100644 --- a/src/Umbraco.Web.UI.Client/src/common/resources/auth.resource.js +++ b/src/Umbraco.Web.UI.Client/src/common/resources/auth.resource.js @@ -51,7 +51,162 @@ function authResource($q, $http, umbRequestHelper, angularHelper) { }), 'Login failed for user ' + username); }, + + /** + * @ngdoc method + * @name umbraco.resources.authResource#performRequestPasswordReset + * @methodOf umbraco.resources.authResource + * + * @description + * Checks to see if the provided email address is a valid user account and sends a link + * to allow them to reset their password + * + * ##usage + *
+         * authResource.performRequestPasswordReset(email)
+         *    .then(function(data) {
+         *        //Do stuff for password reset request...
+         *    });
+         * 
+ * @param {string} email Email address of backoffice user + * @returns {Promise} resourcePromise object + * + */ + performRequestPasswordReset: function (email) { + + if (!email) { + return angularHelper.rejectedPromise({ + errorMsg: 'Email address cannot be empty' + }); + } + + //TODO: This validation shouldn't really be done here, the validation on the login dialog + // is pretty hacky which is why this is here, ideally validation on the login dialog would + // be done properly. + var emailRegex = /\S+@\S+\.\S+/; + if (!emailRegex.test(email)) { + return angularHelper.rejectedPromise({ + errorMsg: 'Email address is not valid' + }); + } + + return umbRequestHelper.resourcePromise( + $http.post( + umbRequestHelper.getApiUrl( + "authenticationApiBaseUrl", + "PostRequestPasswordReset"), { + email: email + }), + 'Request password reset failed for email ' + email); + }, + /** + * @ngdoc method + * @name umbraco.resources.authResource#performValidatePasswordResetCode + * @methodOf umbraco.resources.authResource + * + * @description + * Checks to see if the provided password reset code is valid + * + * ##usage + *
+         * authResource.performValidatePasswordResetCode(resetCode)
+         *    .then(function(data) {
+         *        //Allow reset of password
+         *    });
+         * 
+ * @param {integer} userId User Id + * @param {string} resetCode Password reset code + * @returns {Promise} resourcePromise object + * + */ + performValidatePasswordResetCode: function (userId, resetCode) { + + if (!userId) { + return angularHelper.rejectedPromise({ + errorMsg: 'User Id cannot be empty' + }); + } + + if (!resetCode) { + return angularHelper.rejectedPromise({ + errorMsg: 'Reset code cannot be empty' + }); + } + + return umbRequestHelper.resourcePromise( + $http.post( + umbRequestHelper.getApiUrl( + "authenticationApiBaseUrl", + "PostValidatePasswordResetCode"), + { + userId: userId, + resetCode: resetCode + }), + 'Password reset code validation failed for userId ' + userId + ', code' + resetCode); + }, + + /** + * @ngdoc method + * @name umbraco.resources.authResource#performSetPassword + * @methodOf umbraco.resources.authResource + * + * @description + * Checks to see if the provided password reset code is valid and sets the user's password + * + * ##usage + *
+         * authResource.performSetPassword(userId, password, confirmPassword, resetCode)
+         *    .then(function(data) {
+         *        //Password set
+         *    });
+         * 
+ * @param {integer} userId User Id + * @param {string} password New password + * @param {string} confirmPassword Confirmation of new password + * @param {string} resetCode Password reset code + * @returns {Promise} resourcePromise object + * + */ + performSetPassword: function (userId, password, confirmPassword, resetCode) { + + if (userId === undefined || userId === null) { + return angularHelper.rejectedPromise({ + errorMsg: 'User Id cannot be empty' + }); + } + + if (!password) { + return angularHelper.rejectedPromise({ + errorMsg: 'Password cannot be empty' + }); + } + + if (password !== confirmPassword) { + return angularHelper.rejectedPromise({ + errorMsg: 'Password and confirmation do not match' + }); + } + + if (!resetCode) { + return angularHelper.rejectedPromise({ + errorMsg: 'Reset code cannot be empty' + }); + } + + return umbRequestHelper.resourcePromise( + $http.post( + umbRequestHelper.getApiUrl( + "authenticationApiBaseUrl", + "PostSetPassword"), + { + userId: userId, + password: password, + resetCode: resetCode + }), + 'Password reset code validation failed for userId ' + userId); + }, + unlinkLogin: function (loginProvider, providerKey) { if (!loginProvider || !providerKey) { return angularHelper.rejectedPromise({ diff --git a/src/Umbraco.Web.UI.Client/src/common/resources/content.resource.js b/src/Umbraco.Web.UI.Client/src/common/resources/content.resource.js index 2cf7127707..3c1c1e2252 100644 --- a/src/Umbraco.Web.UI.Client/src/common/resources/content.resource.js +++ b/src/Umbraco.Web.UI.Client/src/common/resources/content.resource.js @@ -29,8 +29,8 @@ function contentResource($q, $http, umbDataFormatter, umbRequestHelper) { function saveContentItem(content, action, files) { return umbRequestHelper.postSaveContent({ restApiUrl: umbRequestHelper.getApiUrl( - "contentApiBaseUrl", - "PostSave"), + "contentApiBaseUrl", + "PostSave"), content: content, action: action, files: files, @@ -41,38 +41,38 @@ function contentResource($q, $http, umbDataFormatter, umbRequestHelper) { } return { - - getRecycleBin: function() { + + getRecycleBin: function () { return umbRequestHelper.resourcePromise( - $http.get( - umbRequestHelper.getApiUrl( - "contentApiBaseUrl", - "GetRecycleBin")), - 'Failed to retrieve data for content recycle bin'); + $http.get( + umbRequestHelper.getApiUrl( + "contentApiBaseUrl", + "GetRecycleBin")), + 'Failed to retrieve data for content recycle bin'); }, /** - * @ngdoc method - * @name umbraco.resources.contentResource#sort - * @methodOf umbraco.resources.contentResource - * - * @description - * Sorts all children below a given parent node id, based on a collection of node-ids - * - * ##usage - *
-         * var ids = [123,34533,2334,23434];
-         * contentResource.sort({ parentId: 1244, sortedIds: ids })
-         *    .then(function() {
-         *        $scope.complete = true;
-         *    });
-         * 
- * @param {Object} args arguments object - * @param {Int} args.parentId the ID of the parent node - * @param {Array} options.sortedIds array of node IDs as they should be sorted - * @returns {Promise} resourcePromise object. - * - */ + * @ngdoc method + * @name umbraco.resources.contentResource#sort + * @methodOf umbraco.resources.contentResource + * + * @description + * Sorts all children below a given parent node id, based on a collection of node-ids + * + * ##usage + *
+          * var ids = [123,34533,2334,23434];
+          * contentResource.sort({ parentId: 1244, sortedIds: ids })
+          *    .then(function() {
+          *        $scope.complete = true;
+          *    });
+          * 
+ * @param {Object} args arguments object + * @param {Int} args.parentId the ID of the parent node + * @param {Array} options.sortedIds array of node IDs as they should be sorted + * @returns {Promise} resourcePromise object. + * + */ sort: function (args) { if (!args) { throw "args cannot be null"; @@ -85,37 +85,37 @@ function contentResource($q, $http, umbDataFormatter, umbRequestHelper) { } return umbRequestHelper.resourcePromise( - $http.post(umbRequestHelper.getApiUrl("contentApiBaseUrl", "PostSort"), - { - parentId: args.parentId, - idSortOrder: args.sortedIds - }), - 'Failed to sort content'); + $http.post(umbRequestHelper.getApiUrl("contentApiBaseUrl", "PostSort"), + { + parentId: args.parentId, + idSortOrder: args.sortedIds + }), + 'Failed to sort content'); }, /** - * @ngdoc method - * @name umbraco.resources.contentResource#move - * @methodOf umbraco.resources.contentResource - * - * @description - * Moves a node underneath a new parentId - * - * ##usage - *
-         * contentResource.move({ parentId: 1244, id: 123 })
-         *    .then(function() {
-         *        alert("node was moved");
-         *    }, function(err){
-         *      alert("node didnt move:" + err.data.Message); 
-         *    });
-         * 
- * @param {Object} args arguments object - * @param {Int} args.idd the ID of the node to move - * @param {Int} args.parentId the ID of the parent node to move to - * @returns {Promise} resourcePromise object. - * - */ + * @ngdoc method + * @name umbraco.resources.contentResource#move + * @methodOf umbraco.resources.contentResource + * + * @description + * Moves a node underneath a new parentId + * + * ##usage + *
+          * contentResource.move({ parentId: 1244, id: 123 })
+          *    .then(function() {
+          *        alert("node was moved");
+          *    }, function(err){
+          *      alert("node didnt move:" + err.data.Message); 
+          *    });
+          * 
+ * @param {Object} args arguments object + * @param {Int} args.idd the ID of the node to move + * @param {Int} args.parentId the ID of the parent node to move to + * @returns {Promise} resourcePromise object. + * + */ move: function (args) { if (!args) { throw "args cannot be null"; @@ -128,38 +128,38 @@ function contentResource($q, $http, umbDataFormatter, umbRequestHelper) { } return umbRequestHelper.resourcePromise( - $http.post(umbRequestHelper.getApiUrl("contentApiBaseUrl", "PostMove"), - { - parentId: args.parentId, - id: args.id - }), - 'Failed to move content'); + $http.post(umbRequestHelper.getApiUrl("contentApiBaseUrl", "PostMove"), + { + parentId: args.parentId, + id: args.id + }), + 'Failed to move content'); }, /** - * @ngdoc method - * @name umbraco.resources.contentResource#copy - * @methodOf umbraco.resources.contentResource - * - * @description - * Copies a node underneath a new parentId - * - * ##usage - *
-         * contentResource.copy({ parentId: 1244, id: 123 })
-         *    .then(function() {
-         *        alert("node was copied");
-         *    }, function(err){
-         *      alert("node wasnt copy:" + err.data.Message); 
-         *    });
-         * 
- * @param {Object} args arguments object - * @param {Int} args.id the ID of the node to copy - * @param {Int} args.parentId the ID of the parent node to copy to - * @param {Boolean} args.relateToOriginal if true, relates the copy to the original through the relation api - * @returns {Promise} resourcePromise object. - * - */ + * @ngdoc method + * @name umbraco.resources.contentResource#copy + * @methodOf umbraco.resources.contentResource + * + * @description + * Copies a node underneath a new parentId + * + * ##usage + *
+          * contentResource.copy({ parentId: 1244, id: 123 })
+          *    .then(function() {
+          *        alert("node was copied");
+          *    }, function(err){
+          *      alert("node wasnt copy:" + err.data.Message); 
+          *    });
+          * 
+ * @param {Object} args arguments object + * @param {Int} args.id the ID of the node to copy + * @param {Int} args.parentId the ID of the parent node to copy to + * @param {Boolean} args.relateToOriginal if true, relates the copy to the original through the relation api + * @returns {Promise} resourcePromise object. + * + */ copy: function (args) { if (!args) { throw "args cannot be null"; @@ -172,271 +172,271 @@ function contentResource($q, $http, umbDataFormatter, umbRequestHelper) { } return umbRequestHelper.resourcePromise( - $http.post(umbRequestHelper.getApiUrl("contentApiBaseUrl", "PostCopy"), - args), - 'Failed to copy content'); + $http.post(umbRequestHelper.getApiUrl("contentApiBaseUrl", "PostCopy"), + args), + 'Failed to copy content'); }, /** - * @ngdoc method - * @name umbraco.resources.contentResource#unPublish - * @methodOf umbraco.resources.contentResource - * - * @description - * Unpublishes a content item with a given Id - * - * ##usage - *
-         * contentResource.unPublish(1234)
-         *    .then(function() {
-         *        alert("node was unpulished");
-         *    }, function(err){
-         *      alert("node wasnt unpublished:" + err.data.Message); 
-         *    });
-         * 
- * @param {Int} id the ID of the node to unpublish - * @returns {Promise} resourcePromise object. - * - */ + * @ngdoc method + * @name umbraco.resources.contentResource#unPublish + * @methodOf umbraco.resources.contentResource + * + * @description + * Unpublishes a content item with a given Id + * + * ##usage + *
+          * contentResource.unPublish(1234)
+          *    .then(function() {
+          *        alert("node was unpulished");
+          *    }, function(err){
+          *      alert("node wasnt unpublished:" + err.data.Message); 
+          *    });
+          * 
+ * @param {Int} id the ID of the node to unpublish + * @returns {Promise} resourcePromise object. + * + */ unPublish: function (id) { if (!id) { throw "id cannot be null"; } - + return umbRequestHelper.resourcePromise( - $http.post( - umbRequestHelper.getApiUrl( - "contentApiBaseUrl", - "PostUnPublish", - [{ id: id }])), - 'Failed to publish content with id ' + id); + $http.post( + umbRequestHelper.getApiUrl( + "contentApiBaseUrl", + "PostUnPublish", + [{ id: id }])), + 'Failed to publish content with id ' + id); }, /** - * @ngdoc method - * @name umbraco.resources.contentResource#emptyRecycleBin - * @methodOf umbraco.resources.contentResource - * - * @description - * Empties the content recycle bin - * - * ##usage - *
-         * contentResource.emptyRecycleBin()
-         *    .then(function() {
-         *        alert('its empty!');
-         *    });
-         * 
- * - * @returns {Promise} resourcePromise object. - * - */ - emptyRecycleBin: function() { + * @ngdoc method + * @name umbraco.resources.contentResource#emptyRecycleBin + * @methodOf umbraco.resources.contentResource + * + * @description + * Empties the content recycle bin + * + * ##usage + *
+          * contentResource.emptyRecycleBin()
+          *    .then(function() {
+          *        alert('its empty!');
+          *    });
+          * 
+ * + * @returns {Promise} resourcePromise object. + * + */ + emptyRecycleBin: function () { return umbRequestHelper.resourcePromise( - $http.post( - umbRequestHelper.getApiUrl( - "contentApiBaseUrl", - "EmptyRecycleBin")), - 'Failed to empty the recycle bin'); + $http.post( + umbRequestHelper.getApiUrl( + "contentApiBaseUrl", + "EmptyRecycleBin")), + 'Failed to empty the recycle bin'); }, /** - * @ngdoc method - * @name umbraco.resources.contentResource#deleteById - * @methodOf umbraco.resources.contentResource - * - * @description - * Deletes a content item with a given id - * - * ##usage - *
-         * contentResource.deleteById(1234)
-         *    .then(function() {
-         *        alert('its gone!');
-         *    });
-         * 
- * - * @param {Int} id id of content item to delete - * @returns {Promise} resourcePromise object. - * - */ - deleteById: function(id) { + * @ngdoc method + * @name umbraco.resources.contentResource#deleteById + * @methodOf umbraco.resources.contentResource + * + * @description + * Deletes a content item with a given id + * + * ##usage + *
+          * contentResource.deleteById(1234)
+          *    .then(function() {
+          *        alert('its gone!');
+          *    });
+          * 
+ * + * @param {Int} id id of content item to delete + * @returns {Promise} resourcePromise object. + * + */ + deleteById: function (id) { return umbRequestHelper.resourcePromise( - $http.post( - umbRequestHelper.getApiUrl( - "contentApiBaseUrl", - "DeleteById", - [{ id: id }])), - 'Failed to delete item ' + id); + $http.post( + umbRequestHelper.getApiUrl( + "contentApiBaseUrl", + "DeleteById", + [{ id: id }])), + 'Failed to delete item ' + id); }, /** - * @ngdoc method - * @name umbraco.resources.contentResource#getById - * @methodOf umbraco.resources.contentResource - * - * @description - * Gets a content item with a given id - * - * ##usage - *
-         * contentResource.getById(1234)
-         *    .then(function(content) {
-         *        var myDoc = content; 
-         *        alert('its here!');
-         *    });
-         * 
- * - * @param {Int} id id of content item to return - * @returns {Promise} resourcePromise object containing the content item. - * - */ - getById: function (id) { + * @ngdoc method + * @name umbraco.resources.contentResource#getById + * @methodOf umbraco.resources.contentResource + * + * @description + * Gets a content item with a given id + * + * ##usage + *
+          * contentResource.getById(1234)
+          *    .then(function(content) {
+          *        var myDoc = content; 
+          *        alert('its here!');
+          *    });
+          * 
+ * + * @param {Int} id id of content item to return + * @returns {Promise} resourcePromise object containing the content item. + * + */ + getById: function (id) { return umbRequestHelper.resourcePromise( - $http.get( - umbRequestHelper.getApiUrl( - "contentApiBaseUrl", - "GetById", - [{ id: id }])), - 'Failed to retrieve data for content id ' + id); + $http.get( + umbRequestHelper.getApiUrl( + "contentApiBaseUrl", + "GetById", + [{ id: id }])), + 'Failed to retrieve data for content id ' + id); }, - + /** - * @ngdoc method - * @name umbraco.resources.contentResource#getByIds - * @methodOf umbraco.resources.contentResource - * - * @description - * Gets an array of content items, given a collection of ids - * - * ##usage - *
-         * contentResource.getByIds( [1234,2526,28262])
-         *    .then(function(contentArray) {
-         *        var myDoc = contentArray; 
-         *        alert('they are here!');
-         *    });
-         * 
- * - * @param {Array} ids ids of content items to return as an array - * @returns {Promise} resourcePromise object containing the content items array. - * - */ + * @ngdoc method + * @name umbraco.resources.contentResource#getByIds + * @methodOf umbraco.resources.contentResource + * + * @description + * Gets an array of content items, given a collection of ids + * + * ##usage + *
+          * contentResource.getByIds( [1234,2526,28262])
+          *    .then(function(contentArray) {
+          *        var myDoc = contentArray; 
+          *        alert('they are here!');
+          *    });
+          * 
+ * + * @param {Array} ids ids of content items to return as an array + * @returns {Promise} resourcePromise object containing the content items array. + * + */ getByIds: function (ids) { - + var idQuery = ""; - _.each(ids, function(item) { + _.each(ids, function (item) { idQuery += "ids=" + item + "&"; }); return umbRequestHelper.resourcePromise( - $http.get( - umbRequestHelper.getApiUrl( - "contentApiBaseUrl", - "GetByIds", - idQuery)), - 'Failed to retrieve data for content with multiple ids'); + $http.get( + umbRequestHelper.getApiUrl( + "contentApiBaseUrl", + "GetByIds", + idQuery)), + 'Failed to retrieve data for content with multiple ids'); }, - + /** - * @ngdoc method - * @name umbraco.resources.contentResource#getScaffold - * @methodOf umbraco.resources.contentResource - * - * @description - * Returns a scaffold of an empty content item, given the id of the content item to place it underneath and the content type alias. - * - * - Parent Id must be provided so umbraco knows where to store the content - * - Content Type alias must be provided so umbraco knows which properties to put on the content scaffold - * - * The scaffold is used to build editors for content that has not yet been populated with data. - * - * ##usage - *
-         * contentResource.getScaffold(1234, 'homepage')
-         *    .then(function(scaffold) {
-         *        var myDoc = scaffold;
-         *        myDoc.name = "My new document"; 
-         *
-         *        contentResource.publish(myDoc, true)
-         *            .then(function(content){
-         *                alert("Retrieved, updated and published again");
-         *            });
-         *    });
-         * 
- * - * @param {Int} parentId id of content item to return - * @param {String} alias contenttype alias to base the scaffold on - * @returns {Promise} resourcePromise object containing the content scaffold. - * - */ + * @ngdoc method + * @name umbraco.resources.contentResource#getScaffold + * @methodOf umbraco.resources.contentResource + * + * @description + * Returns a scaffold of an empty content item, given the id of the content item to place it underneath and the content type alias. + * + * - Parent Id must be provided so umbraco knows where to store the content + * - Content Type alias must be provided so umbraco knows which properties to put on the content scaffold + * + * The scaffold is used to build editors for content that has not yet been populated with data. + * + * ##usage + *
+          * contentResource.getScaffold(1234, 'homepage')
+          *    .then(function(scaffold) {
+          *        var myDoc = scaffold;
+          *        myDoc.name = "My new document"; 
+          *
+          *        contentResource.publish(myDoc, true)
+          *            .then(function(content){
+          *                alert("Retrieved, updated and published again");
+          *            });
+          *    });
+          * 
+ * + * @param {Int} parentId id of content item to return + * @param {String} alias contenttype alias to base the scaffold on + * @returns {Promise} resourcePromise object containing the content scaffold. + * + */ getScaffold: function (parentId, alias) { - + return umbRequestHelper.resourcePromise( - $http.get( - umbRequestHelper.getApiUrl( - "contentApiBaseUrl", - "GetEmpty", - [{ contentTypeAlias: alias }, { parentId: parentId }])), - 'Failed to retrieve data for empty content item type ' + alias); + $http.get( + umbRequestHelper.getApiUrl( + "contentApiBaseUrl", + "GetEmpty", + [{ contentTypeAlias: alias }, { parentId: parentId }])), + 'Failed to retrieve data for empty content item type ' + alias); }, /** - * @ngdoc method - * @name umbraco.resources.contentResource#getNiceUrl - * @methodOf umbraco.resources.contentResource - * - * @description - * Returns a url, given a node ID - * - * ##usage - *
-         * contentResource.getNiceUrl(id)
-         *    .then(function(url) {
-         *        alert('its here!');
-         *    });
-         * 
- * - * @param {Int} id Id of node to return the public url to - * @returns {Promise} resourcePromise object containing the url. - * - */ - getNiceUrl: function (id) { + * @ngdoc method + * @name umbraco.resources.contentResource#getNiceUrl + * @methodOf umbraco.resources.contentResource + * + * @description + * Returns a url, given a node ID + * + * ##usage + *
+          * contentResource.getNiceUrl(id)
+          *    .then(function(url) {
+          *        alert('its here!');
+          *    });
+          * 
+ * + * @param {Int} id Id of node to return the public url to + * @returns {Promise} resourcePromise object containing the url. + * + */ + getNiceUrl: function (id) { return umbRequestHelper.resourcePromise( - $http.get( - umbRequestHelper.getApiUrl( - "contentApiBaseUrl", - "GetNiceUrl",[{id: id}])), - 'Failed to retrieve url for id:' + id); + $http.get( + umbRequestHelper.getApiUrl( + "contentApiBaseUrl", + "GetNiceUrl", [{ id: id }])), + 'Failed to retrieve url for id:' + id); }, /** - * @ngdoc method - * @name umbraco.resources.contentResource#getChildren - * @methodOf umbraco.resources.contentResource - * - * @description - * Gets children of a content item with a given id - * - * ##usage - *
-         * contentResource.getChildren(1234, {pageSize: 10, pageNumber: 2})
-         *    .then(function(contentArray) {
-         *        var children = contentArray; 
-         *        alert('they are here!');
-         *    });
-         * 
- * - * @param {Int} parentid id of content item to return children of - * @param {Object} options optional options object - * @param {Int} options.pageSize if paging data, number of nodes per page, default = 0 - * @param {Int} options.pageNumber if paging data, current page index, default = 0 - * @param {String} options.filter if provided, query will only return those with names matching the filter - * @param {String} options.orderDirection can be `Ascending` or `Descending` - Default: `Ascending` - * @param {String} options.orderBy property to order items by, default: `SortOrder` - * @returns {Promise} resourcePromise object containing an array of content items. - * - */ + * @ngdoc method + * @name umbraco.resources.contentResource#getChildren + * @methodOf umbraco.resources.contentResource + * + * @description + * Gets children of a content item with a given id + * + * ##usage + *
+          * contentResource.getChildren(1234, {pageSize: 10, pageNumber: 2})
+          *    .then(function(contentArray) {
+          *        var children = contentArray; 
+          *        alert('they are here!');
+          *    });
+          * 
+ * + * @param {Int} parentid id of content item to return children of + * @param {Object} options optional options object + * @param {Int} options.pageSize if paging data, number of nodes per page, default = 0 + * @param {Int} options.pageNumber if paging data, current page index, default = 0 + * @param {String} options.filter if provided, query will only return those with names matching the filter + * @param {String} options.orderDirection can be `Ascending` or `Descending` - Default: `Ascending` + * @param {String} options.orderBy property to order items by, default: `SortOrder` + * @returns {Promise} resourcePromise object containing an array of content items. + * + */ getChildren: function (parentId, options) { var defaults = { @@ -444,10 +444,11 @@ function contentResource($q, $http, umbDataFormatter, umbRequestHelper) { pageNumber: 0, filter: '', orderDirection: "Ascending", - orderBy: "SortOrder" + orderBy: "SortOrder", + orderBySystemField: true }; if (options === undefined) { - options = {}; + options = {}; } //overwrite the defaults if there are any specified angular.extend(defaults, options); @@ -461,52 +462,67 @@ function contentResource($q, $http, umbDataFormatter, umbRequestHelper) { options.orderDirection = "Descending"; } + //converts the value to a js bool + function toBool(v) { + if (angular.isNumber(v)) { + return v > 0; + } + if (angular.isString(v)) { + return v === "true"; + } + if (typeof v === "boolean") { + return v; + } + return false; + } + return umbRequestHelper.resourcePromise( - $http.get( - umbRequestHelper.getApiUrl( - "contentApiBaseUrl", - "GetChildren", - [ - { id: parentId }, - { pageNumber: options.pageNumber }, - { pageSize: options.pageSize }, - { orderBy: options.orderBy }, - { orderDirection: options.orderDirection }, - { filter: options.filter } - ])), - 'Failed to retrieve children for content item ' + parentId); + $http.get( + umbRequestHelper.getApiUrl( + "contentApiBaseUrl", + "GetChildren", + [ + { id: parentId }, + { pageNumber: options.pageNumber }, + { pageSize: options.pageSize }, + { orderBy: options.orderBy }, + { orderDirection: options.orderDirection }, + { orderBySystemField: toBool(options.orderBySystemField) }, + { filter: options.filter } + ])), + 'Failed to retrieve children for content item ' + parentId); }, /** - * @ngdoc method - * @name umbraco.resources.contentResource#hasPermission - * @methodOf umbraco.resources.contentResource - * - * @description - * Returns true/false given a permission char to check against a nodeID - * for the current user - * - * ##usage - *
-         * contentResource.hasPermission('p',1234)
-         *    .then(function() {
-         *        alert('You are allowed to publish this item');
-         *    });
-         * 
- * - * @param {String} permission char representing the permission to check - * @param {Int} id id of content item to delete - * @returns {Promise} resourcePromise object. - * - */ - checkPermission: function(permission, id) { + * @ngdoc method + * @name umbraco.resources.contentResource#hasPermission + * @methodOf umbraco.resources.contentResource + * + * @description + * Returns true/false given a permission char to check against a nodeID + * for the current user + * + * ##usage + *
+          * contentResource.hasPermission('p',1234)
+          *    .then(function() {
+          *        alert('You are allowed to publish this item');
+          *    });
+          * 
+ * + * @param {String} permission char representing the permission to check + * @param {Int} id id of content item to delete + * @returns {Promise} resourcePromise object. + * + */ + checkPermission: function (permission, id) { return umbRequestHelper.resourcePromise( - $http.get( - umbRequestHelper.getApiUrl( - "contentApiBaseUrl", - "HasPermission", - [{ permissionToCheck: permission },{ nodeId: id }])), - 'Failed to check permission for item ' + id); + $http.get( + umbRequestHelper.getApiUrl( + "contentApiBaseUrl", + "HasPermission", + [{ permissionToCheck: permission }, { nodeId: id }])), + 'Failed to check permission for item ' + id); }, getPermissions: function (nodeIds) { @@ -520,135 +536,135 @@ function contentResource($q, $http, umbDataFormatter, umbRequestHelper) { }, /** - * @ngdoc method - * @name umbraco.resources.contentResource#save - * @methodOf umbraco.resources.contentResource - * - * @description - * Saves changes made to a content item to its current version, if the content item is new, the isNew paramater must be passed to force creation - * if the content item needs to have files attached, they must be provided as the files param and passed separately - * - * - * ##usage - *
-         * contentResource.getById(1234)
-         *    .then(function(content) {
-         *          content.name = "I want a new name!";
-         *          contentResource.save(content, false)
-         *            .then(function(content){
-         *                alert("Retrieved, updated and saved again");
-         *            });
-         *    });
-         * 
- * - * @param {Object} content The content item object with changes applied - * @param {Bool} isNew set to true to create a new item or to update an existing - * @param {Array} files collection of files for the document - * @returns {Promise} resourcePromise object containing the saved content item. - * - */ + * @ngdoc method + * @name umbraco.resources.contentResource#save + * @methodOf umbraco.resources.contentResource + * + * @description + * Saves changes made to a content item to its current version, if the content item is new, the isNew paramater must be passed to force creation + * if the content item needs to have files attached, they must be provided as the files param and passed separately + * + * + * ##usage + *
+          * contentResource.getById(1234)
+          *    .then(function(content) {
+          *          content.name = "I want a new name!";
+          *          contentResource.save(content, false)
+          *            .then(function(content){
+          *                alert("Retrieved, updated and saved again");
+          *            });
+          *    });
+          * 
+ * + * @param {Object} content The content item object with changes applied + * @param {Bool} isNew set to true to create a new item or to update an existing + * @param {Array} files collection of files for the document + * @returns {Promise} resourcePromise object containing the saved content item. + * + */ save: function (content, isNew, files) { return saveContentItem(content, "save" + (isNew ? "New" : ""), files); }, /** - * @ngdoc method - * @name umbraco.resources.contentResource#publish - * @methodOf umbraco.resources.contentResource - * - * @description - * Saves and publishes changes made to a content item to a new version, if the content item is new, the isNew paramater must be passed to force creation - * if the content item needs to have files attached, they must be provided as the files param and passed separately - * - * - * ##usage - *
-         * contentResource.getById(1234)
-         *    .then(function(content) {
-         *          content.name = "I want a new name, and be published!";
-         *          contentResource.publish(content, false)
-         *            .then(function(content){
-         *                alert("Retrieved, updated and published again");
-         *            });
-         *    });
-         * 
- * - * @param {Object} content The content item object with changes applied - * @param {Bool} isNew set to true to create a new item or to update an existing - * @param {Array} files collection of files for the document - * @returns {Promise} resourcePromise object containing the saved content item. - * - */ + * @ngdoc method + * @name umbraco.resources.contentResource#publish + * @methodOf umbraco.resources.contentResource + * + * @description + * Saves and publishes changes made to a content item to a new version, if the content item is new, the isNew paramater must be passed to force creation + * if the content item needs to have files attached, they must be provided as the files param and passed separately + * + * + * ##usage + *
+          * contentResource.getById(1234)
+          *    .then(function(content) {
+          *          content.name = "I want a new name, and be published!";
+          *          contentResource.publish(content, false)
+          *            .then(function(content){
+          *                alert("Retrieved, updated and published again");
+          *            });
+          *    });
+          * 
+ * + * @param {Object} content The content item object with changes applied + * @param {Bool} isNew set to true to create a new item or to update an existing + * @param {Array} files collection of files for the document + * @returns {Promise} resourcePromise object containing the saved content item. + * + */ publish: function (content, isNew, files) { return saveContentItem(content, "publish" + (isNew ? "New" : ""), files); }, - + /** - * @ngdoc method - * @name umbraco.resources.contentResource#sendToPublish - * @methodOf umbraco.resources.contentResource - * - * @description - * Saves changes made to a content item, and notifies any subscribers about a pending publication - * - * ##usage - *
-         * contentResource.getById(1234)
-         *    .then(function(content) {
-         *          content.name = "I want a new name, and be published!";
-         *          contentResource.sendToPublish(content, false)
-         *            .then(function(content){
-         *                alert("Retrieved, updated and notication send off");
-         *            });
-         *    });
-         * 
- * - * @param {Object} content The content item object with changes applied - * @param {Bool} isNew set to true to create a new item or to update an existing - * @param {Array} files collection of files for the document - * @returns {Promise} resourcePromise object containing the saved content item. - * - */ + * @ngdoc method + * @name umbraco.resources.contentResource#sendToPublish + * @methodOf umbraco.resources.contentResource + * + * @description + * Saves changes made to a content item, and notifies any subscribers about a pending publication + * + * ##usage + *
+          * contentResource.getById(1234)
+          *    .then(function(content) {
+          *          content.name = "I want a new name, and be published!";
+          *          contentResource.sendToPublish(content, false)
+          *            .then(function(content){
+          *                alert("Retrieved, updated and notication send off");
+          *            });
+          *    });
+          * 
+ * + * @param {Object} content The content item object with changes applied + * @param {Bool} isNew set to true to create a new item or to update an existing + * @param {Array} files collection of files for the document + * @returns {Promise} resourcePromise object containing the saved content item. + * + */ sendToPublish: function (content, isNew, files) { return saveContentItem(content, "sendPublish" + (isNew ? "New" : ""), files); }, /** - * @ngdoc method - * @name umbraco.resources.contentResource#publishByid - * @methodOf umbraco.resources.contentResource - * - * @description - * Publishes a content item with a given ID - * - * ##usage - *
-         * contentResource.publishById(1234)
-         *    .then(function(content) {
-         *        alert("published");
-         *    });
-         * 
- * - * @param {Int} id The ID of the conten to publish - * @returns {Promise} resourcePromise object containing the published content item. - * - */ - publishById: function(id){ + * @ngdoc method + * @name umbraco.resources.contentResource#publishByid + * @methodOf umbraco.resources.contentResource + * + * @description + * Publishes a content item with a given ID + * + * ##usage + *
+          * contentResource.publishById(1234)
+          *    .then(function(content) {
+          *        alert("published");
+          *    });
+          * 
+ * + * @param {Int} id The ID of the conten to publish + * @returns {Promise} resourcePromise object containing the published content item. + * + */ + publishById: function (id) { if (!id) { throw "id cannot be null"; } - + return umbRequestHelper.resourcePromise( - $http.post( - umbRequestHelper.getApiUrl( - "contentApiBaseUrl", - "PostPublishById", - [{ id: id }])), - 'Failed to publish content with id ' + id); - + $http.post( + umbRequestHelper.getApiUrl( + "contentApiBaseUrl", + "PostPublishById", + [{ id: id }])), + 'Failed to publish content with id ' + id); + } diff --git a/src/Umbraco.Web.UI.Client/src/common/resources/media.resource.js b/src/Umbraco.Web.UI.Client/src/common/resources/media.resource.js index 9a2310299f..4b56e55801 100644 --- a/src/Umbraco.Web.UI.Client/src/common/resources/media.resource.js +++ b/src/Umbraco.Web.UI.Client/src/common/resources/media.resource.js @@ -4,13 +4,13 @@ * @description Loads in data for media **/ function mediaResource($q, $http, umbDataFormatter, umbRequestHelper) { - + /** internal method process the saving of data and post processing the result */ function saveMediaItem(content, action, files) { return umbRequestHelper.postSaveContent({ restApiUrl: umbRequestHelper.getApiUrl( - "mediaApiBaseUrl", - "PostSave"), + "mediaApiBaseUrl", + "PostSave"), content: content, action: action, files: files, @@ -21,38 +21,38 @@ function mediaResource($q, $http, umbDataFormatter, umbRequestHelper) { } return { - + getRecycleBin: function () { return umbRequestHelper.resourcePromise( - $http.get( - umbRequestHelper.getApiUrl( - "mediaApiBaseUrl", - "GetRecycleBin")), - 'Failed to retrieve data for media recycle bin'); + $http.get( + umbRequestHelper.getApiUrl( + "mediaApiBaseUrl", + "GetRecycleBin")), + 'Failed to retrieve data for media recycle bin'); }, /** - * @ngdoc method - * @name umbraco.resources.mediaResource#sort - * @methodOf umbraco.resources.mediaResource - * - * @description - * Sorts all children below a given parent node id, based on a collection of node-ids - * - * ##usage - *
-         * var ids = [123,34533,2334,23434];
-         * mediaResource.sort({ sortedIds: ids })
-         *    .then(function() {
-         *        $scope.complete = true;
-         *    });
-         * 
- * @param {Object} args arguments object - * @param {Int} args.parentId the ID of the parent node - * @param {Array} options.sortedIds array of node IDs as they should be sorted - * @returns {Promise} resourcePromise object. - * - */ + * @ngdoc method + * @name umbraco.resources.mediaResource#sort + * @methodOf umbraco.resources.mediaResource + * + * @description + * Sorts all children below a given parent node id, based on a collection of node-ids + * + * ##usage + *
+          * var ids = [123,34533,2334,23434];
+          * mediaResource.sort({ sortedIds: ids })
+          *    .then(function() {
+          *        $scope.complete = true;
+          *    });
+          * 
+ * @param {Object} args arguments object + * @param {Int} args.parentId the ID of the parent node + * @param {Array} options.sortedIds array of node IDs as they should be sorted + * @returns {Promise} resourcePromise object. + * + */ sort: function (args) { if (!args) { throw "args cannot be null"; @@ -65,37 +65,37 @@ function mediaResource($q, $http, umbDataFormatter, umbRequestHelper) { } return umbRequestHelper.resourcePromise( - $http.post(umbRequestHelper.getApiUrl("mediaApiBaseUrl", "PostSort"), - { - parentId: args.parentId, - idSortOrder: args.sortedIds - }), - 'Failed to sort media'); + $http.post(umbRequestHelper.getApiUrl("mediaApiBaseUrl", "PostSort"), + { + parentId: args.parentId, + idSortOrder: args.sortedIds + }), + 'Failed to sort media'); }, /** - * @ngdoc method - * @name umbraco.resources.mediaResource#move - * @methodOf umbraco.resources.mediaResource - * - * @description - * Moves a node underneath a new parentId - * - * ##usage - *
-         * mediaResource.move({ parentId: 1244, id: 123 })
-         *    .then(function() {
-         *        alert("node was moved");
-         *    }, function(err){
-         *      alert("node didnt move:" + err.data.Message); 
-         *    });
-         * 
- * @param {Object} args arguments object - * @param {Int} args.idd the ID of the node to move - * @param {Int} args.parentId the ID of the parent node to move to - * @returns {Promise} resourcePromise object. - * - */ + * @ngdoc method + * @name umbraco.resources.mediaResource#move + * @methodOf umbraco.resources.mediaResource + * + * @description + * Moves a node underneath a new parentId + * + * ##usage + *
+          * mediaResource.move({ parentId: 1244, id: 123 })
+          *    .then(function() {
+          *        alert("node was moved");
+          *    }, function(err){
+          *      alert("node didnt move:" + err.data.Message); 
+          *    });
+          * 
+ * @param {Object} args arguments object + * @param {Int} args.idd the ID of the node to move + * @param {Int} args.parentId the ID of the parent node to move to + * @returns {Promise} resourcePromise object. + * + */ move: function (args) { if (!args) { throw "args cannot be null"; @@ -108,196 +108,196 @@ function mediaResource($q, $http, umbDataFormatter, umbRequestHelper) { } return umbRequestHelper.resourcePromise( - $http.post(umbRequestHelper.getApiUrl("mediaApiBaseUrl", "PostMove"), - { - parentId: args.parentId, - id: args.id - }), - 'Failed to move media'); + $http.post(umbRequestHelper.getApiUrl("mediaApiBaseUrl", "PostMove"), + { + parentId: args.parentId, + id: args.id + }), + 'Failed to move media'); }, /** - * @ngdoc method - * @name umbraco.resources.mediaResource#getById - * @methodOf umbraco.resources.mediaResource - * - * @description - * Gets a media item with a given id - * - * ##usage - *
-         * mediaResource.getById(1234)
-         *    .then(function(media) {
-         *        var myMedia = media; 
-         *        alert('its here!');
-         *    });
-         * 
- * - * @param {Int} id id of media item to return - * @returns {Promise} resourcePromise object containing the media item. - * - */ + * @ngdoc method + * @name umbraco.resources.mediaResource#getById + * @methodOf umbraco.resources.mediaResource + * + * @description + * Gets a media item with a given id + * + * ##usage + *
+          * mediaResource.getById(1234)
+          *    .then(function(media) {
+          *        var myMedia = media; 
+          *        alert('its here!');
+          *    });
+          * 
+ * + * @param {Int} id id of media item to return + * @returns {Promise} resourcePromise object containing the media item. + * + */ getById: function (id) { - + return umbRequestHelper.resourcePromise( - $http.get( - umbRequestHelper.getApiUrl( - "mediaApiBaseUrl", - "GetById", - [{ id: id }])), - 'Failed to retrieve data for media id ' + id); + $http.get( + umbRequestHelper.getApiUrl( + "mediaApiBaseUrl", + "GetById", + [{ id: id }])), + 'Failed to retrieve data for media id ' + id); }, /** - * @ngdoc method - * @name umbraco.resources.mediaResource#deleteById - * @methodOf umbraco.resources.mediaResource - * - * @description - * Deletes a media item with a given id - * - * ##usage - *
-         * mediaResource.deleteById(1234)
-         *    .then(function() {
-         *        alert('its gone!');
-         *    });
-         * 
- * - * @param {Int} id id of media item to delete - * @returns {Promise} resourcePromise object. - * - */ - deleteById: function(id) { + * @ngdoc method + * @name umbraco.resources.mediaResource#deleteById + * @methodOf umbraco.resources.mediaResource + * + * @description + * Deletes a media item with a given id + * + * ##usage + *
+          * mediaResource.deleteById(1234)
+          *    .then(function() {
+          *        alert('its gone!');
+          *    });
+          * 
+ * + * @param {Int} id id of media item to delete + * @returns {Promise} resourcePromise object. + * + */ + deleteById: function (id) { return umbRequestHelper.resourcePromise( - $http.post( - umbRequestHelper.getApiUrl( - "mediaApiBaseUrl", - "DeleteById", - [{ id: id }])), - 'Failed to delete item ' + id); + $http.post( + umbRequestHelper.getApiUrl( + "mediaApiBaseUrl", + "DeleteById", + [{ id: id }])), + 'Failed to delete item ' + id); }, /** - * @ngdoc method - * @name umbraco.resources.mediaResource#getByIds - * @methodOf umbraco.resources.mediaResource - * - * @description - * Gets an array of media items, given a collection of ids - * - * ##usage - *
-         * mediaResource.getByIds( [1234,2526,28262])
-         *    .then(function(mediaArray) {
-         *        var myDoc = contentArray; 
-         *        alert('they are here!');
-         *    });
-         * 
- * - * @param {Array} ids ids of media items to return as an array - * @returns {Promise} resourcePromise object containing the media items array. - * - */ + * @ngdoc method + * @name umbraco.resources.mediaResource#getByIds + * @methodOf umbraco.resources.mediaResource + * + * @description + * Gets an array of media items, given a collection of ids + * + * ##usage + *
+          * mediaResource.getByIds( [1234,2526,28262])
+          *    .then(function(mediaArray) {
+          *        var myDoc = contentArray; 
+          *        alert('they are here!');
+          *    });
+          * 
+ * + * @param {Array} ids ids of media items to return as an array + * @returns {Promise} resourcePromise object containing the media items array. + * + */ getByIds: function (ids) { - + var idQuery = ""; - _.each(ids, function(item) { + _.each(ids, function (item) { idQuery += "ids=" + item + "&"; }); return umbRequestHelper.resourcePromise( - $http.get( - umbRequestHelper.getApiUrl( - "mediaApiBaseUrl", - "GetByIds", - idQuery)), - 'Failed to retrieve data for media ids ' + ids); + $http.get( + umbRequestHelper.getApiUrl( + "mediaApiBaseUrl", + "GetByIds", + idQuery)), + 'Failed to retrieve data for media ids ' + ids); }, /** - * @ngdoc method - * @name umbraco.resources.mediaResource#getScaffold - * @methodOf umbraco.resources.mediaResource - * - * @description - * Returns a scaffold of an empty media item, given the id of the media item to place it underneath and the media type alias. - * - * - Parent Id must be provided so umbraco knows where to store the media - * - Media Type alias must be provided so umbraco knows which properties to put on the media scaffold - * - * The scaffold is used to build editors for media that has not yet been populated with data. - * - * ##usage - *
-         * mediaResource.getScaffold(1234, 'folder')
-         *    .then(function(scaffold) {
-         *        var myDoc = scaffold;
-         *        myDoc.name = "My new media item"; 
-         *
-         *        mediaResource.save(myDoc, true)
-         *            .then(function(media){
-         *                alert("Retrieved, updated and saved again");
-         *            });
-         *    });
-         * 
- * - * @param {Int} parentId id of media item to return - * @param {String} alias mediatype alias to base the scaffold on - * @returns {Promise} resourcePromise object containing the media scaffold. - * - */ + * @ngdoc method + * @name umbraco.resources.mediaResource#getScaffold + * @methodOf umbraco.resources.mediaResource + * + * @description + * Returns a scaffold of an empty media item, given the id of the media item to place it underneath and the media type alias. + * + * - Parent Id must be provided so umbraco knows where to store the media + * - Media Type alias must be provided so umbraco knows which properties to put on the media scaffold + * + * The scaffold is used to build editors for media that has not yet been populated with data. + * + * ##usage + *
+          * mediaResource.getScaffold(1234, 'folder')
+          *    .then(function(scaffold) {
+          *        var myDoc = scaffold;
+          *        myDoc.name = "My new media item"; 
+          *
+          *        mediaResource.save(myDoc, true)
+          *            .then(function(media){
+          *                alert("Retrieved, updated and saved again");
+          *            });
+          *    });
+          * 
+ * + * @param {Int} parentId id of media item to return + * @param {String} alias mediatype alias to base the scaffold on + * @returns {Promise} resourcePromise object containing the media scaffold. + * + */ getScaffold: function (parentId, alias) { - + return umbRequestHelper.resourcePromise( - $http.get( - umbRequestHelper.getApiUrl( - "mediaApiBaseUrl", - "GetEmpty", - [{ contentTypeAlias: alias }, { parentId: parentId }])), - 'Failed to retrieve data for empty media item type ' + alias); + $http.get( + umbRequestHelper.getApiUrl( + "mediaApiBaseUrl", + "GetEmpty", + [{ contentTypeAlias: alias }, { parentId: parentId }])), + 'Failed to retrieve data for empty media item type ' + alias); }, rootMedia: function () { - + return umbRequestHelper.resourcePromise( - $http.get( - umbRequestHelper.getApiUrl( - "mediaApiBaseUrl", - "GetRootMedia")), - 'Failed to retrieve data for root media'); + $http.get( + umbRequestHelper.getApiUrl( + "mediaApiBaseUrl", + "GetRootMedia")), + 'Failed to retrieve data for root media'); }, /** - * @ngdoc method - * @name umbraco.resources.mediaResource#getChildren - * @methodOf umbraco.resources.mediaResource - * - * @description - * Gets children of a media item with a given id - * - * ##usage - *
-         * mediaResource.getChildren(1234, {pageSize: 10, pageNumber: 2})
-         *    .then(function(contentArray) {
-         *        var children = contentArray; 
-         *        alert('they are here!');
-         *    });
-         * 
- * - * @param {Int} parentid id of content item to return children of - * @param {Object} options optional options object - * @param {Int} options.pageSize if paging data, number of nodes per page, default = 0 - * @param {Int} options.pageNumber if paging data, current page index, default = 0 - * @param {String} options.filter if provided, query will only return those with names matching the filter - * @param {String} options.orderDirection can be `Ascending` or `Descending` - Default: `Ascending` - * @param {String} options.orderBy property to order items by, default: `SortOrder` - * @returns {Promise} resourcePromise object containing an array of content items. - * - */ + * @ngdoc method + * @name umbraco.resources.mediaResource#getChildren + * @methodOf umbraco.resources.mediaResource + * + * @description + * Gets children of a media item with a given id + * + * ##usage + *
+          * mediaResource.getChildren(1234, {pageSize: 10, pageNumber: 2})
+          *    .then(function(contentArray) {
+          *        var children = contentArray; 
+          *        alert('they are here!');
+          *    });
+          * 
+ * + * @param {Int} parentid id of content item to return children of + * @param {Object} options optional options object + * @param {Int} options.pageSize if paging data, number of nodes per page, default = 0 + * @param {Int} options.pageNumber if paging data, current page index, default = 0 + * @param {String} options.filter if provided, query will only return those with names matching the filter + * @param {String} options.orderDirection can be `Ascending` or `Descending` - Default: `Ascending` + * @param {String} options.orderBy property to order items by, default: `SortOrder` + * @returns {Promise} resourcePromise object containing an array of content items. + * + */ getChildren: function (parentId, options) { var defaults = { @@ -305,7 +305,8 @@ function mediaResource($q, $http, umbDataFormatter, umbRequestHelper) { pageNumber: 0, filter: '', orderDirection: "Ascending", - orderBy: "SortOrder" + orderBy: "SortOrder", + orderBySystemField: true }; if (options === undefined) { options = {}; @@ -322,150 +323,165 @@ function mediaResource($q, $http, umbDataFormatter, umbRequestHelper) { options.orderDirection = "Descending"; } + //converts the value to a js bool + function toBool(v) { + if (angular.isNumber(v)) { + return v > 0; + } + if (angular.isString(v)) { + return v === "true"; + } + if (typeof v === "boolean") { + return v; + } + return false; + } + return umbRequestHelper.resourcePromise( - $http.get( - umbRequestHelper.getApiUrl( - "mediaApiBaseUrl", - "GetChildren", - [ - { id: parentId }, - { pageNumber: options.pageNumber }, - { pageSize: options.pageSize }, - { orderBy: options.orderBy }, - { orderDirection: options.orderDirection }, - { filter: options.filter } - ])), - 'Failed to retrieve children for media item ' + parentId); + $http.get( + umbRequestHelper.getApiUrl( + "mediaApiBaseUrl", + "GetChildren", + [ + { id: parentId }, + { pageNumber: options.pageNumber }, + { pageSize: options.pageSize }, + { orderBy: options.orderBy }, + { orderDirection: options.orderDirection }, + { orderBySystemField: toBool(options.orderBySystemField) }, + { filter: options.filter } + ])), + 'Failed to retrieve children for media item ' + parentId); }, - + /** - * @ngdoc method - * @name umbraco.resources.mediaResource#save - * @methodOf umbraco.resources.mediaResource - * - * @description - * Saves changes made to a media item, if the media item is new, the isNew paramater must be passed to force creation - * if the media item needs to have files attached, they must be provided as the files param and passed separately - * - * - * ##usage - *
-         * mediaResource.getById(1234)
-         *    .then(function(media) {
-         *          media.name = "I want a new name!";
-         *          mediaResource.save(media, false)
-         *            .then(function(media){
-         *                alert("Retrieved, updated and saved again");
-         *            });
-         *    });
-         * 
- * - * @param {Object} media The media item object with changes applied - * @param {Bool} isNew set to true to create a new item or to update an existing - * @param {Array} files collection of files for the media item - * @returns {Promise} resourcePromise object containing the saved media item. - * - */ + * @ngdoc method + * @name umbraco.resources.mediaResource#save + * @methodOf umbraco.resources.mediaResource + * + * @description + * Saves changes made to a media item, if the media item is new, the isNew paramater must be passed to force creation + * if the media item needs to have files attached, they must be provided as the files param and passed separately + * + * + * ##usage + *
+          * mediaResource.getById(1234)
+          *    .then(function(media) {
+          *          media.name = "I want a new name!";
+          *          mediaResource.save(media, false)
+          *            .then(function(media){
+          *                alert("Retrieved, updated and saved again");
+          *            });
+          *    });
+          * 
+ * + * @param {Object} media The media item object with changes applied + * @param {Bool} isNew set to true to create a new item or to update an existing + * @param {Array} files collection of files for the media item + * @returns {Promise} resourcePromise object containing the saved media item. + * + */ save: function (media, isNew, files) { return saveMediaItem(media, "save" + (isNew ? "New" : ""), files); }, /** - * @ngdoc method - * @name umbraco.resources.mediaResource#addFolder - * @methodOf umbraco.resources.mediaResource - * - * @description - * Shorthand for adding a media item of the type "Folder" under a given parent ID - * - * ##usage - *
-         * mediaResource.addFolder("My gallery", 1234)
-         *    .then(function(folder) {
-         *        alert('New folder');
-         *    });
-         * 
- * - * @param {string} name Name of the folder to create - * @param {int} parentId Id of the media item to create the folder underneath - * @returns {Promise} resourcePromise object. - * - */ - addFolder: function(name, parentId){ + * @ngdoc method + * @name umbraco.resources.mediaResource#addFolder + * @methodOf umbraco.resources.mediaResource + * + * @description + * Shorthand for adding a media item of the type "Folder" under a given parent ID + * + * ##usage + *
+          * mediaResource.addFolder("My gallery", 1234)
+          *    .then(function(folder) {
+          *        alert('New folder');
+          *    });
+          * 
+ * + * @param {string} name Name of the folder to create + * @param {int} parentId Id of the media item to create the folder underneath + * @returns {Promise} resourcePromise object. + * + */ + addFolder: function (name, parentId) { return umbRequestHelper.resourcePromise( - $http.post(umbRequestHelper - .getApiUrl("mediaApiBaseUrl", "PostAddFolder"), - { - name: name, - parentId: parentId - }), - 'Failed to add folder'); + $http.post(umbRequestHelper + .getApiUrl("mediaApiBaseUrl", "PostAddFolder"), + { + name: name, + parentId: parentId + }), + 'Failed to add folder'); }, - + /** - * @ngdoc method - * @name umbraco.resources.mediaResource#getChildFolders - * @methodOf umbraco.resources.mediaResource - * - * @description - * Retrieves all media children with types used as folders. - * Uses the convention of looking for media items with mediaTypes ending in - * *Folder so will match "Folder", "bannerFolder", "secureFolder" etc, - * - * ##usage - *
-         * mediaResource.getChildFolders(1234)
-         *    .then(function(data) {
-         *        alert('folders');
-         *    });
-         * 
- * - * @param {int} parentId Id of the media item to query for child folders - * @returns {Promise} resourcePromise object. - * - */ - getChildFolders: function(parentId){ - if(!parentId){ + * @ngdoc method + * @name umbraco.resources.mediaResource#getChildFolders + * @methodOf umbraco.resources.mediaResource + * + * @description + * Retrieves all media children with types used as folders. + * Uses the convention of looking for media items with mediaTypes ending in + * *Folder so will match "Folder", "bannerFolder", "secureFolder" etc, + * + * ##usage + *
+          * mediaResource.getChildFolders(1234)
+          *    .then(function(data) {
+          *        alert('folders');
+          *    });
+          * 
+ * + * @param {int} parentId Id of the media item to query for child folders + * @returns {Promise} resourcePromise object. + * + */ + getChildFolders: function (parentId) { + if (!parentId) { parentId = -1; } - + return umbRequestHelper.resourcePromise( - $http.get( - umbRequestHelper.getApiUrl( - "mediaApiBaseUrl", - "GetChildFolders", - [ - { id: parentId } - ])), - 'Failed to retrieve child folders for media item ' + parentId); + $http.get( + umbRequestHelper.getApiUrl( + "mediaApiBaseUrl", + "GetChildFolders", + [ + { id: parentId } + ])), + 'Failed to retrieve child folders for media item ' + parentId); }, - + /** - * @ngdoc method - * @name umbraco.resources.mediaResource#emptyRecycleBin - * @methodOf umbraco.resources.mediaResource - * - * @description - * Empties the media recycle bin - * - * ##usage - *
-         * mediaResource.emptyRecycleBin()
-         *    .then(function() {
-         *        alert('its empty!');
-         *    });
-         * 
- * - * @returns {Promise} resourcePromise object. - * - */ - emptyRecycleBin: function() { + * @ngdoc method + * @name umbraco.resources.mediaResource#emptyRecycleBin + * @methodOf umbraco.resources.mediaResource + * + * @description + * Empties the media recycle bin + * + * ##usage + *
+          * mediaResource.emptyRecycleBin()
+          *    .then(function() {
+          *        alert('its empty!');
+          *    });
+          * 
+ * + * @returns {Promise} resourcePromise object. + * + */ + emptyRecycleBin: function () { return umbRequestHelper.resourcePromise( - $http.post( - umbRequestHelper.getApiUrl( - "mediaApiBaseUrl", - "EmptyRecycleBin")), - 'Failed to empty the recycle bin'); + $http.post( + umbRequestHelper.getApiUrl( + "mediaApiBaseUrl", + "EmptyRecycleBin")), + 'Failed to empty the recycle bin'); } }; } diff --git a/src/Umbraco.Web.UI.Client/src/common/resources/member.resource.js b/src/Umbraco.Web.UI.Client/src/common/resources/member.resource.js index 42db4f6366..2073307db9 100644 --- a/src/Umbraco.Web.UI.Client/src/common/resources/member.resource.js +++ b/src/Umbraco.Web.UI.Client/src/common/resources/member.resource.js @@ -4,25 +4,25 @@ * @description Loads in data for members **/ function memberResource($q, $http, umbDataFormatter, umbRequestHelper) { - + /** internal method process the saving of data and post processing the result */ function saveMember(content, action, files) { - + return umbRequestHelper.postSaveContent({ restApiUrl: umbRequestHelper.getApiUrl( - "memberApiBaseUrl", - "PostSave"), + "memberApiBaseUrl", + "PostSave"), content: content, action: action, - files: files, - dataFormatter: function(c, a) { + files: files, + dataFormatter: function (c, a) { return umbDataFormatter.formatMemberPostData(c, a); } }); } return { - + getPagedResults: function (memberTypeAlias, options) { if (memberTypeAlias === 'all-members') { @@ -34,7 +34,8 @@ function memberResource($q, $http, umbDataFormatter, umbRequestHelper) { pageNumber: 1, filter: '', orderDirection: "Ascending", - orderBy: "LoginName" + orderBy: "LoginName", + orderBySystemField: true }; if (options === undefined) { options = {}; @@ -51,179 +52,194 @@ function memberResource($q, $http, umbDataFormatter, umbRequestHelper) { options.orderDirection = "Descending"; } + //converts the value to a js bool + function toBool(v) { + if (angular.isNumber(v)) { + return v > 0; + } + if (angular.isString(v)) { + return v === "true"; + } + if (typeof v === "boolean") { + return v; + } + return false; + } + var params = [ - { pageNumber: options.pageNumber }, - { pageSize: options.pageSize }, - { orderBy: options.orderBy }, - { orderDirection: options.orderDirection }, - { filter: options.filter } + { pageNumber: options.pageNumber }, + { pageSize: options.pageSize }, + { orderBy: options.orderBy }, + { orderDirection: options.orderDirection }, + { orderBySystemField: toBool(options.orderBySystemField) }, + { filter: options.filter } ]; if (memberTypeAlias != null) { params.push({ memberTypeAlias: memberTypeAlias }); } return umbRequestHelper.resourcePromise( - $http.get( - umbRequestHelper.getApiUrl( - "memberApiBaseUrl", - "GetPagedResults", - params)), - 'Failed to retrieve member paged result'); + $http.get( + umbRequestHelper.getApiUrl( + "memberApiBaseUrl", + "GetPagedResults", + params)), + 'Failed to retrieve member paged result'); }, - + getListNode: function (listName) { return umbRequestHelper.resourcePromise( - $http.get( - umbRequestHelper.getApiUrl( - "memberApiBaseUrl", - "GetListNodeDisplay", - [{ listName: listName }])), - 'Failed to retrieve data for member list ' + listName); + $http.get( + umbRequestHelper.getApiUrl( + "memberApiBaseUrl", + "GetListNodeDisplay", + [{ listName: listName }])), + 'Failed to retrieve data for member list ' + listName); }, /** - * @ngdoc method - * @name umbraco.resources.memberResource#getByKey - * @methodOf umbraco.resources.memberResource - * - * @description - * Gets a member item with a given key - * - * ##usage - *
-         * memberResource.getByKey("0000-0000-000-00000-000")
-         *    .then(function(member) {
-         *        var mymember = member; 
-         *        alert('its here!');
-         *    });
-         * 
- * - * @param {Guid} key key of member item to return - * @returns {Promise} resourcePromise object containing the member item. - * - */ + * @ngdoc method + * @name umbraco.resources.memberResource#getByKey + * @methodOf umbraco.resources.memberResource + * + * @description + * Gets a member item with a given key + * + * ##usage + *
+          * memberResource.getByKey("0000-0000-000-00000-000")
+          *    .then(function(member) {
+          *        var mymember = member; 
+          *        alert('its here!');
+          *    });
+          * 
+ * + * @param {Guid} key key of member item to return + * @returns {Promise} resourcePromise object containing the member item. + * + */ getByKey: function (key) { - + return umbRequestHelper.resourcePromise( - $http.get( - umbRequestHelper.getApiUrl( - "memberApiBaseUrl", - "GetByKey", - [{ key: key }])), - 'Failed to retrieve data for member id ' + key); + $http.get( + umbRequestHelper.getApiUrl( + "memberApiBaseUrl", + "GetByKey", + [{ key: key }])), + 'Failed to retrieve data for member id ' + key); }, /** - * @ngdoc method - * @name umbraco.resources.memberResource#deleteByKey - * @methodOf umbraco.resources.memberResource - * - * @description - * Deletes a member item with a given key - * - * ##usage - *
-         * memberResource.deleteByKey("0000-0000-000-00000-000")
-         *    .then(function() {
-         *        alert('its gone!');
-         *    });
-         * 
- * - * @param {Guid} key id of member item to delete - * @returns {Promise} resourcePromise object. - * - */ + * @ngdoc method + * @name umbraco.resources.memberResource#deleteByKey + * @methodOf umbraco.resources.memberResource + * + * @description + * Deletes a member item with a given key + * + * ##usage + *
+          * memberResource.deleteByKey("0000-0000-000-00000-000")
+          *    .then(function() {
+          *        alert('its gone!');
+          *    });
+          * 
+ * + * @param {Guid} key id of member item to delete + * @returns {Promise} resourcePromise object. + * + */ deleteByKey: function (key) { return umbRequestHelper.resourcePromise( - $http.post( - umbRequestHelper.getApiUrl( - "memberApiBaseUrl", - "DeleteByKey", - [{ key: key }])), - 'Failed to delete item ' + key); + $http.post( + umbRequestHelper.getApiUrl( + "memberApiBaseUrl", + "DeleteByKey", + [{ key: key }])), + 'Failed to delete item ' + key); }, /** - * @ngdoc method - * @name umbraco.resources.memberResource#getScaffold - * @methodOf umbraco.resources.memberResource - * - * @description - * Returns a scaffold of an empty member item, given the id of the member item to place it underneath and the member type alias. - * - * - Member Type alias must be provided so umbraco knows which properties to put on the member scaffold - * - * The scaffold is used to build editors for member that has not yet been populated with data. - * - * ##usage - *
-         * memberResource.getScaffold('client')
-         *    .then(function(scaffold) {
-         *        var myDoc = scaffold;
-         *        myDoc.name = "My new member item"; 
-         *
-         *        memberResource.save(myDoc, true)
-         *            .then(function(member){
-         *                alert("Retrieved, updated and saved again");
-         *            });
-         *    });
-         * 
- * - * @param {String} alias membertype alias to base the scaffold on - * @returns {Promise} resourcePromise object containing the member scaffold. - * - */ + * @ngdoc method + * @name umbraco.resources.memberResource#getScaffold + * @methodOf umbraco.resources.memberResource + * + * @description + * Returns a scaffold of an empty member item, given the id of the member item to place it underneath and the member type alias. + * + * - Member Type alias must be provided so umbraco knows which properties to put on the member scaffold + * + * The scaffold is used to build editors for member that has not yet been populated with data. + * + * ##usage + *
+          * memberResource.getScaffold('client')
+          *    .then(function(scaffold) {
+          *        var myDoc = scaffold;
+          *        myDoc.name = "My new member item"; 
+          *
+          *        memberResource.save(myDoc, true)
+          *            .then(function(member){
+          *                alert("Retrieved, updated and saved again");
+          *            });
+          *    });
+          * 
+ * + * @param {String} alias membertype alias to base the scaffold on + * @returns {Promise} resourcePromise object containing the member scaffold. + * + */ getScaffold: function (alias) { - + if (alias) { return umbRequestHelper.resourcePromise( - $http.get( - umbRequestHelper.getApiUrl( - "memberApiBaseUrl", - "GetEmpty", - [{ contentTypeAlias: alias }])), - 'Failed to retrieve data for empty member item type ' + alias); + $http.get( + umbRequestHelper.getApiUrl( + "memberApiBaseUrl", + "GetEmpty", + [{ contentTypeAlias: alias }])), + 'Failed to retrieve data for empty member item type ' + alias); } else { return umbRequestHelper.resourcePromise( - $http.get( - umbRequestHelper.getApiUrl( - "memberApiBaseUrl", - "GetEmpty")), - 'Failed to retrieve data for empty member item type ' + alias); + $http.get( + umbRequestHelper.getApiUrl( + "memberApiBaseUrl", + "GetEmpty")), + 'Failed to retrieve data for empty member item type ' + alias); } }, - + /** - * @ngdoc method - * @name umbraco.resources.memberResource#save - * @methodOf umbraco.resources.memberResource - * - * @description - * Saves changes made to a member, if the member is new, the isNew paramater must be passed to force creation - * if the member needs to have files attached, they must be provided as the files param and passed separately - * - * - * ##usage - *
-         * memberResource.getBykey("23234-sd8djsd-3h8d3j-sdh8d")
-         *    .then(function(member) {
-         *          member.name = "Bob";
-         *          memberResource.save(member, false)
-         *            .then(function(member){
-         *                alert("Retrieved, updated and saved again");
-         *            });
-         *    });
-         * 
- * - * @param {Object} media The member item object with changes applied - * @param {Bool} isNew set to true to create a new item or to update an existing - * @param {Array} files collection of files for the media item - * @returns {Promise} resourcePromise object containing the saved media item. - * - */ + * @ngdoc method + * @name umbraco.resources.memberResource#save + * @methodOf umbraco.resources.memberResource + * + * @description + * Saves changes made to a member, if the member is new, the isNew paramater must be passed to force creation + * if the member needs to have files attached, they must be provided as the files param and passed separately + * + * + * ##usage + *
+          * memberResource.getBykey("23234-sd8djsd-3h8d3j-sdh8d")
+          *    .then(function(member) {
+          *          member.name = "Bob";
+          *          memberResource.save(member, false)
+          *            .then(function(member){
+          *                alert("Retrieved, updated and saved again");
+          *            });
+          *    });
+          * 
+ * + * @param {Object} media The member item object with changes applied + * @param {Bool} isNew set to true to create a new item or to update an existing + * @param {Array} files collection of files for the media item + * @returns {Promise} resourcePromise object containing the saved media item. + * + */ save: function (member, isNew, files) { return saveMember(member, "save" + (isNew ? "New" : ""), files); } diff --git a/src/Umbraco.Web.UI.Client/src/common/services/listviewhelper.service.js b/src/Umbraco.Web.UI.Client/src/common/services/listviewhelper.service.js index e211218ce1..0bdc3bb524 100644 --- a/src/Umbraco.Web.UI.Client/src/common/services/listviewhelper.service.js +++ b/src/Umbraco.Web.UI.Client/src/common/services/listviewhelper.service.js @@ -1,3 +1,47 @@ +/** + @ngdoc service + * @name umbraco.services.listViewHelper + * + * + * @description + * Service for performing operations against items in the list view UI. Used by the built-in internal listviews + * as well as custom listview. + * + * A custom listview is always used inside a wrapper listview, so there are a number of inherited values on its + * scope by default: + * + * **$scope.selection**: Array containing all items currently selected in the listview + * + * **$scope.items**: Array containing all items currently displayed in the listview + * + * **$scope.folders**: Array containing all folders in the current listview (only for media) + * + * **$scope.options**: configuration object containing information such as pagesize, permissions, order direction etc. + * + * **$scope.model.config.layouts**: array of available layouts to apply to the listview (grid, list or custom layout) + * + * ##Usage## + * To use, inject listViewHelper into custom listview controller, listviewhelper expects you + * to pass in the full collection of items in the listview in several of its methods + * this collection is inherited from the parent controller and is available on $scope.selection + * + *
+ *      angular.module("umbraco").controller("my.listVieweditor". function($scope, listViewHelper){
+ *
+ *          //current items in the listview
+ *          var items = $scope.items;
+ *
+ *          //current selection
+ *          var selection = $scope.selection;
+ *
+ *          //deselect an item , $scope.selection is inherited, item is picked from inherited $scope.items
+ *          listViewHelper.deselectItem(item, $scope.selection);
+ *
+ *          //test if all items are selected, $scope.items + $scope.selection are inherited
+ *          listViewhelper.isSelectedAll($scope.items, $scope.selection);
+ *      });
+ * 
+ */ (function () { 'use strict'; @@ -6,6 +50,19 @@ var firstSelectedIndex = 0; var localStorageKey = "umblistViewLayout"; + /** + * @ngdoc method + * @name umbraco.services.listViewHelper#getLayout + * @methodOf umbraco.services.listViewHelper + * + * @description + * Method for internal use, based on the collection of layouts passed, the method selects either + * any previous layout from local storage, or picks the first allowed layout + * + * @param {Number} nodeId The id of the current node displayed in the content editor + * @param {Array} availableLayouts Array of all allowed layouts, available from $scope.model.config.layouts + */ + function getLayout(nodeId, availableLayouts) { var storedLayouts = []; @@ -28,6 +85,19 @@ } + /** + * @ngdoc method + * @name umbraco.services.listViewHelper#setLayout + * @methodOf umbraco.services.listViewHelper + * + * @description + * Changes the current layout used by the listview to the layout passed in. Stores selection in localstorage + * + * @param {Number} nodeID Id of the current node displayed in the content editor + * @param {Object} selectedLayout Layout selected as the layout to set as the current layout + * @param {Array} availableLayouts Array of all allowed layouts, available from $scope.model.config.layouts + */ + function setLayout(nodeId, selectedLayout, availableLayouts) { var activeLayout = {}; @@ -54,6 +124,18 @@ } + /** + * @ngdoc method + * @name umbraco.services.listViewHelper#saveLayoutInLocalStorage + * @methodOf umbraco.services.listViewHelper + * + * @description + * Stores a given layout as the current default selection in local storage + * + * @param {Number} nodeId Id of the current node displayed in the content editor + * @param {Object} selectedLayout Layout selected as the layout to set as the current layout + */ + function saveLayoutInLocalStorage(nodeId, selectedLayout) { var layoutFound = false; var storedLayouts = []; @@ -84,6 +166,17 @@ } + /** + * @ngdoc method + * @name umbraco.services.listViewHelper#getFirstAllowedLayout + * @methodOf umbraco.services.listViewHelper + * + * @description + * Returns currently selected layout, or alternatively the first layout in the available layouts collection + * + * @param {Array} layouts Array of all allowed layouts, available from $scope.model.config.layouts + */ + function getFirstAllowedLayout(layouts) { var firstAllowedLayout = {}; @@ -99,6 +192,23 @@ return firstAllowedLayout; } + /** + * @ngdoc method + * @name umbraco.services.listViewHelper#selectHandler + * @methodOf umbraco.services.listViewHelper + * + * @description + * Helper method for working with item selection via a checkbox, internally it uses selectItem and deselectItem. + * Working with this method, requires its triggered via a checkbox which can then pass in its triggered $event + * When the checkbox is clicked, this method will toggle selection of the associated item so it matches the state of the checkbox + * + * @param {Object} selectedItem Item being selected or deselected by the checkbox + * @param {Number} selectedIndex Index of item being selected/deselected, usually passed as $index + * @param {Array} items All items in the current listview, available as $scope.items + * @param {Array} selection All selected items in the current listview, available as $scope.selection + * @param {Event} $event Event triggered by the checkbox being checked to select / deselect an item + */ + function selectHandler(selectedItem, selectedIndex, items, selection, $event) { var start = 0; @@ -143,6 +253,18 @@ } + /** + * @ngdoc method + * @name umbraco.services.listViewHelper#selectItem + * @methodOf umbraco.services.listViewHelper + * + * @description + * Selects a given item to the listview selection array, requires you pass in the inherited $scope.selection collection + * + * @param {Object} item Item to select + * @param {Array} selection Listview selection, available as $scope.selection + */ + function selectItem(item, selection) { var isSelected = false; for (var i = 0; selection.length > i; i++) { @@ -157,6 +279,18 @@ } } + /** + * @ngdoc method + * @name umbraco.services.listViewHelper#deselectItem + * @methodOf umbraco.services.listViewHelper + * + * @description + * Deselects a given item from the listviews selection array, requires you pass in the inherited $scope.selection collection + * + * @param {Object} item Item to deselect + * @param {Array} selection Listview selection, available as $scope.selection + */ + function deselectItem(item, selection) { for (var i = 0; selection.length > i; i++) { var selectedItem = selection[i]; @@ -167,6 +301,20 @@ } } + /** + * @ngdoc method + * @name umbraco.services.listViewHelper#clearSelection + * @methodOf umbraco.services.listViewHelper + * + * @description + * Removes a given number of items and folders from the listviews selection array + * Folders can only be passed in if the listview is used in the media section which has a concept of folders. + * + * @param {Array} items Items to remove, can be null + * @param {Array} folders Folders to remove, can be null + * @param {Array} selection Listview selection, available as $scope.selection + */ + function clearSelection(items, folders, selection) { var i = 0; @@ -180,7 +328,7 @@ } } - if (angular.isArray(items)) { + if(angular.isArray(folders)) { for (i = 0; folders.length > i; i++) { var folder = folders[i]; folder.selected = false; @@ -188,6 +336,20 @@ } } + /** + * @ngdoc method + * @name umbraco.services.listViewHelper#selectAllItems + * @methodOf umbraco.services.listViewHelper + * + * @description + * Helper method for toggling the select state on all items in the active listview + * Can only be used from a checkbox as a checkbox $event is required to pass in. + * + * @param {Array} items Items to toggle selection on, should be $scope.items + * @param {Array} selection Listview selection, available as $scope.selection + * @param {$event} $event Event passed from the checkbox being toggled + */ + function selectAllItems(items, selection, $event) { var checkbox = $event.target; @@ -219,6 +381,20 @@ } + /** + * @ngdoc method + * @name umbraco.services.listViewHelper#isSelectedAll + * @methodOf umbraco.services.listViewHelper + * + * @description + * Method to determine if all items on the current page in the list has been selected + * Given the current items in the view, and the current selection, it will return true/false + * + * @param {Array} items Items to test if all are selected, should be $scope.items + * @param {Array} selection Listview selection, available as $scope.selection + * @returns {Boolean} boolean indicate if all items in the listview have been selected + */ + function isSelectedAll(items, selection) { var numberOfSelectedItem = 0; @@ -242,27 +418,51 @@ } + /** + * @ngdoc method + * @name umbraco.services.listViewHelper#setSortingDirection + * @methodOf umbraco.services.listViewHelper + * + * @description + * *Internal* method for changing sort order icon + * @param {String} col Column alias to order after + * @param {String} direction Order direction `asc` or `desc` + * @param {Object} options object passed from the parent listview available as $scope.options + */ + function setSortingDirection(col, direction, options) { return options.orderBy.toUpperCase() === col.toUpperCase() && options.orderDirection === direction; } + /** + * @ngdoc method + * @name umbraco.services.listViewHelper#setSorting + * @methodOf umbraco.services.listViewHelper + * + * @description + * Method for setting the field on which the listview will order its items after. + * + * @param {String} field Field alias to order after + * @param {Boolean} allow Determines if the user is allowed to set this field, normally true + * @param {Object} options Options object passed from the parent listview available as $scope.options + */ + function setSorting(field, allow, options) { if (allow) { - options.orderBy = field; - - if (options.orderDirection === "desc") { - options.orderDirection = "asc"; - } else { + if (options.orderBy === field && options.orderDirection === 'asc') { options.orderDirection = "desc"; + } else { + options.orderDirection = "asc"; } + options.orderBy = field; } } - + //This takes in a dictionary of Ids with Permissions and determines // the intersect of all permissions to return an object representing the // listview button permissions function getButtonPermissions(unmergedPermissions, currentIdsWithPermissions) { - + if (currentIdsWithPermissions == null) { currentIdsWithPermissions = {}; } @@ -286,26 +486,28 @@ canCopy: _.contains(intersectPermissions, 'O'), //Magic Char = O canCreate: _.contains(intersectPermissions, 'C'), //Magic Char = C canDelete: _.contains(intersectPermissions, 'D'), //Magic Char = D - canMove: _.contains(intersectPermissions, 'M'), //Magic Char = M + canMove: _.contains(intersectPermissions, 'M'), //Magic Char = M canPublish: _.contains(intersectPermissions, 'U'), //Magic Char = U - canUnpublish: _.contains(intersectPermissions, 'U'), //Magic Char = Z (however UI says it can't be set, so if we can publish 'U' we can unpublish) + canUnpublish: _.contains(intersectPermissions, 'U'), //Magic Char = Z (however UI says it can't be set, so if we can publish 'U' we can unpublish) }; } var service = { - getLayout: getLayout, - getFirstAllowedLayout: getFirstAllowedLayout, - setLayout: setLayout, - saveLayoutInLocalStorage: saveLayoutInLocalStorage, - selectHandler: selectHandler, - selectItem: selectItem, - deselectItem: deselectItem, - clearSelection: clearSelection, - selectAllItems: selectAllItems, - isSelectedAll: isSelectedAll, - setSortingDirection: setSortingDirection, - setSorting: setSorting, - getButtonPermissions: getButtonPermissions + + getLayout: getLayout, + getFirstAllowedLayout: getFirstAllowedLayout, + setLayout: setLayout, + saveLayoutInLocalStorage: saveLayoutInLocalStorage, + selectHandler: selectHandler, + selectItem: selectItem, + deselectItem: deselectItem, + clearSelection: clearSelection, + selectAllItems: selectAllItems, + isSelectedAll: isSelectedAll, + setSortingDirection: setSortingDirection, + setSorting: setSorting, + getButtonPermissions: getButtonPermissions + }; return service; diff --git a/src/Umbraco.Web.UI.Client/src/common/services/menuactions.service.js b/src/Umbraco.Web.UI.Client/src/common/services/menuactions.service.js index bcfb5df0a7..c7438a1c47 100644 --- a/src/Umbraco.Web.UI.Client/src/common/services/menuactions.service.js +++ b/src/Umbraco.Web.UI.Client/src/common/services/menuactions.service.js @@ -8,10 +8,21 @@ * @description * Defines the methods that are called when menu items declare only an action to execute */ -function umbracoMenuActions($q, treeService, $location, navigationService, appState) { +function umbracoMenuActions($q, treeService, $location, navigationService, appState, localizationService, userResource) { return { + "DisableUser": function(args) { + localizationService.localize("defaultdialogs_confirmdisable").then(function (txtConfirmDisable) { + var currentMenuNode = UmbClientMgr.mainTree().getActionNode(); + if (confirm(txtConfirmDisable + ' "' + args.entity.name + '"?\n\n')) { + userResource.disableUser(args.entity.id).then(function () { + navigationService.syncTree({ tree: args.treeAlias, path: [args.entity.parentId, args.entity.id], forceReload: true }); + }); + } + }); + }, + /** * @ngdoc method * @name umbraco.services.umbracoMenuActions#RefreshNode diff --git a/src/Umbraco.Web.UI.Client/src/common/services/user.service.js b/src/Umbraco.Web.UI.Client/src/common/services/user.service.js index 3fb291619d..dffda24f1d 100644 --- a/src/Umbraco.Web.UI.Client/src/common/services/user.service.js +++ b/src/Umbraco.Web.UI.Client/src/common/services/user.service.js @@ -211,7 +211,7 @@ angular.module('umbraco.services') return result; }); }, - + /** Logs the user out */ logout: function () { diff --git a/src/Umbraco.Web.UI.Client/src/less/components/umb-content-grid.less b/src/Umbraco.Web.UI.Client/src/less/components/umb-content-grid.less index b34face8ba..aef523887c 100644 --- a/src/Umbraco.Web.UI.Client/src/less/components/umb-content-grid.less +++ b/src/Umbraco.Web.UI.Client/src/less/components/umb-content-grid.less @@ -26,7 +26,9 @@ justify-content: center; } -.umb-content-grid__icon { +.umb-content-grid__icon, +.umb-content-grid__icon[class^="icon-"], +.umb-content-grid__icon[class*=" icon-"] { font-size: 40px; color: lighten(@gray, 20%); } diff --git a/src/Umbraco.Web.UI.Client/src/less/components/umb-folder-grid.less b/src/Umbraco.Web.UI.Client/src/less/components/umb-folder-grid.less index 14e343652d..c7c7fb78e5 100644 --- a/src/Umbraco.Web.UI.Client/src/less/components/umb-folder-grid.less +++ b/src/Umbraco.Web.UI.Client/src/less/components/umb-folder-grid.less @@ -37,7 +37,9 @@ align-items: center; } -.umb-folder-grid__folder-icon { +.umb-folder-grid__folder-icon, +.umb-folder-grid__folder-icon[class^="icon-"], +.umb-folder-grid__folder-icon[class*=" icon-"] { font-size: 20px; margin-right: 15px; color: @black; diff --git a/src/Umbraco.Web.UI.Client/src/less/components/umb-layout-selector.less b/src/Umbraco.Web.UI.Client/src/less/components/umb-layout-selector.less index 122107f88c..74d85461fa 100644 --- a/src/Umbraco.Web.UI.Client/src/less/components/umb-layout-selector.less +++ b/src/Umbraco.Web.UI.Client/src/less/components/umb-layout-selector.less @@ -51,7 +51,9 @@ border: 1px solid @blue; } -.umb-layout-selector__dropdown-item-icon { +.umb-layout-selector__dropdown-item-icon, +.umb-layout-selector__dropdown-item-icon[class^="icon-"], +.umb-layout-selector__dropdown-item-icon[class*=" icon-"] { font-size: 20px; color: @gray; text-align: center; diff --git a/src/Umbraco.Web.UI.Client/src/less/components/umb-table.less b/src/Umbraco.Web.UI.Client/src/less/components/umb-table.less index e94aa81898..874f9e9551 100644 --- a/src/Umbraco.Web.UI.Client/src/less/components/umb-table.less +++ b/src/Umbraco.Web.UI.Client/src/less/components/umb-table.less @@ -85,7 +85,7 @@ input.umb-table__input { .umb-table-body .umb-table-row { color: fade(@gray, 75%); border-top: 1px solid @grayLight; - + cursor: pointer; font-size: 13px; &:hover { @@ -101,16 +101,21 @@ input.umb-table__input { } } -.umb-table-body__icon { +.umb-table-body__icon, +.umb-table-body__icon[class^="icon-"], +.umb-table-body__icon[class*=" icon-"] { margin: 0 auto; - font-size: 22px; + line-height: 22px; color: @blueDark; } -.umb-table-body__checkicon { +.umb-table-body__checkicon, +.umb-table-body__checkicon[class^="icon-"], +.umb-table-body__checkicon[class*=" icon-"] { display: none; font-size: 16px; + line-height: 22px; } .umb-table-body .umb-table__name { @@ -205,8 +210,6 @@ input.umb-table__input { overflow: hidden; white-space: nowrap; //NOTE Disable/Enable this to keep textstring on one line text-overflow: ellipsis; - - cursor: default; } .umb-table-cell:first-of-type { diff --git a/src/Umbraco.Web.UI.Client/src/less/listview.less b/src/Umbraco.Web.UI.Client/src/less/listview.less index b6efa9567f..88762edf0c 100644 --- a/src/Umbraco.Web.UI.Client/src/less/listview.less +++ b/src/Umbraco.Web.UI.Client/src/less/listview.less @@ -243,7 +243,8 @@ background-color: @grayLighter } -.table-striped tbody i:hover { +/* don't hide all icons, e.g. for a sortable handle */ +.umb-listview .table-striped tbody i:not(.handle):hover { display: none !important } diff --git a/src/Umbraco.Web.UI.Client/src/less/pages/login.less b/src/Umbraco.Web.UI.Client/src/less/pages/login.less index 081a194b7e..6805783a86 100644 --- a/src/Umbraco.Web.UI.Client/src/less/pages/login.less +++ b/src/Umbraco.Web.UI.Client/src/less/pages/login.less @@ -66,7 +66,7 @@ font-weight: normal; } -.login-overlay .alert.alert-error { +.login-overlay .alert { display: inline-block; padding-right: 6px; padding-left: 6px; @@ -74,6 +74,10 @@ text-align: center; } +.login-overlay .switch-view { + margin-top: 10px; +} + @media (max-width: 565px) { // Remove padding on login-form on smaller devices .login-overlay .form { @@ -108,3 +112,9 @@ margin: auto; color: @grayLight; } + +.login-overlay .text-error, +.login-overlay .text-info +{ + font-weight:bold; +} diff --git a/src/Umbraco.Web.UI.Client/src/less/property-editors.less b/src/Umbraco.Web.UI.Client/src/less/property-editors.less index f274740020..a06484b8a0 100644 --- a/src/Umbraco.Web.UI.Client/src/less/property-editors.less +++ b/src/Umbraco.Web.UI.Client/src/less/property-editors.less @@ -714,7 +714,45 @@ ul.color-picker li a { } // -// tags +// Related links +// -------------------------------------------------- +.umb-relatedlinks table > tr > td { word-wrap:break-word; word-break: break-all; border-bottom: 1px solid transparent; } +.umb-relatedlinks .handle { cursor:move; } +.umb-relatedlinks table > tbody > tr.unsortable .handle { cursor:default; } + +.umb-relatedlinks table td.col-sort { width: 20px; } +.umb-relatedlinks table td.col-caption { min-width: 200px; } +.umb-relatedlinks table td.col-link { min-width: 200px; } +.umb-relatedlinks table td.col-actions { min-width: 120px; } + +.umb-relatedlinks table td.col-caption .control-wrapper, +.umb-relatedlinks table td.col-link .control-wrapper { display: flex; } + +.umb-relatedlinks table td.col-caption .control-wrapper input[type="text"], +.umb-relatedlinks table td.col-link .control-wrapper input[type="text"] { width: auto; flex: 1; } + +/* sortable placeholder */ +.umb-relatedlinks .sortable-placeholder { + background-color: @tableBackgroundAccent; + display: table-row; +} +.umb-relatedlinks .sortable-placeholder > td { + display: table-cell; + padding: 8px; +} +.umb-relatedlinks .ui-sortable-helper { + display: table-row; + background-color: @white; + opacity: 0.7; +} +.umb-relatedlinks .ui-sortable-helper > td { + display: table-cell; + border-bottom: 1px solid @tableBorder; +} + + +// +// Tags // -------------------------------------------------- .umb-tags{border: @grayLighter solid 1px; padding: 10px; font-size: 13px; text-shadow: none;} .umb-tags .tag{cursor: pointer; margin: 7px; padding: 7px; background: @blue} diff --git a/src/Umbraco.Web.UI.Client/src/less/tree.less b/src/Umbraco.Web.UI.Client/src/less/tree.less index 185b5a6e3b..35de441137 100644 --- a/src/Umbraco.Web.UI.Client/src/less/tree.less +++ b/src/Umbraco.Web.UI.Client/src/less/tree.less @@ -418,9 +418,9 @@ div.locked:before{ padding-left: 10px; } .umb-actions-child li .menu-label { - font-size: 12px; + font-size: 14px; color: #000; - margin-left: 20px; + margin-left: 10px; } .umb-actions-child li .menu-label small { @@ -436,6 +436,9 @@ div.locked:before{ } .umb-actions-child i { font-size: 32px; + min-width: 32px; + text-align: center; + line-height: 24px; /* set line-height to ensure all icons use same line-height */ } .umb-actions-child li.add { diff --git a/src/Umbraco.Web.UI.Client/src/routes.js b/src/Umbraco.Web.UI.Client/src/routes.js index 5d641fcb6c..69e6779a15 100644 --- a/src/Umbraco.Web.UI.Client/src/routes.js +++ b/src/Umbraco.Web.UI.Client/src/routes.js @@ -93,10 +93,10 @@ app.config(function ($routeProvider) { //ensure auth is *not* required so it will redirect to / resolve: canRoute(false) }) - .when('/logout', { + .when('/logout', { redirectTo: '/login/false', - resolve: doLogout() - }) + resolve: doLogout() + }) .when('/:section', { templateUrl: function (rp) { if (rp.section.toLowerCase() === "default" || rp.section.toLowerCase() === "umbraco" || rp.section === "") diff --git a/src/Umbraco.Web.UI.Client/src/views/common/dialogs/login.controller.js b/src/Umbraco.Web.UI.Client/src/views/common/dialogs/login.controller.js index 325af02bbc..c38c55fcfb 100644 --- a/src/Umbraco.Web.UI.Client/src/views/common/dialogs/login.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/common/dialogs/login.controller.js @@ -1,22 +1,56 @@ angular.module("umbraco").controller("Umbraco.Dialogs.LoginController", - function ($scope, $cookies, localizationService, userService, externalLoginInfo) { + function ($scope, $cookies, localizationService, userService, externalLoginInfo, resetPasswordCodeInfo, $timeout, authResource) { - /** - * @ngdoc function - * @name signin - * @methodOf MainController - * @function - * - * @description - * signs the user in - */ + var setFieldFocus = function(form, field) { + $timeout(function() { + $("form[name='" + form + "'] input[name='" + field + "']").focus(); + }); + } + function resetInputValidation() { + $scope.confirmPassword = ""; + $scope.password = ""; + $scope.login = ""; + if ($scope.loginForm) { + $scope.loginForm.username.$setValidity('auth', true); + $scope.loginForm.password.$setValidity('auth', true); + } + if ($scope.requestPasswordResetForm) { + $scope.requestPasswordResetForm.email.$setValidity("auth", true); + } + if ($scope.setPasswordForm) { + $scope.setPasswordForm.password.$setValidity('auth', true); + $scope.setPasswordForm.confirmPassword.$setValidity('auth', true); + } + } + $scope.allowPasswordReset = Umbraco.Sys.ServerVariables.umbracoSettings.allowPasswordReset; + + $scope.showLogin = function () { + $scope.errorMsg = ""; + resetInputValidation(); + $scope.view = "login"; + setFieldFocus("loginForm", "username"); + } + + $scope.showRequestPasswordReset = function () { + $scope.errorMsg = ""; + resetInputValidation(); + $scope.view = "request-password-reset"; + $scope.showEmailResetConfirmation = false; + setFieldFocus("requestPasswordResetForm", "email"); + } + + $scope.showSetPassword = function () { + $scope.errorMsg = ""; + resetInputValidation(); + $scope.view = "set-password"; + setFieldFocus("setPasswordForm", "password"); + } var d = new Date(); var konamiGreetings = new Array("Suze Sunday", "Malibu Monday", "Tequila Tuesday", "Whiskey Wednesday", "Negroni Day", "Fernet Friday", "Sancerre Saturday"); var konamiMode = $cookies.konamiLogin; - //var weekday = new Array("Super Sunday", "Manic Monday", "Tremendous Tuesday", "Wonderful Wednesday", "Thunder Thursday", "Friendly Friday", "Shiny Saturday"); if (konamiMode == "1") { $scope.greeting = "Happy " + konamiGreetings[d.getDay()]; } else { @@ -29,6 +63,7 @@ $scope.externalLoginFormAction = Umbraco.Sys.ServerVariables.umbracoUrls.externalLoginsUrl; $scope.externalLoginProviders = externalLoginInfo.providers; $scope.externalLoginInfo = externalLoginInfo; + $scope.resetPasswordCodeInfo = resetPasswordCodeInfo; $scope.activateKonamiMode = function () { if ($cookies.konamiLogin == "1") { @@ -48,13 +83,12 @@ //if the login and password are not empty we need to automatically // validate them - this is because if there are validation errors on the server // then the user has to change both username & password to resubmit which isn't ideal, - // so if they're not empty , we'l just make sure to set them to valid. + // so if they're not empty, we'll just make sure to set them to valid. if (login && password && login.length > 0 && password.length > 0) { $scope.loginForm.username.$setValidity('auth', true); $scope.loginForm.password.$setValidity('auth', true); } - if ($scope.loginForm.$invalid) { return; } @@ -84,4 +118,88 @@ } }); }; + + $scope.requestPasswordResetSubmit = function (email) { + + $scope.errorMsg = ""; + $scope.showEmailResetConfirmation = false; + + if ($scope.requestPasswordResetForm.$invalid) { + return; + } + + authResource.performRequestPasswordReset(email) + .then(function () { + //remove the email entered + $scope.email = ""; + $scope.showEmailResetConfirmation = true; + }, function (reason) { + $scope.errorMsg = reason.errorMsg; + $scope.requestPasswordResetForm.email.$setValidity("auth", false); + }); + + $scope.requestPasswordResetForm.email.$viewChangeListeners.push(function () { + if ($scope.requestPasswordResetForm.email.$invalid) { + $scope.requestPasswordResetForm.email.$setValidity('auth', true); + } + }); + }; + + $scope.setPasswordSubmit = function (password, confirmPassword) { + + $scope.showSetPasswordConfirmation = false; + + if (password && confirmPassword && password.length > 0 && confirmPassword.length > 0) { + $scope.setPasswordForm.password.$setValidity('auth', true); + $scope.setPasswordForm.confirmPassword.$setValidity('auth', true); + } + + if ($scope.setPasswordForm.$invalid) { + return; + } + + authResource.performSetPassword($scope.resetPasswordCodeInfo.resetCodeModel.userId, password, confirmPassword, $scope.resetPasswordCodeInfo.resetCodeModel.resetCode) + .then(function () { + $scope.showSetPasswordConfirmation = true; + $scope.resetComplete = true; + + //reset the values in the resetPasswordCodeInfo angular so if someone logs out the change password isn't shown again + resetPasswordCodeInfo.resetCodeModel = null; + + }, function (reason) { + if (reason.data && reason.data.Message) { + $scope.errorMsg = reason.data.Message; + } + else { + $scope.errorMsg = reason.errorMsg; + } + $scope.setPasswordForm.password.$setValidity("auth", false); + $scope.setPasswordForm.confirmPassword.$setValidity("auth", false); + }); + + $scope.setPasswordForm.password.$viewChangeListeners.push(function () { + if ($scope.setPasswordForm.password.$invalid) { + $scope.setPasswordForm.password.$setValidity('auth', true); + } + }); + $scope.setPasswordForm.confirmPassword.$viewChangeListeners.push(function () { + if ($scope.setPasswordForm.confirmPassword.$invalid) { + $scope.setPasswordForm.confirmPassword.$setValidity('auth', true); + } + }); + } + + + //Now, show the correct panel: + + if ($scope.resetPasswordCodeInfo.resetCodeModel) { + $scope.showSetPassword(); + } + else if ($scope.resetPasswordCodeInfo.errors.length > 0) { + $scope.view = "password-reset-code-expired"; + } + else { + $scope.showLogin(); + } + }); diff --git a/src/Umbraco.Web.UI.Client/src/views/common/dialogs/login.html b/src/Umbraco.Web.UI.Client/src/views/common/dialogs/login.html index 3ca9bcda10..12f25f42a5 100644 --- a/src/Umbraco.Web.UI.Client/src/views/common/dialogs/login.html +++ b/src/Umbraco.Web.UI.Client/src/views/common/dialogs/login.html @@ -1,55 +1,135 @@ 
-
+

{{greeting}}

-

- Log in below. - Log in below -

- -
- -
- {{error}} + +
+ +

+ Log in below. + Log in below +

+ +
+ +
+ {{error}} +
+ +
+ +
+ + + +
+
+ +
+
+
Or
+
+
-
+ +
+ +
-
+
+ +
+ +
+
{{errorMsg}}
+
- + + - -
-
Or
-
-
-
-
- -
+
+

+ An email will be sent to the address specified with a link to reset your password +

-
- -
+ +
+ +
+ +
+
{{errorMsg}}
+
+ +
+
+ An email with password reset instructions will be sent to the specified address if it matched our records +
+
- + -
-
{{errorMsg}}
+ + +
+ +
+ +

+ Please provide a new password. +

+ +
+ +
+ +
+ +
+ +
+ +
+
{{errorMsg}}
+
+ +
+
+ Your new password has been set and you may now use it to log in. +
+
+ + + + +
+
+ +
+
+ {{error}}
- - + + +
\ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/views/common/overlays/mediaPicker/mediapicker.controller.js b/src/Umbraco.Web.UI.Client/src/views/common/overlays/mediaPicker/mediapicker.controller.js index a63dfdc951..774e14f50e 100644 --- a/src/Umbraco.Web.UI.Client/src/views/common/overlays/mediaPicker/mediapicker.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/common/overlays/mediaPicker/mediapicker.controller.js @@ -16,7 +16,12 @@ angular.module("umbraco") $scope.startNodeId = dialogOptions.startNodeId ? dialogOptions.startNodeId : -1; $scope.cropSize = dialogOptions.cropSize; $scope.lastOpenedNode = $cookieStore.get("umbLastOpenedMediaNodeId"); - $scope.acceptedFileTypes = mediaHelper.formatFileTypes(Umbraco.Sys.ServerVariables.umbracoSettings.imageFileTypes); + if($scope.onlyImages){ + $scope.acceptedFileTypes = mediaHelper.formatFileTypes(Umbraco.Sys.ServerVariables.umbracoSettings.imageFileTypes); + } + else { + $scope.acceptedFileTypes = !mediaHelper.formatFileTypes(Umbraco.Sys.ServerVariables.umbracoSettings.disallowedUploadFiles); + } $scope.maxFileSize = Umbraco.Sys.ServerVariables.umbracoSettings.maxFileSize + "KB"; $scope.model.selectedImages = []; diff --git a/src/Umbraco.Web.UI.Client/src/views/common/overlays/mediaPicker/mediapicker.html b/src/Umbraco.Web.UI.Client/src/views/common/overlays/mediaPicker/mediapicker.html index 5bcbfbb3d2..51f05fea00 100644 --- a/src/Umbraco.Web.UI.Client/src/views/common/overlays/mediaPicker/mediapicker.html +++ b/src/Umbraco.Web.UI.Client/src/views/common/overlays/mediaPicker/mediapicker.html @@ -80,7 +80,8 @@ item-max-width="150" item-max-height="150" item-min-width="100" - item-min-height="100"> + item-min-height="100" + only-images={{onlyImages}}>
diff --git a/src/Umbraco.Web.UI.Client/src/views/common/overlays/ysod/ysod.controller.js b/src/Umbraco.Web.UI.Client/src/views/common/overlays/ysod/ysod.controller.js index a6d66a0f99..5d42edd3a5 100644 --- a/src/Umbraco.Web.UI.Client/src/views/common/overlays/ysod/ysod.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/common/overlays/ysod/ysod.controller.js @@ -10,4 +10,16 @@ angular.module("umbraco") $scope.model.error.data.StackTrace = $scope.model.error.data.StackTrace.trim(); } + if ($scope.model.error && $scope.model.error.data) { + $scope.model.error.data.InnerExceptions = []; + var ex = $scope.model.error.data.InnerException; + while (ex) { + if (ex.StackTrace) { + ex.StackTrace = ex.StackTrace.trim(); + } + $scope.model.error.data.InnerExceptions.push(ex); + ex = ex.InnerException; + } + } + }); diff --git a/src/Umbraco.Web.UI.Client/src/views/common/overlays/ysod/ysod.html b/src/Umbraco.Web.UI.Client/src/views/common/overlays/ysod/ysod.html index 6c35763069..9a4ff7cb81 100644 --- a/src/Umbraco.Web.UI.Client/src/views/common/overlays/ysod/ysod.html +++ b/src/Umbraco.Web.UI.Client/src/views/common/overlays/ysod/ysod.html @@ -16,4 +16,12 @@
{{model.error.data.StackTrace}}
+ +
+
+ Inner Exception: +
+
{{e.ExceptionType}}: {{e.ExceptionMessage}}
+
{{e.StackTrace}}
+
diff --git a/src/Umbraco.Web.UI.Client/src/views/components/umb-content-grid.html b/src/Umbraco.Web.UI.Client/src/views/components/umb-content-grid.html index 7443cdd393..499594253e 100644 --- a/src/Umbraco.Web.UI.Client/src/views/components/umb-content-grid.html +++ b/src/Umbraco.Web.UI.Client/src/views/components/umb-content-grid.html @@ -9,7 +9,7 @@
- +
diff --git a/src/Umbraco.Web.UI.Client/src/views/components/umb-layout-selector.html b/src/Umbraco.Web.UI.Client/src/views/components/umb-layout-selector.html index a7b2e0e556..c7dba13bae 100644 --- a/src/Umbraco.Web.UI.Client/src/views/components/umb-layout-selector.html +++ b/src/Umbraco.Web.UI.Client/src/views/components/umb-layout-selector.html @@ -5,10 +5,9 @@
- -
- -
+
+ +
diff --git a/src/Umbraco.Web.UI.Client/src/views/components/umb-table.html b/src/Umbraco.Web.UI.Client/src/views/components/umb-table.html index fdd7dd23c9..fb5e992d81 100644 --- a/src/Umbraco.Web.UI.Client/src/views/components/umb-table.html +++ b/src/Umbraco.Web.UI.Client/src/views/components/umb-table.html @@ -1,76 +1,60 @@ -
- -
- - -
-
- -
- -
- - - - - -
-
- - -
-
- - -
- - -
- -
- - -
- -
- {{item[column.alias]}} -
- -
-
- -
- - - - There are no items show in the list. - - -
+
+
+ +
+
+
+ +
+ + +
+
+ +
+
+ +
+ + +
+
+ + +
+
+ {{item[column.alias]}} +
+
+
+
+ + + There are no items show in the list. + +
diff --git a/src/Umbraco.Web.UI.Client/src/views/components/upload/umb-file-dropzone.html b/src/Umbraco.Web.UI.Client/src/views/components/upload/umb-file-dropzone.html index c1d5ad9de8..60cec9996f 100644 --- a/src/Umbraco.Web.UI.Client/src/views/components/upload/umb-file-dropzone.html +++ b/src/Umbraco.Web.UI.Client/src/views/components/upload/umb-file-dropzone.html @@ -78,12 +78,12 @@ {{ file.name }} - (: "{{ accept }}") - ( "{{maxFileSize}}") + + "{{maxFileSize}}" - ({{file.serverErrorMessage}}) + {{file.serverErrorMessage}}
diff --git a/src/Umbraco.Web.UI.Client/src/views/dashboard/settings/settingsdashboardintro.html b/src/Umbraco.Web.UI.Client/src/views/dashboard/settings/settingsdashboardintro.html index 16bb80c0d1..fa9849022c 100644 --- a/src/Umbraco.Web.UI.Client/src/views/dashboard/settings/settingsdashboardintro.html +++ b/src/Umbraco.Web.UI.Client/src/views/dashboard/settings/settingsdashboardintro.html @@ -1,13 +1,13 @@

Start here

This section contains the building blocks for your Umbraco site

-

Follow the below links to find out more about working with the items in the Setings section:

+

Follow the below links to find out more about working with the items in the Settings section:

Find out more:

    -
  • Read more about working with the Items in Settings in the Community Wiki
  • -
  • Download the Editors Manual for details on working with the Umbraco UI
  • -
  • Ask a question in the Community Forum
  • +
  • Read more about working with the Items in Settings in the Documentation section of Our Umbraco
  • +
  • Download the Editors Manual for details on working with the Umbraco UI
  • +
  • Ask a question in the Community Forum
  • Watch our tutorial videos (some are free, some require a subscription)
  • Find out about our productivity boosting tools and commercial support
  • Find out about real-life training and certification opportunities
  • diff --git a/src/Umbraco.Web.UI.Client/src/views/documenttypes/edit.controller.js b/src/Umbraco.Web.UI.Client/src/views/documenttypes/edit.controller.js index 8132f50b58..0b304aaef4 100644 --- a/src/Umbraco.Web.UI.Client/src/views/documenttypes/edit.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/documenttypes/edit.controller.js @@ -145,7 +145,8 @@ contentTypeHelper.generateModels().then(function (result) { - if (result.success) { + // generateModels() returns the dashboard content + if (!result.lastError) { //re-check model status contentTypeHelper.checkModelsBuilderStatus().then(function(statusResult) { diff --git a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/listview/layouts/grid/grid.listviewlayout.controller.js b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/listview/layouts/grid/grid.listviewlayout.controller.js index e1754dd89d..24c00ebe1d 100644 --- a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/listview/layouts/grid/grid.listviewlayout.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/listview/layouts/grid/grid.listviewlayout.controller.js @@ -14,10 +14,8 @@ var vm = this; vm.nodeId = $scope.contentId; - //vm.acceptedFileTypes = mediaHelper.formatFileTypes(Umbraco.Sys.ServerVariables.umbracoSettings.imageFileTypes); - //instead of passing in a whitelist, we pass in a blacklist by adding ! to the ext - vm.acceptedFileTypes = mediaHelper.formatFileTypes(Umbraco.Sys.ServerVariables.umbracoSettings.disallowedUploadFiles).replace(/\./g, "!."); - + //we pass in a blacklist by adding ! to the file extensions, allowing everything EXCEPT for disallowedUploadFiles + vm.acceptedFileTypes = !mediaHelper.formatFileTypes(Umbraco.Sys.ServerVariables.umbracoSettings.disallowedUploadFiles); vm.maxFileSize = Umbraco.Sys.ServerVariables.umbracoSettings.maxFileSize + "KB"; vm.activeDrag = false; vm.mediaDetailsTooltip = {}; diff --git a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/listview/layouts/list/list.listviewlayout.controller.js b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/listview/layouts/list/list.listviewlayout.controller.js index 1d2d361f28..660bd38ce7 100644 --- a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/listview/layouts/list/list.listviewlayout.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/listview/layouts/list/list.listviewlayout.controller.js @@ -1,75 +1,75 @@ -(function() { - "use strict"; +(function () { + "use strict"; - function ListViewListLayoutController($scope, listViewHelper, $location, mediaHelper) { + function ListViewListLayoutController($scope, listViewHelper, $location, mediaHelper) { - var vm = this; + var vm = this; - vm.nodeId = $scope.contentId; - //vm.acceptedFileTypes = mediaHelper.formatFileTypes(Umbraco.Sys.ServerVariables.umbracoSettings.imageFileTypes); - //instead of passing in a whitelist, we pass in a blacklist by adding ! to the ext - vm.acceptedFileTypes = mediaHelper.formatFileTypes(Umbraco.Sys.ServerVariables.umbracoSettings.disallowedUploadFiles).replace(/./g, "!."); - vm.maxFileSize = Umbraco.Sys.ServerVariables.umbracoSettings.maxFileSize + "KB"; - vm.activeDrag = false; - vm.isRecycleBin = $scope.contentId === '-21' || $scope.contentId === '-20'; + vm.nodeId = $scope.contentId; + //we pass in a blacklist by adding ! to the file extensions, allowing everything EXCEPT for disallowedUploadFiles + vm.acceptedFileTypes = !mediaHelper.formatFileTypes(Umbraco.Sys.ServerVariables.umbracoSettings.disallowedUploadFiles); + vm.maxFileSize = Umbraco.Sys.ServerVariables.umbracoSettings.maxFileSize + "KB"; + vm.activeDrag = false; + vm.isRecycleBin = $scope.contentId === '-21' || $scope.contentId === '-20'; - vm.selectItem = selectItem; - vm.clickItem = clickItem; - vm.selectAll = selectAll; - vm.isSelectedAll = isSelectedAll; - vm.isSortDirection = isSortDirection; - vm.sort = sort; - vm.dragEnter = dragEnter; - vm.dragLeave = dragLeave; - vm.onFilesQueue = onFilesQueue; - vm.onUploadComplete = onUploadComplete; + vm.selectItem = selectItem; + vm.clickItem = clickItem; + vm.selectAll = selectAll; + vm.isSelectedAll = isSelectedAll; + vm.isSortDirection = isSortDirection; + vm.sort = sort; + vm.dragEnter = dragEnter; + vm.dragLeave = dragLeave; + vm.onFilesQueue = onFilesQueue; + vm.onUploadComplete = onUploadComplete; - function selectAll($event) { - listViewHelper.selectAllItems($scope.items, $scope.selection, $event); - } + function selectAll($event) { + listViewHelper.selectAllItems($scope.items, $scope.selection, $event); + } - function isSelectedAll() { - return listViewHelper.isSelectedAll($scope.items, $scope.selection); - } + function isSelectedAll() { + return listViewHelper.isSelectedAll($scope.items, $scope.selection); + } - function selectItem(selectedItem, $index, $event) { - listViewHelper.selectHandler(selectedItem, $index, $scope.items, $scope.selection, $event); - } + function selectItem(selectedItem, $index, $event) { + listViewHelper.selectHandler(selectedItem, $index, $scope.items, $scope.selection, $event); + } - function clickItem(item) { - $location.path($scope.entityType + '/' + $scope.entityType + '/edit/' + item.id); - } + function clickItem(item) { + $location.path($scope.entityType + '/' +$scope.entityType + '/edit/' +item.id); + } - function isSortDirection(col, direction) { - return listViewHelper.setSortingDirection(col, direction, $scope.options); - } + function isSortDirection(col, direction) { + return listViewHelper.setSortingDirection(col, direction, $scope.options); + } - function sort(field, allow) { - if (allow) { - listViewHelper.setSorting(field, allow, $scope.options); - $scope.getContent($scope.contentId); + function sort(field, allow, isSystem) { + if (allow) { + $scope.options.orderBySystemField = isSystem; + listViewHelper.setSorting(field, allow, $scope.options); + $scope.getContent($scope.contentId); + } } - } - // Dropzone upload functions - function dragEnter(el, event) { - vm.activeDrag = true; - } + // Dropzone upload functions + function dragEnter(el, event) { + vm.activeDrag = true; + } - function dragLeave(el, event) { - vm.activeDrag = false; - } + function dragLeave(el, event) { + vm.activeDrag = false; + } - function onFilesQueue() { - vm.activeDrag = false; - } + function onFilesQueue() { + vm.activeDrag = false; + } - function onUploadComplete() { - $scope.getContent($scope.contentId); - } + function onUploadComplete() { + $scope.getContent($scope.contentId); + } - } + } - angular.module("umbraco").controller("Umbraco.PropertyEditors.ListView.ListLayoutController", ListViewListLayoutController); +angular.module("umbraco").controller("Umbraco.PropertyEditors.ListView.ListLayoutController", ListViewListLayoutController); -})(); +}) (); diff --git a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/listview/listview.controller.js b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/listview/listview.controller.js index 59ea03aa91..518c27d110 100644 --- a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/listview/listview.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/listview/listview.controller.js @@ -1,382 +1,393 @@ function listViewController($rootScope, $scope, $routeParams, $injector, $cookieStore, notificationsService, iconHelper, dialogService, editorState, localizationService, $location, appState, $timeout, $q, mediaResource, listViewHelper, userService) { - //this is a quick check to see if we're in create mode, if so just exit - we cannot show children for content - // that isn't created yet, if we continue this will use the parent id in the route params which isn't what - // we want. NOTE: This is just a safety check since when we scaffold an empty model on the server we remove - // the list view tab entirely when it's new. - if ($routeParams.create) { - $scope.isNew = true; - return; - } + //this is a quick check to see if we're in create mode, if so just exit - we cannot show children for content + // that isn't created yet, if we continue this will use the parent id in the route params which isn't what + // we want. NOTE: This is just a safety check since when we scaffold an empty model on the server we remove + // the list view tab entirely when it's new. + if ($routeParams.create) { + $scope.isNew = true; + return; + } - //Now we need to check if this is for media, members or content because that will depend on the resources we use - var contentResource, getContentTypesCallback, getListResultsCallback, deleteItemCallback, getIdCallback, createEditUrlCallback; + //Now we need to check if this is for media, members or content because that will depend on the resources we use + var contentResource, getContentTypesCallback, getListResultsCallback, deleteItemCallback, getIdCallback, createEditUrlCallback; - //check the config for the entity type, or the current section name (since the config is only set in c#, not in pre-vals) - if (($scope.model.config.entityType && $scope.model.config.entityType === "member") || (appState.getSectionState("currentSection") === "member")) { - $scope.entityType = "member"; - contentResource = $injector.get('memberResource'); - getContentTypesCallback = $injector.get('memberTypeResource').getTypes; - getListResultsCallback = contentResource.getPagedResults; - deleteItemCallback = contentResource.deleteByKey; - getIdCallback = function(selected) { - var selectedKey = getItemKey(selected.id); - return selectedKey; - }; - createEditUrlCallback = function(item) { - return "/" + $scope.entityType + "/" + $scope.entityType + "/edit/" + item.key + "?page=" + $scope.options.pageNumber + "&listName=" + $scope.contentId; - }; - } - else { - //check the config for the entity type, or the current section name (since the config is only set in c#, not in pre-vals) - if (($scope.model.config.entityType && $scope.model.config.entityType === "media") || (appState.getSectionState("currentSection") === "media")) { - $scope.entityType = "media"; - contentResource = $injector.get('mediaResource'); - getContentTypesCallback = $injector.get('mediaTypeResource').getAllowedTypes; - } - else { - $scope.entityType = "content"; - contentResource = $injector.get('contentResource'); - getContentTypesCallback = $injector.get('contentTypeResource').getAllowedTypes; - } - getListResultsCallback = contentResource.getChildren; - deleteItemCallback = contentResource.deleteById; - getIdCallback = function(selected) { - return selected.id; - }; - createEditUrlCallback = function(item) { - return "/" + $scope.entityType + "/" + $scope.entityType + "/edit/" + item.id + "?page=" + $scope.options.pageNumber; - }; - } + //check the config for the entity type, or the current section name (since the config is only set in c#, not in pre-vals) + if (($scope.model.config.entityType && $scope.model.config.entityType === "member") || (appState.getSectionState("currentSection") === "member")) { + $scope.entityType = "member"; + contentResource = $injector.get('memberResource'); + getContentTypesCallback = $injector.get('memberTypeResource').getTypes; + getListResultsCallback = contentResource.getPagedResults; + deleteItemCallback = contentResource.deleteByKey; + getIdCallback = function (selected) { + var selectedKey = getItemKey(selected.id); + return selectedKey; + }; + createEditUrlCallback = function (item) { + return "/" + $scope.entityType + "/" + $scope.entityType + "/edit/" + item.key + "?page=" + $scope.options.pageNumber + "&listName=" + $scope.contentId; + }; + } + else { + //check the config for the entity type, or the current section name (since the config is only set in c#, not in pre-vals) + if (($scope.model.config.entityType && $scope.model.config.entityType === "media") || (appState.getSectionState("currentSection") === "media")) { + $scope.entityType = "media"; + contentResource = $injector.get('mediaResource'); + getContentTypesCallback = $injector.get('mediaTypeResource').getAllowedTypes; + } + else { + $scope.entityType = "content"; + contentResource = $injector.get('contentResource'); + getContentTypesCallback = $injector.get('contentTypeResource').getAllowedTypes; + } + getListResultsCallback = contentResource.getChildren; + deleteItemCallback = contentResource.deleteById; + getIdCallback = function (selected) { + return selected.id; + }; + createEditUrlCallback = function (item) { + return "/" + $scope.entityType + "/" + $scope.entityType + "/edit/" + item.id + "?page=" + $scope.options.pageNumber; + }; + } - $scope.pagination = []; - $scope.isNew = false; - $scope.actionInProgress = false; - $scope.selection = []; - $scope.folders = []; - $scope.listViewResultSet = { - totalPages: 0, - items: [] - }; - - $scope.currentNodePermissions = {} + $scope.pagination = []; + $scope.isNew = false; + $scope.actionInProgress = false; + $scope.selection = []; + $scope.folders = []; + $scope.listViewResultSet = { + totalPages: 0, + items: [] + }; - //Just ensure we do have an editorState - if (editorState.current) { - //Fetch current node allowed actions for the current user - //This is the current node & not each individual child node in the list - var currentUserPermissions = editorState.current.allowedActions; + $scope.currentNodePermissions = {} - //Create a nicer model rather than the funky & hard to remember permissions strings - $scope.currentNodePermissions = { - "canCopy": _.contains(currentUserPermissions, 'O'), //Magic Char = O - "canCreate": _.contains(currentUserPermissions, 'C'), //Magic Char = C - "canDelete": _.contains(currentUserPermissions, 'D'), //Magic Char = D - "canMove": _.contains(currentUserPermissions, 'M'), //Magic Char = M - "canPublish": _.contains(currentUserPermissions, 'U'), //Magic Char = U - "canUnpublish": _.contains(currentUserPermissions, 'U'), //Magic Char = Z (however UI says it can't be set, so if we can publish 'U' we can unpublish) - }; - } + //Just ensure we do have an editorState + if (editorState.current) { + //Fetch current node allowed actions for the current user + //This is the current node & not each individual child node in the list + var currentUserPermissions = editorState.current.allowedActions; - //when this is null, we don't check permissions - $scope.buttonPermissions = null; + //Create a nicer model rather than the funky & hard to remember permissions strings + $scope.currentNodePermissions = { + "canCopy": _.contains(currentUserPermissions, 'O'), //Magic Char = O + "canCreate": _.contains(currentUserPermissions, 'C'), //Magic Char = C + "canDelete": _.contains(currentUserPermissions, 'D'), //Magic Char = D + "canMove": _.contains(currentUserPermissions, 'M'), //Magic Char = M + "canPublish": _.contains(currentUserPermissions, 'U'), //Magic Char = U + "canUnpublish": _.contains(currentUserPermissions, 'U'), //Magic Char = Z (however UI says it can't be set, so if we can publish 'U' we can unpublish) + }; + } - //When we are dealing with 'content', we need to deal with permissions on child nodes. - // Currently there is no real good way to - if ($scope.entityType === "content") { + //when this is null, we don't check permissions + $scope.buttonPermissions = null; - var idsWithPermissions = null; + //When we are dealing with 'content', we need to deal with permissions on child nodes. + // Currently there is no real good way to + if ($scope.entityType === "content") { - $scope.buttonPermissions = { - canCopy: true, - canCreate: true, - canDelete: true, - canMove: true, - canPublish: true, - canUnpublish: true - }; + var idsWithPermissions = null; - $scope.$watch(function() { - return $scope.selection.length; - }, function(newVal, oldVal) { + $scope.buttonPermissions = { + canCopy: true, + canCreate: true, + canDelete: true, + canMove: true, + canPublish: true, + canUnpublish: true + }; - if ((idsWithPermissions == null && newVal > 0) || (idsWithPermissions != null)) { - - //get all of the selected ids - var ids = _.map($scope.selection, function(i) { - return i.id.toString(); - }); + $scope.$watch(function () { + return $scope.selection.length; + }, function (newVal, oldVal) { - //remove the dictionary items that don't have matching ids - var filtered = {}; - _.each(idsWithPermissions, function (value, key, list) { - if (_.contains(ids, key)) { - filtered[key] = value; - } - }); - idsWithPermissions = filtered; + if ((idsWithPermissions == null && newVal > 0) || (idsWithPermissions != null)) { - //find all ids that we haven't looked up permissions for - var existingIds = _.keys(idsWithPermissions); - var missingLookup = _.map(_.difference(ids, existingIds), function (i) { - return Number(i); - }); + //get all of the selected ids + var ids = _.map($scope.selection, function (i) { + return i.id.toString(); + }); - if (missingLookup.length > 0) { - contentResource.getPermissions(missingLookup).then(function(p) { - $scope.buttonPermissions = listViewHelper.getButtonPermissions(p, idsWithPermissions); - }); - } - else { - $scope.buttonPermissions = listViewHelper.getButtonPermissions({}, idsWithPermissions); - } + //remove the dictionary items that don't have matching ids + var filtered = {}; + _.each(idsWithPermissions, function (value, key, list) { + if (_.contains(ids, key)) { + filtered[key] = value; + } + }); + idsWithPermissions = filtered; + + //find all ids that we haven't looked up permissions for + var existingIds = _.keys(idsWithPermissions); + var missingLookup = _.map(_.difference(ids, existingIds), function (i) { + return Number(i); + }); + + if (missingLookup.length > 0) { + contentResource.getPermissions(missingLookup).then(function (p) { + $scope.buttonPermissions = listViewHelper.getButtonPermissions(p, idsWithPermissions); + }); } - }); + else { + $scope.buttonPermissions = listViewHelper.getButtonPermissions({}, idsWithPermissions); + } + } + }); - } + } - $scope.options = { - displayAtTabNumber: $scope.model.config.displayAtTabNumber ? $scope.model.config.displayAtTabNumber : 1, - pageSize: $scope.model.config.pageSize ? $scope.model.config.pageSize : 10, - pageNumber: ($routeParams.page && Number($routeParams.page) != NaN && Number($routeParams.page) > 0) ? $routeParams.page : 1, - filter: '', - orderBy: ($scope.model.config.orderBy ? $scope.model.config.orderBy : 'VersionDate').trim(), - orderDirection: $scope.model.config.orderDirection ? $scope.model.config.orderDirection.trim() : "desc", - includeProperties: $scope.model.config.includeProperties ? $scope.model.config.includeProperties : [ - { alias: 'updateDate', header: 'Last edited', isSystem: 1 }, - { alias: 'updater', header: 'Last edited by', isSystem: 1 } - ], - layout: { - layouts: $scope.model.config.layouts, - activeLayout: listViewHelper.getLayout($routeParams.id, $scope.model.config.layouts) - }, - allowBulkPublish: $scope.entityType === 'content' && $scope.model.config.bulkActionPermissions.allowBulkPublish, - allowBulkUnpublish: $scope.entityType === 'content' && $scope.model.config.bulkActionPermissions.allowBulkUnpublish, - allowBulkCopy: $scope.entityType === 'content' && $scope.model.config.bulkActionPermissions.allowBulkCopy, - allowBulkMove: $scope.model.config.bulkActionPermissions.allowBulkMove, - allowBulkDelete: $scope.model.config.bulkActionPermissions.allowBulkDelete - }; + $scope.options = { + displayAtTabNumber: $scope.model.config.displayAtTabNumber ? $scope.model.config.displayAtTabNumber : 1, + pageSize: $scope.model.config.pageSize ? $scope.model.config.pageSize : 10, + pageNumber: ($routeParams.page && Number($routeParams.page) != NaN && Number($routeParams.page) > 0) ? $routeParams.page : 1, + filter: '', + orderBy: ($scope.model.config.orderBy ? $scope.model.config.orderBy : 'VersionDate').trim(), + orderDirection: $scope.model.config.orderDirection ? $scope.model.config.orderDirection.trim() : "desc", + orderBySystemField: true, + includeProperties: $scope.model.config.includeProperties ? $scope.model.config.includeProperties : [ + { alias: 'updateDate', header: 'Last edited', isSystem: 1 }, + { alias: 'updater', header: 'Last edited by', isSystem: 1 } + ], + layout: { + layouts: $scope.model.config.layouts, + activeLayout: listViewHelper.getLayout($routeParams.id, $scope.model.config.layouts) + }, + orderBySystemField: true, + allowBulkPublish: $scope.entityType === 'content' && $scope.model.config.bulkActionPermissions.allowBulkPublish, + allowBulkUnpublish: $scope.entityType === 'content' && $scope.model.config.bulkActionPermissions.allowBulkUnpublish, + allowBulkCopy: $scope.entityType === 'content' && $scope.model.config.bulkActionPermissions.allowBulkCopy, + allowBulkMove: $scope.model.config.bulkActionPermissions.allowBulkMove, + allowBulkDelete: $scope.model.config.bulkActionPermissions.allowBulkDelete + }; - //update all of the system includeProperties to enable sorting - _.each($scope.options.includeProperties, function(e, i) { + //update all of the system includeProperties to enable sorting + _.each($scope.options.includeProperties, function (e, i) { + + //NOTE: special case for contentTypeAlias, it's a system property that cannot be sorted + // to do that, we'd need to update the base query for content to include the content type alias column + // which requires another join and would be slower. BUT We are doing this for members so not sure it makes a diff? + if (e.alias != "contentTypeAlias") { + e.allowSorting = true; + } + + // Another special case for lasted edited data/update date for media, again this field isn't available on the base table so we can't sort by it + if (e.isSystem && $scope.entityType == "media") { + e.allowSorting = e.alias != 'updateDate'; + } + + // Another special case for members, only fields on the base table (cmsMember) can be used for sorting + if (e.isSystem && $scope.entityType == "member") { + e.allowSorting = e.alias == 'username' || e.alias == 'email'; + } if (e.isSystem) { + //localize the header + var key = getLocalizedKey(e.alias); + localizationService.localize(key).then(function (v) { + e.header = v; + }); + } + }); - //NOTE: special case for contentTypeAlias, it's a system property that cannot be sorted - // to do that, we'd need to update the base query for content to include the content type alias column - // which requires another join and would be slower. BUT We are doing this for members so not sure it makes a diff? - if (e.alias != "contentTypeAlias") { - e.allowSorting = true; - } + $scope.selectLayout = function (selectedLayout) { + $scope.options.layout.activeLayout = listViewHelper.setLayout($routeParams.id, selectedLayout, $scope.model.config.layouts); + }; - //localize the header - var key = getLocalizedKey(e.alias); - localizationService.localize(key).then(function (v) { - e.header = v; + function showNotificationsAndReset(err, reload, successMsg) { + + //check if response is ysod + if (err.status && err.status >= 500) { + + // Open ysod overlay + $scope.ysodOverlay = { + view: "ysod", + error: err, + show: true + }; + } + + $timeout(function () { + $scope.bulkStatus = ""; + $scope.actionInProgress = false; + }, 500); + + if (reload === true) { + $scope.reloadView($scope.contentId); + } + + if (err.data && angular.isArray(err.data.notifications)) { + for (var i = 0; i < err.data.notifications.length; i++) { + notificationsService.showNotification(err.data.notifications[i]); + } + } + else if (successMsg) { + notificationsService.success("Done", successMsg); + } + } + + $scope.next = function (pageNumber) { + $scope.options.pageNumber = pageNumber; + $scope.reloadView($scope.contentId); + }; + + $scope.goToPage = function (pageNumber) { + $scope.options.pageNumber = pageNumber; + $scope.reloadView($scope.contentId); + }; + + $scope.prev = function (pageNumber) { + $scope.options.pageNumber = pageNumber; + $scope.reloadView($scope.contentId); + }; + + + /*Loads the search results, based on parameters set in prev,next,sort and so on*/ + /*Pagination is done by an array of objects, due angularJS's funky way of monitoring state + with simple values */ + + $scope.reloadView = function (id) { + + $scope.viewLoaded = false; + + listViewHelper.clearSelection($scope.listViewResultSet.items, $scope.folders, $scope.selection); + + getListResultsCallback(id, $scope.options).then(function (data) { + + $scope.actionInProgress = false; + $scope.listViewResultSet = data; + + //update all values for display + if ($scope.listViewResultSet.items) { + _.each($scope.listViewResultSet.items, function (e, index) { + setPropertyValues(e); }); - } - }); + } - $scope.selectLayout = function(selectedLayout) { - $scope.options.layout.activeLayout = listViewHelper.setLayout($routeParams.id, selectedLayout, $scope.model.config.layouts); - }; + if ($scope.entityType === 'media') { - function showNotificationsAndReset(err, reload, successMsg) { - - //check if response is ysod - if(err.status && err.status >= 500) { - - // Open ysod overlay - $scope.ysodOverlay = { - view : "ysod", - error : err, - show : true - }; - } - - $timeout(function() { - $scope.bulkStatus = ""; - $scope.actionInProgress = false; - }, 500); - - if (reload === true) { - $scope.reloadView($scope.contentId); - } - - if (err.data && angular.isArray(err.data.notifications)) { - for (var i = 0; i < err.data.notifications.length; i++) { - notificationsService.showNotification(err.data.notifications[i]); - } - } - else if (successMsg) { - notificationsService.success("Done", successMsg); - } - } - - $scope.next = function(pageNumber) { - $scope.options.pageNumber = pageNumber; - $scope.reloadView($scope.contentId); - }; - - $scope.goToPage = function(pageNumber) { - $scope.options.pageNumber = pageNumber; - $scope.reloadView($scope.contentId); - }; - - $scope.prev = function(pageNumber) { - $scope.options.pageNumber = pageNumber; - $scope.reloadView($scope.contentId); - }; - - - /*Loads the search results, based on parameters set in prev,next,sort and so on*/ - /*Pagination is done by an array of objects, due angularJS's funky way of monitoring state - with simple values */ - - $scope.reloadView = function(id) { - - $scope.viewLoaded = false; - - listViewHelper.clearSelection($scope.listViewResultSet.items, $scope.folders, $scope.selection); - - getListResultsCallback(id, $scope.options).then(function(data) { - - $scope.actionInProgress = false; - $scope.listViewResultSet = data; - - //update all values for display - if ($scope.listViewResultSet.items) { - _.each($scope.listViewResultSet.items, function(e, index) { - setPropertyValues(e); - }); - } - - if ($scope.entityType === 'media') { - - mediaResource.getChildFolders($scope.contentId) - .then(function(folders) { - $scope.folders = folders; - $scope.viewLoaded = true; + mediaResource.getChildFolders($scope.contentId) + .then(function (folders) { + $scope.folders = folders; + $scope.viewLoaded = true; }); - } else { - $scope.viewLoaded = true; - } + } else { + $scope.viewLoaded = true; + } - //NOTE: This might occur if we are requesting a higher page number than what is actually available, for example - // if you have more than one page and you delete all items on the last page. In this case, we need to reset to the last - // available page and then re-load again - if ($scope.options.pageNumber > $scope.listViewResultSet.totalPages) { - $scope.options.pageNumber = $scope.listViewResultSet.totalPages; + //NOTE: This might occur if we are requesting a higher page number than what is actually available, for example + // if you have more than one page and you delete all items on the last page. In this case, we need to reset to the last + // available page and then re-load again + if ($scope.options.pageNumber > $scope.listViewResultSet.totalPages) { + $scope.options.pageNumber = $scope.listViewResultSet.totalPages; - //reload! - $scope.reloadView(id); - } + //reload! + $scope.reloadView(id); + } - }); - }; + }); + }; - var searchListView = _.debounce(function(){ - $scope.$apply(function() { + var searchListView = _.debounce(function () { + $scope.$apply(function () { + makeSearch(); + }); + }, 500); + + $scope.forceSearch = function (ev) { + //13: enter + switch (ev.keyCode) { + case 13: makeSearch(); - }); - }, 500); + break; + } + }; - $scope.forceSearch = function (ev) { - //13: enter - switch (ev.keyCode) { - case 13: - makeSearch(); - break; - } - }; + $scope.enterSearch = function () { + $scope.viewLoaded = false; + searchListView(); + }; - $scope.enterSearch = function() { - $scope.viewLoaded = false; - searchListView(); - }; + function makeSearch() { + if ($scope.options.filter !== null && $scope.options.filter !== undefined) { + $scope.options.pageNumber = 1; + //$scope.actionInProgress = true; + $scope.reloadView($scope.contentId); + } + } - function makeSearch() { - if ($scope.options.filter !== null && $scope.options.filter !== undefined) { - $scope.options.pageNumber = 1; - //$scope.actionInProgress = true; - $scope.reloadView($scope.contentId); - } - } + $scope.isAnythingSelected = function () { + if ($scope.selection.length === 0) { + return false; + } else { + return true; + } + }; - $scope.isAnythingSelected = function() { - if ($scope.selection.length === 0) { - return false; - } else { - return true; - } - }; - - $scope.selectedItemsCount = function() { + $scope.selectedItemsCount = function () { return $scope.selection.length; - }; + }; - $scope.clearSelection = function() { + $scope.clearSelection = function () { listViewHelper.clearSelection($scope.listViewResultSet.items, $scope.folders, $scope.selection); - }; + }; - $scope.getIcon = function(entry) { - return iconHelper.convertFromLegacyIcon(entry.icon); - }; + $scope.getIcon = function (entry) { + return iconHelper.convertFromLegacyIcon(entry.icon); + }; - function serial(selected, fn, getStatusMsg, index) { - return fn(selected, index).then(function (content) { - index++; - $scope.bulkStatus = getStatusMsg(index, selected.length); - return index < selected.length ? serial(selected, fn, getStatusMsg, index) : content; - }, function (err) { - var reload = index > 0; - showNotificationsAndReset(err, reload); - return err; - }); - } + function serial(selected, fn, getStatusMsg, index) { + return fn(selected, index).then(function (content) { + index++; + $scope.bulkStatus = getStatusMsg(index, selected.length); + return index < selected.length ? serial(selected, fn, getStatusMsg, index) : content; + }, function (err) { + var reload = index > 0; + showNotificationsAndReset(err, reload); + return err; + }); + } - function applySelected(fn, getStatusMsg, getSuccessMsg, confirmMsg) { - var selected = $scope.selection; - if (selected.length === 0) - return; - if (confirmMsg && !confirm(confirmMsg)) - return; + function applySelected(fn, getStatusMsg, getSuccessMsg, confirmMsg) { + var selected = $scope.selection; + if (selected.length === 0) + return; + if (confirmMsg && !confirm(confirmMsg)) + return; - $scope.actionInProgress = true; - $scope.bulkStatus = getStatusMsg(0, selected.length); + $scope.actionInProgress = true; + $scope.bulkStatus = getStatusMsg(0, selected.length); - serial(selected, fn, getStatusMsg, 0).then(function (result) { - // executes once the whole selection has been processed - // in case of an error (caught by serial), result will be the error - if (!(result.data && angular.isArray(result.data.notifications))) - showNotificationsAndReset(result, true, getSuccessMsg(selected.length)); - }); - } + serial(selected, fn, getStatusMsg, 0).then(function (result) { + // executes once the whole selection has been processed + // in case of an error (caught by serial), result will be the error + if (!(result.data && angular.isArray(result.data.notifications))) + showNotificationsAndReset(result, true, getSuccessMsg(selected.length)); + }); + } - $scope.delete = function () { - applySelected( - function (selected, index) { return deleteItemCallback(getIdCallback(selected[index])); }, - function (count, total) { return "Deleted " + count + " out of " + total + " item" + (total > 1 ? "s" : ""); }, - function (total) { return "Deleted " + total + " item" + (total > 1 ? "s" : ""); }, - "Sure you want to delete?"); - }; + $scope.delete = function () { + applySelected( + function (selected, index) { return deleteItemCallback(getIdCallback(selected[index])); }, + function (count, total) { return "Deleted " + count + " out of " + total + " item" + (total > 1 ? "s" : ""); }, + function (total) { return "Deleted " + total + " item" + (total > 1 ? "s" : ""); }, + "Sure you want to delete?"); + }; - $scope.publish = function () { - applySelected( - function (selected, index) { return contentResource.publishById(getIdCallback(selected[index])); }, - function (count, total) { return "Published " + count + " out of " + total + " item" + (total > 1 ? "s" : ""); }, - function (total) { return "Published " + total + " item" + (total > 1 ? "s" : ""); }); - }; + $scope.publish = function () { + applySelected( + function (selected, index) { return contentResource.publishById(getIdCallback(selected[index])); }, + function (count, total) { return "Published " + count + " out of " + total + " item" + (total > 1 ? "s" : ""); }, + function (total) { return "Published " + total + " item" + (total > 1 ? "s" : ""); }); + }; - $scope.unpublish = function() { - applySelected( - function (selected, index) { return contentResource.unPublish(getIdCallback(selected[index])); }, - function (count, total) { return "Unpublished " + count + " out of " + total + " item" + (total > 1 ? "s" : ""); }, - function (total) { return "Unpublished " + total + " item" + (total > 1 ? "s" : ""); }); - }; + $scope.unpublish = function () { + applySelected( + function (selected, index) { return contentResource.unPublish(getIdCallback(selected[index])); }, + function (count, total) { return "Unpublished " + count + " out of " + total + " item" + (total > 1 ? "s" : ""); }, + function (total) { return "Unpublished " + total + " item" + (total > 1 ? "s" : ""); }); + }; - $scope.move = function() { + $scope.move = function () { $scope.moveDialog = {}; $scope.moveDialog.title = "Move"; $scope.moveDialog.section = $scope.entityType; @@ -384,9 +395,9 @@ function listViewController($rootScope, $scope, $routeParams, $injector, $cookie $scope.moveDialog.view = "move"; $scope.moveDialog.show = true; - $scope.moveDialog.submit = function(model) { + $scope.moveDialog.submit = function (model) { - if(model.target) { + if (model.target) { performMove(model.target); } @@ -394,22 +405,22 @@ function listViewController($rootScope, $scope, $routeParams, $injector, $cookie $scope.moveDialog = null; }; - $scope.moveDialog.close = function(oldModel) { + $scope.moveDialog.close = function (oldModel) { $scope.moveDialog.show = false; $scope.moveDialog = null; }; - }; + }; - function performMove(target) { + function performMove(target) { applySelected( - function(selected, index) {return contentResource.move({parentId: target.id, id: getIdCallback(selected[index])}); }, - function(count, total) {return "Moved " + count + " out of " + total + " item" + (total > 1 ? "s" : ""); }, - function(total) {return "Moved " + total + " item" + (total > 1 ? "s" : ""); }); - } + function (selected, index) { return contentResource.move({ parentId: target.id, id: getIdCallback(selected[index]) }); }, + function (count, total) { return "Moved " + count + " out of " + total + " item" + (total > 1 ? "s" : ""); }, + function (total) { return "Moved " + total + " item" + (total > 1 ? "s" : ""); }); + } - $scope.copy = function() { + $scope.copy = function () { $scope.copyDialog = {}; $scope.copyDialog.title = "Copy"; $scope.copyDialog.section = $scope.entityType; @@ -417,8 +428,8 @@ function listViewController($rootScope, $scope, $routeParams, $injector, $cookie $scope.copyDialog.view = "copy"; $scope.copyDialog.show = true; - $scope.copyDialog.submit = function(model) { - if(model.target) { + $scope.copyDialog.submit = function (model) { + if (model.target) { performCopy(model.target, model.relateToOriginal); } @@ -426,142 +437,142 @@ function listViewController($rootScope, $scope, $routeParams, $injector, $cookie $scope.copyDialog = null; }; - $scope.copyDialog.close = function(oldModel) { + $scope.copyDialog.close = function (oldModel) { $scope.copyDialog.show = false; $scope.copyDialog = null; }; - }; + }; - function performCopy(target, relateToOriginal) { + function performCopy(target, relateToOriginal) { applySelected( - function(selected, index) {return contentResource.copy({parentId: target.id, id: getIdCallback(selected[index]), relateToOriginal: relateToOriginal}); }, - function(count, total) {return "Copied " + count + " out of " + total + " item" + (total > 1 ? "s" : ""); }, - function(total) {return "Copied " + total + " item" + (total > 1 ? "s" : ""); }); - } + function (selected, index) { return contentResource.copy({ parentId: target.id, id: getIdCallback(selected[index]), relateToOriginal: relateToOriginal }); }, + function (count, total) { return "Copied " + count + " out of " + total + " item" + (total > 1 ? "s" : ""); }, + function (total) { return "Copied " + total + " item" + (total > 1 ? "s" : ""); }); + } - function getCustomPropertyValue(alias, properties) { - var value = ''; - var index = 0; - var foundAlias = false; - for (var i = 0; i < properties.length; i++) { - if (properties[i].alias == alias) { - foundAlias = true; - break; - } - index++; - } + function getCustomPropertyValue(alias, properties) { + var value = ''; + var index = 0; + var foundAlias = false; + for (var i = 0; i < properties.length; i++) { + if (properties[i].alias == alias) { + foundAlias = true; + break; + } + index++; + } - if (foundAlias) { - value = properties[index].value; - } + if (foundAlias) { + value = properties[index].value; + } - return value; - } + return value; + } - /** This ensures that the correct value is set for each item in a row, we don't want to call a function during interpolation or ng-bind as performance is really bad that way */ - function setPropertyValues(result) { + /** This ensures that the correct value is set for each item in a row, we don't want to call a function during interpolation or ng-bind as performance is really bad that way */ + function setPropertyValues(result) { - //set the edit url - result.editPath = createEditUrlCallback(result); + //set the edit url + result.editPath = createEditUrlCallback(result); - _.each($scope.options.includeProperties, function (e, i) { + _.each($scope.options.includeProperties, function (e, i) { - var alias = e.alias; + var alias = e.alias; - // First try to pull the value directly from the alias (e.g. updatedBy) - var value = result[alias]; + // First try to pull the value directly from the alias (e.g. updatedBy) + var value = result[alias]; - // If this returns an object, look for the name property of that (e.g. owner.name) - if (value === Object(value)) { - value = value['name']; - } + // If this returns an object, look for the name property of that (e.g. owner.name) + if (value === Object(value)) { + value = value['name']; + } - // If we've got nothing yet, look at a user defined property - if (typeof value === 'undefined') { - value = getCustomPropertyValue(alias, result.properties); - } + // If we've got nothing yet, look at a user defined property + if (typeof value === 'undefined') { + value = getCustomPropertyValue(alias, result.properties); + } - // If we have a date, format it - if (isDate(value)) { - value = value.substring(0, value.length - 3); - } + // If we have a date, format it + if (isDate(value)) { + value = value.substring(0, value.length - 3); + } - // set what we've got on the result - result[alias] = value; - }); + // set what we've got on the result + result[alias] = value; + }); - } + } - function isDate(val) { - if (angular.isString(val)) { - return val.match(/^(\d{4})\-(\d{2})\-(\d{2})\ (\d{2})\:(\d{2})\:(\d{2})$/); - } - return false; - } + function isDate(val) { + if (angular.isString(val)) { + return val.match(/^(\d{4})\-(\d{2})\-(\d{2})\ (\d{2})\:(\d{2})\:(\d{2})$/); + } + return false; + } - function initView() { - //default to root id if the id is undefined - var id = $routeParams.id; - if(id === undefined){ - id = -1; - } + function initView() { + //default to root id if the id is undefined + var id = $routeParams.id; + if (id === undefined) { + id = -1; + } - $scope.listViewAllowedTypes = getContentTypesCallback(id); + $scope.listViewAllowedTypes = getContentTypesCallback(id); - $scope.contentId = id; - $scope.isTrashed = id === "-20" || id === "-21"; + $scope.contentId = id; + $scope.isTrashed = id === "-20" || id === "-21"; - $scope.options.allowBulkPublish = $scope.options.allowBulkPublish && !$scope.isTrashed; - $scope.options.allowBulkUnpublish = $scope.options.allowBulkUnpublish && !$scope.isTrashed; + $scope.options.allowBulkPublish = $scope.options.allowBulkPublish && !$scope.isTrashed; + $scope.options.allowBulkUnpublish = $scope.options.allowBulkUnpublish && !$scope.isTrashed; - $scope.options.bulkActionsAllowed = $scope.options.allowBulkPublish || - $scope.options.allowBulkUnpublish || - $scope.options.allowBulkCopy || - $scope.options.allowBulkMove || - $scope.options.allowBulkDelete; + $scope.options.bulkActionsAllowed = $scope.options.allowBulkPublish || + $scope.options.allowBulkUnpublish || + $scope.options.allowBulkCopy || + $scope.options.allowBulkMove || + $scope.options.allowBulkDelete; - $scope.reloadView($scope.contentId); - } + $scope.reloadView($scope.contentId); + } - function getLocalizedKey(alias) { + function getLocalizedKey(alias) { - switch (alias) { - case "sortOrder": - return "general_sort"; - case "updateDate": - return "content_updateDate"; - case "updater": - return "content_updatedBy"; - case "createDate": - return "content_createDate"; - case "owner": - return "content_createBy"; - case "published": - return "content_isPublished"; - case "contentTypeAlias": - //TODO: Check for members - return $scope.entityType === "content" ? "content_documentType" : "content_mediatype"; - case "email": - return "general_email"; - case "username": - return "general_username"; - } - return alias; - } + switch (alias) { + case "sortOrder": + return "general_sort"; + case "updateDate": + return "content_updateDate"; + case "updater": + return "content_updatedBy"; + case "createDate": + return "content_createDate"; + case "owner": + return "content_createBy"; + case "published": + return "content_isPublished"; + case "contentTypeAlias": + //TODO: Check for members + return $scope.entityType === "content" ? "content_documentType" : "content_mediatype"; + case "email": + return "general_email"; + case "username": + return "general_username"; + } + return alias; + } - function getItemKey(itemId) { - for (var i = 0; i < $scope.listViewResultSet.items.length; i++) { - var item = $scope.listViewResultSet.items[i]; - if (item.id === itemId) { - return item.key; - } - } - } + function getItemKey(itemId) { + for (var i = 0; i < $scope.listViewResultSet.items.length; i++) { + var item = $scope.listViewResultSet.items[i]; + if (item.id === itemId) { + return item.key; + } + } + } - //GO! - initView(); + //GO! + initView(); } diff --git a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/mediapicker/mediapicker.controller.js b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/mediapicker/mediapicker.controller.js index bf82efae24..9969af937d 100644 --- a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/mediapicker/mediapicker.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/mediapicker/mediapicker.controller.js @@ -12,10 +12,10 @@ angular.module('umbraco').controller("Umbraco.PropertyEditors.MediaPickerControl $scope.model.config.startNodeId = userData.startMediaId; }); } - + function setupViewModel() { $scope.images = []; - $scope.ids = []; + $scope.ids = []; if ($scope.model.value) { var ids = $scope.model.value.split(','); @@ -30,16 +30,16 @@ angular.module('umbraco').controller("Umbraco.PropertyEditors.MediaPickerControl entityResource.getByIds(ids, "Media").then(function (medias) { _.each(medias, function (media, i) { - + //only show non-trashed items if (media.parentId >= -1) { - if (!media.thumbnail) { + if (!media.thumbnail) { media.thumbnail = mediaHelper.resolveFileFromEntity(media, true); } $scope.images.push(media); - $scope.ids.push(media.id); + $scope.ids.push(media.id); } }); @@ -67,6 +67,7 @@ angular.module('umbraco').controller("Umbraco.PropertyEditors.MediaPickerControl title: "Select media", startNodeId: $scope.model.config.startNodeId, multiPicker: multiPicker, + onlyImages: onlyImages, show: true, submit: function(model) { @@ -93,8 +94,8 @@ angular.module('umbraco').controller("Umbraco.PropertyEditors.MediaPickerControl $scope.sortableOptions = { update: function(e, ui) { var r = []; - //TODO: Instead of doing this with a half second delay would be better to use a watch like we do in the - // content picker. THen we don't have to worry about setting ids, render models, models, we just set one and let the + //TODO: Instead of doing this with a half second delay would be better to use a watch like we do in the + // content picker. THen we don't have to worry about setting ids, render models, models, we just set one and let the // watch do all the rest. $timeout(function(){ angular.forEach($scope.images, function(value, key){ diff --git a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/relatedlinks/relatedlinks.controller.js b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/relatedlinks/relatedlinks.controller.js index e10bce28b2..cb6c8e595a 100644 --- a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/relatedlinks/relatedlinks.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/relatedlinks/relatedlinks.controller.js @@ -1,16 +1,19 @@ angular.module("umbraco") .controller("Umbraco.PropertyEditors.RelatedLinksController", - function ($rootScope, $scope, dialogService) { + function ($rootScope, $scope, dialogService, iconHelper) { if (!$scope.model.value) { $scope.model.value = []; } + + $scope.model.config.max = isNumeric($scope.model.config.max) && $scope.model.config.max !== 0 ? $scope.model.config.max : Number.MAX_VALUE; $scope.newCaption = ''; $scope.newLink = 'http://'; $scope.newNewWindow = false; $scope.newInternal = null; $scope.newInternalName = ''; + $scope.newInternalIcon = null; $scope.addExternal = true; $scope.currentEditLink = null; $scope.hasError = false; @@ -72,7 +75,6 @@ } $scope.model.value[idx].edit = true; }; - $scope.saveEdit = function (idx) { $scope.model.value[idx].title = $scope.model.value[idx].caption; @@ -107,6 +109,7 @@ this.edit = false; this.isInternal = true; this.internalName = $scope.newInternalName; + this.internalIcon = $scope.newInternalIcon; this.type = "internal"; this.title = $scope.newCaption; }; @@ -117,7 +120,7 @@ $scope.newNewWindow = false; $scope.newInternal = null; $scope.newInternalName = ''; - + $scope.newInternalIcon = null; } $event.preventDefault(); }; @@ -141,23 +144,73 @@ $scope.model.value[index + direction] = temp; }; + //helper for determining if a user can add items + $scope.canAdd = function () { + return $scope.model.config.max <= 0 || $scope.model.config.max > countVisible(); + } + + //helper that returns if an item can be sorted + $scope.canSort = function () { + return countVisible() > 1; + } + $scope.sortableOptions = { - containment: 'parent', + axis: 'y', + handle: '.handle', cursor: 'move', + cancel: '.no-drag', + containment: 'parent', + placeholder: 'sortable-placeholder', + forcePlaceholderSize: true, helper: function (e, ui) { - // When sorting , the cells collapse. This helper fixes that: http://www.foliotek.com/devblog/make-table-rows-sortable-using-jquery-ui-sortable/ + // When sorting table rows, the cells collapse. This helper fixes that: http://www.foliotek.com/devblog/make-table-rows-sortable-using-jquery-ui-sortable/ ui.children().each(function () { $(this).width($(this).width()); }); return ui; }, - items: '> tr', + items: '> tr:not(.unsortable)', tolerance: 'pointer', update: function (e, ui) { - + // Get the new and old index for the moved element (using the URL as the identifier) + var newIndex = ui.item.index(); + var movedLinkUrl = ui.item.attr('data-link'); + var originalIndex = getElementIndexByUrl(movedLinkUrl); + + // Move the element in the model + var movedElement = $scope.model.value[originalIndex]; + $scope.model.value.splice(originalIndex, 1); + $scope.model.value.splice(newIndex, 0, movedElement); + }, + start: function (e, ui) { + //ui.placeholder.html(""); + + // Build a placeholder cell that spans all the cells in the row: http://stackoverflow.com/questions/25845310/jquery-ui-sortable-and-table-cell-size + var cellCount = 0; + $('td, th', ui.helper).each(function () { + // For each td or th try and get it's colspan attribute, and add that or 1 to the total + var colspan = 1; + var colspanAttr = $(this).attr('colspan'); + if (colspanAttr > 1) { + colspan = colspanAttr; + } + cellCount += colspan; + }); + + // Add the placeholder UI - note that this is the item's content, so td rather than tr - and set height of tr + ui.placeholder.html('').height(ui.item.height()); } }; + //helper to count what is visible + function countVisible() { + return $scope.model.value.length; + } + + function isNumeric(n) { + return !isNaN(parseFloat(n)) && isFinite(n); + } + function getElementIndexByUrl(url) { for (var i = 0; i < $scope.model.value.length; i++) { if ($scope.model.value[i].link == url) { @@ -172,10 +225,12 @@ if ($scope.currentEditLink != null) { $scope.currentEditLink.internal = data.id; $scope.currentEditLink.internalName = data.name; + $scope.currentEditLink.internalIcon = iconHelper.convertFromLegacyIcon(data.icon); $scope.currentEditLink.link = data.id; } else { $scope.newInternal = data.id; $scope.newInternalName = data.name; + $scope.newInternalIcon = iconHelper.convertFromLegacyIcon(data.icon); } } }); diff --git a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/relatedlinks/relatedlinks.html b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/relatedlinks/relatedlinks.html index 8b3381bf75..c6e02976f5 100644 --- a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/relatedlinks/relatedlinks.html +++ b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/relatedlinks/relatedlinks.html @@ -11,68 +11,79 @@ - - - + + + {{link.caption}} - +
    + +
    - +
- + {{link.newWindow}} - - +
-
+
- - + - - - -
+ + +
+ +
+ + + - - - - -
- -
- + + + + +
+ +
+ @@ -84,4 +95,4 @@ position="right"> -
+
\ No newline at end of file diff --git a/src/Umbraco.Web.UI/Umbraco.Web.UI.csproj b/src/Umbraco.Web.UI/Umbraco.Web.UI.csproj index 409cc514cc..824214e0e6 100644 --- a/src/Umbraco.Web.UI/Umbraco.Web.UI.csproj +++ b/src/Umbraco.Web.UI/Umbraco.Web.UI.csproj @@ -434,13 +434,6 @@ User.ascx - - ExamineManagement.ascx - ASPXCodeBehind - - - ExamineManagement.ascx - UserControlProxy.aspx ASPXCodeBehind @@ -591,14 +584,6 @@ - - - - - - - - @@ -676,7 +661,6 @@ - @@ -689,21 +673,6 @@ ASPXCodeBehind - - - - - - - - - - - - - - - @@ -731,8 +700,6 @@ - - @@ -741,15 +708,6 @@ - - - - - - - - - @@ -773,12 +731,7 @@ - - - - - @@ -795,7 +748,6 @@ - @@ -808,53 +760,15 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -877,67 +791,11 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Designer - - - - - - Designer @@ -1015,10 +873,6 @@ - - - - @@ -1034,7 +888,6 @@ - @@ -1042,207 +895,15 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Form + + Form + diff --git a/src/Umbraco.Web.UI/umbraco/images/editor/dictionaryItem.gif b/src/Umbraco.Web.UI/Umbraco/Images/editor/dictionaryItem.gif similarity index 100% rename from src/Umbraco.Web.UI/umbraco/images/editor/dictionaryItem.gif rename to src/Umbraco.Web.UI/Umbraco/Images/editor/dictionaryItem.gif diff --git a/src/Umbraco.Web.UI/umbraco/images/editor/help.png b/src/Umbraco.Web.UI/Umbraco/Images/editor/help.png similarity index 100% rename from src/Umbraco.Web.UI/umbraco/images/editor/help.png rename to src/Umbraco.Web.UI/Umbraco/Images/editor/help.png diff --git a/src/Umbraco.Web.UI/umbraco/images/editor/insChildTemplateNew.gif b/src/Umbraco.Web.UI/Umbraco/Images/editor/insChildTemplateNew.gif similarity index 100% rename from src/Umbraco.Web.UI/umbraco/images/editor/insChildTemplateNew.gif rename to src/Umbraco.Web.UI/Umbraco/Images/editor/insChildTemplateNew.gif diff --git a/src/Umbraco.Web.UI/umbraco/images/editor/insField.gif b/src/Umbraco.Web.UI/Umbraco/Images/editor/insField.gif similarity index 100% rename from src/Umbraco.Web.UI/umbraco/images/editor/insField.gif rename to src/Umbraco.Web.UI/Umbraco/Images/editor/insField.gif diff --git a/src/Umbraco.Web.UI/umbraco/images/editor/insFieldByLevel.gif b/src/Umbraco.Web.UI/Umbraco/Images/editor/insFieldByLevel.gif similarity index 100% rename from src/Umbraco.Web.UI/umbraco/images/editor/insFieldByLevel.gif rename to src/Umbraco.Web.UI/Umbraco/Images/editor/insFieldByLevel.gif diff --git a/src/Umbraco.Web.UI/umbraco/images/editor/insFieldByTree.gif b/src/Umbraco.Web.UI/Umbraco/Images/editor/insFieldByTree.gif similarity index 100% rename from src/Umbraco.Web.UI/umbraco/images/editor/insFieldByTree.gif rename to src/Umbraco.Web.UI/Umbraco/Images/editor/insFieldByTree.gif diff --git a/src/Umbraco.Web.UI/umbraco/images/editor/insMacro.gif b/src/Umbraco.Web.UI/Umbraco/Images/editor/insMacro.gif similarity index 100% rename from src/Umbraco.Web.UI/umbraco/images/editor/insMacro.gif rename to src/Umbraco.Web.UI/Umbraco/Images/editor/insMacro.gif diff --git a/src/Umbraco.Web.UI/umbraco/images/editor/insMacroSB.png b/src/Umbraco.Web.UI/Umbraco/Images/editor/insMacroSB.png similarity index 100% rename from src/Umbraco.Web.UI/umbraco/images/editor/insMacroSB.png rename to src/Umbraco.Web.UI/Umbraco/Images/editor/insMacroSB.png diff --git a/src/Umbraco.Web.UI/umbraco/images/editor/insMemberItem.gif b/src/Umbraco.Web.UI/Umbraco/Images/editor/insMemberItem.gif similarity index 100% rename from src/Umbraco.Web.UI/umbraco/images/editor/insMemberItem.gif rename to src/Umbraco.Web.UI/Umbraco/Images/editor/insMemberItem.gif diff --git a/src/Umbraco.Web.UI/umbraco/images/editor/insRazorMacro.png b/src/Umbraco.Web.UI/Umbraco/Images/editor/insRazorMacro.png similarity index 100% rename from src/Umbraco.Web.UI/umbraco/images/editor/insRazorMacro.png rename to src/Umbraco.Web.UI/Umbraco/Images/editor/insRazorMacro.png diff --git a/src/Umbraco.Web.UI/umbraco/images/editor/inshtml.GIF b/src/Umbraco.Web.UI/Umbraco/Images/editor/inshtml.GIF similarity index 100% rename from src/Umbraco.Web.UI/umbraco/images/editor/inshtml.GIF rename to src/Umbraco.Web.UI/Umbraco/Images/editor/inshtml.GIF diff --git a/src/Umbraco.Web.UI/umbraco/images/editor/masterpageContent.gif b/src/Umbraco.Web.UI/Umbraco/Images/editor/masterpageContent.gif similarity index 100% rename from src/Umbraco.Web.UI/umbraco/images/editor/masterpageContent.gif rename to src/Umbraco.Web.UI/Umbraco/Images/editor/masterpageContent.gif diff --git a/src/Umbraco.Web.UI/umbraco/images/editor/masterpagePlaceHolder.gif b/src/Umbraco.Web.UI/Umbraco/Images/editor/masterpagePlaceHolder.gif similarity index 100% rename from src/Umbraco.Web.UI/umbraco/images/editor/masterpagePlaceHolder.gif rename to src/Umbraco.Web.UI/Umbraco/Images/editor/masterpagePlaceHolder.gif diff --git a/src/Umbraco.Web.UI/umbraco/images/editor/xslVisualize.gif b/src/Umbraco.Web.UI/Umbraco/Images/editor/xslVisualize.gif similarity index 100% rename from src/Umbraco.Web.UI/umbraco/images/editor/xslVisualize.gif rename to src/Umbraco.Web.UI/Umbraco/Images/editor/xslVisualize.gif diff --git a/src/Umbraco.Web.UI/Umbraco/Images/pinnedIcons/task_content.ico b/src/Umbraco.Web.UI/Umbraco/Images/pinnedIcons/task_content.ico deleted file mode 100644 index 06aed6d45d..0000000000 Binary files a/src/Umbraco.Web.UI/Umbraco/Images/pinnedIcons/task_content.ico and /dev/null differ diff --git a/src/Umbraco.Web.UI/Umbraco/Images/pinnedIcons/task_default.ico b/src/Umbraco.Web.UI/Umbraco/Images/pinnedIcons/task_default.ico deleted file mode 100644 index 8ccffe0794..0000000000 Binary files a/src/Umbraco.Web.UI/Umbraco/Images/pinnedIcons/task_default.ico and /dev/null differ diff --git a/src/Umbraco.Web.UI/Umbraco/Images/pinnedIcons/task_developer.ico b/src/Umbraco.Web.UI/Umbraco/Images/pinnedIcons/task_developer.ico deleted file mode 100644 index 07bbf289e9..0000000000 Binary files a/src/Umbraco.Web.UI/Umbraco/Images/pinnedIcons/task_developer.ico and /dev/null differ diff --git a/src/Umbraco.Web.UI/Umbraco/Images/pinnedIcons/task_media.ico b/src/Umbraco.Web.UI/Umbraco/Images/pinnedIcons/task_media.ico deleted file mode 100644 index 50e357ca8b..0000000000 Binary files a/src/Umbraco.Web.UI/Umbraco/Images/pinnedIcons/task_media.ico and /dev/null differ diff --git a/src/Umbraco.Web.UI/Umbraco/Images/pinnedIcons/task_member.ico b/src/Umbraco.Web.UI/Umbraco/Images/pinnedIcons/task_member.ico deleted file mode 100644 index 7d68fa3c81..0000000000 Binary files a/src/Umbraco.Web.UI/Umbraco/Images/pinnedIcons/task_member.ico and /dev/null differ diff --git a/src/Umbraco.Web.UI/Umbraco/Images/pinnedIcons/task_settings.ico b/src/Umbraco.Web.UI/Umbraco/Images/pinnedIcons/task_settings.ico deleted file mode 100644 index 619bdf265d..0000000000 Binary files a/src/Umbraco.Web.UI/Umbraco/Images/pinnedIcons/task_settings.ico and /dev/null differ diff --git a/src/Umbraco.Web.UI/Umbraco/Images/pinnedIcons/task_users.ico b/src/Umbraco.Web.UI/Umbraco/Images/pinnedIcons/task_users.ico deleted file mode 100644 index 925f0f60d3..0000000000 Binary files a/src/Umbraco.Web.UI/Umbraco/Images/pinnedIcons/task_users.ico and /dev/null differ diff --git a/src/Umbraco.Web.UI/Umbraco/Images/pinnedIcons/umb.ico b/src/Umbraco.Web.UI/Umbraco/Images/pinnedIcons/umb.ico deleted file mode 100644 index b1baa5b622..0000000000 Binary files a/src/Umbraco.Web.UI/Umbraco/Images/pinnedIcons/umb.ico and /dev/null differ diff --git a/src/Umbraco.Web.UI/Umbraco/Images/umbraco/icon_folder.gif b/src/Umbraco.Web.UI/Umbraco/Images/umbraco/icon_folder.gif deleted file mode 100644 index 4d4fdc8e92..0000000000 Binary files a/src/Umbraco.Web.UI/Umbraco/Images/umbraco/icon_folder.gif and /dev/null differ diff --git a/src/Umbraco.Web.UI/Umbraco/config/lang/cs.xml b/src/Umbraco.Web.UI/Umbraco/config/lang/cs.xml index c1e806177a..20e252c431 100644 --- a/src/Umbraco.Web.UI/Umbraco/config/lang/cs.xml +++ b/src/Umbraco.Web.UI/Umbraco/config/lang/cs.xml @@ -964,6 +964,7 @@ Šablony XSLT soubory Typy Uživatelů + Uživatelé Nová aktualizace je připrvena diff --git a/src/Umbraco.Web.UI/Umbraco/config/lang/nb.xml b/src/Umbraco.Web.UI/Umbraco/config/lang/nb.xml index 0d527fe4d8..12031dc0e0 100644 --- a/src/Umbraco.Web.UI/Umbraco/config/lang/nb.xml +++ b/src/Umbraco.Web.UI/Umbraco/config/lang/nb.xml @@ -929,6 +929,7 @@ Vennlig hilsen Umbraco roboten XSLT Filer Analytics Brukertyper typer + Brukere Ny oppdatering er klar diff --git a/src/Umbraco.Web.UI/config/trees.Release.config b/src/Umbraco.Web.UI/config/trees.Release.config index 2825b5205e..844fe9617b 100644 --- a/src/Umbraco.Web.UI/config/trees.Release.config +++ b/src/Umbraco.Web.UI/config/trees.Release.config @@ -3,47 +3,39 @@ - - - - - - - + + + + + - - + - - - + + - + - - - + - + - - \ No newline at end of file diff --git a/src/Umbraco.Web.UI/config/trees.config b/src/Umbraco.Web.UI/config/trees.config index dece42a362..e2e1e7dc10 100644 --- a/src/Umbraco.Web.UI/config/trees.config +++ b/src/Umbraco.Web.UI/config/trees.config @@ -9,22 +9,21 @@ - - - - + + + - + - - + + - + @@ -32,7 +31,7 @@ - + @@ -41,4 +40,5 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI/config/umbracoSettings.config b/src/Umbraco.Web.UI/config/umbracoSettings.config index dcf9c4c7e4..200c30648c 100644 --- a/src/Umbraco.Web.UI/config/umbracoSettings.config +++ b/src/Umbraco.Web.UI/config/umbracoSettings.config @@ -103,6 +103,9 @@ false + + true + diff --git a/src/Umbraco.Web.UI/umbraco/Views/Default.cshtml b/src/Umbraco.Web.UI/umbraco/Views/Default.cshtml index 8fb1487713..7b1f83115f 100644 --- a/src/Umbraco.Web.UI/umbraco/Views/Default.cshtml +++ b/src/Umbraco.Web.UI/umbraco/Views/Default.cshtml @@ -71,8 +71,8 @@ diff --git a/src/Umbraco.Web.UI/umbraco/config/create/UI.Release.xml b/src/Umbraco.Web.UI/umbraco/config/create/UI.Release.xml index 9fca6d082a..fdb8697398 100644 --- a/src/Umbraco.Web.UI/umbraco/config/create/UI.Release.xml +++ b/src/Umbraco.Web.UI/umbraco/config/create/UI.Release.xml @@ -115,14 +115,7 @@ - -
Dictionary editor egenskab
- /create/simple.ascx - - - -
- +
Dictionary editor egenskab
/create/simple.ascx diff --git a/src/Umbraco.Web.UI/umbraco/config/create/UI.xml b/src/Umbraco.Web.UI/umbraco/config/create/UI.xml index f6859c6423..d8d3064f7b 100644 --- a/src/Umbraco.Web.UI/umbraco/config/create/UI.xml +++ b/src/Umbraco.Web.UI/umbraco/config/create/UI.xml @@ -40,6 +40,7 @@
Xslt
/create/xslt.ascx +
@@ -72,6 +73,14 @@
+ +
Stylesheet
+ /create/simple.ascx + + + + +
XSLT file
/create/xslt.ascx @@ -101,14 +110,7 @@
- -
Dictionary editor egenskab
- /create/simple.ascx - - - -
- +
Dictionary editor egenskab
/create/simple.ascx @@ -229,6 +231,13 @@
+ +
Macro
+ /Create/PartialView.ascx + + + +
Macro
/Create/PartialViewMacro.ascx @@ -237,6 +246,13 @@
+ +
Macro
+ /Create/PartialViewMacro.ascx + + + +
Macro
/Create/PartialView.ascx diff --git a/src/Umbraco.Web.UI/umbraco/config/lang/da.xml b/src/Umbraco.Web.UI/umbraco/config/lang/da.xml index aad5e0d69b..df4318ec2a 100644 --- a/src/Umbraco.Web.UI/umbraco/config/lang/da.xml +++ b/src/Umbraco.Web.UI/umbraco/config/lang/da.xml @@ -999,6 +999,7 @@ Mange hilsner fra Umbraco robotten XSLT-filer Analytics Bruger Typer + Brugere Ny opdatering er klar diff --git a/src/Umbraco.Web.UI/umbraco/config/lang/de.xml b/src/Umbraco.Web.UI/umbraco/config/lang/de.xml index 158bb06287..4bb906f983 100644 --- a/src/Umbraco.Web.UI/umbraco/config/lang/de.xml +++ b/src/Umbraco.Web.UI/umbraco/config/lang/de.xml @@ -947,6 +947,7 @@ Ihr freundlicher Umbraco-Robot XSLT-Dateien Auswertungen Benutzertypen + Benutzer Neues Update verfügbar diff --git a/src/Umbraco.Web.UI/umbraco/config/lang/en.xml b/src/Umbraco.Web.UI/umbraco/config/lang/en.xml index f6d092ba31..1360c09667 100644 --- a/src/Umbraco.Web.UI/umbraco/config/lang/en.xml +++ b/src/Umbraco.Web.UI/umbraco/config/lang/en.xml @@ -271,7 +271,8 @@ External login providers Exception Details - Stacktrace + Stacktrace + Inner Exception Link your Un-Link your @@ -289,6 +290,7 @@ Enter your username Enter your password + Confirm your password Name the %0%... Enter a name... Label... @@ -296,6 +298,7 @@ Type to search... Type to filter... Type to add tags (press enter after each tag)... + Enter your email Allow at root @@ -659,6 +662,17 @@ To manage your website, simply open the Umbraco back office and start adding con Log in below Session timed out © 2001 - %0%
Umbraco.com

]]>
+ Forgotten password? + An email will be sent to the address specified with a link to reset your password + An email with password reset instructions will be sent to the specified address if it matched our records + Return to login form + Please provide a new password + Your Password has been updated + The link you have clicked on is invalid or has expired + Umbraco: Reset Password + + Your username to login to the Umbraco back-office is: %0%

Click here to reset your password or copy/paste this URL into your browser:

%1%

]]> +
Dashboard @@ -1189,6 +1203,7 @@ To manage your website, simply open the Umbraco back office and start adding con XSLT Files Analytics User Types + Users New update ready diff --git a/src/Umbraco.Web.UI/umbraco/config/lang/en_us.xml b/src/Umbraco.Web.UI/umbraco/config/lang/en_us.xml index f89eb06b94..700c252cde 100644 --- a/src/Umbraco.Web.UI/umbraco/config/lang/en_us.xml +++ b/src/Umbraco.Web.UI/umbraco/config/lang/en_us.xml @@ -175,6 +175,7 @@ Link to media or click here to choose files Only allowed file types are + Cannot upload this file, it does not have an approved file type Max file size is @@ -271,7 +272,8 @@ External login providers Exception Details - Stacktrace + Stacktrace + Inner Exception Link your Un-Link your @@ -289,6 +291,7 @@ Enter your username Enter your password + Confirm your password Name the %0%... Enter a name... Label... @@ -296,6 +299,7 @@ Type to search... Type to filter... Type to add tags (press enter after each tag)... + Enter your email @@ -656,6 +660,17 @@ To manage your website, simply open the Umbraco back office and start adding con Log in below Session timed out © 2001 - %0%
Umbraco.com

]]>
+ Forgotten password? + An email will be sent to the address specified with a link to reset your password + An email with password reset instructions will be sent to the specified address if it matched our records + Return to login form + Please provide a new password + Your Password has been updated + The link you have clicked on is invalid or has expired + Umbraco: Reset Password + + Your username to login to the Umbraco back-office is: %0%

Click here to reset your password or copy/paste this URL into your browser:

%1%

]]> +
Dashboard @@ -1193,6 +1208,7 @@ To manage your website, simply open the Umbraco back office and start adding con XSLT Files Analytics User Types + Users New update ready diff --git a/src/Umbraco.Web.UI/umbraco/config/lang/es.xml b/src/Umbraco.Web.UI/umbraco/config/lang/es.xml index ef67c6e6d4..097c028d2b 100644 --- a/src/Umbraco.Web.UI/umbraco/config/lang/es.xml +++ b/src/Umbraco.Web.UI/umbraco/config/lang/es.xml @@ -851,6 +851,7 @@ Plantillas Archivos XSLT Tipos de Usuarios + Usuarios Existe una nueva actualización diff --git a/src/Umbraco.Web.UI/umbraco/config/lang/fr.xml b/src/Umbraco.Web.UI/umbraco/config/lang/fr.xml index 4045056567..853f1b11f1 100644 --- a/src/Umbraco.Web.UI/umbraco/config/lang/fr.xml +++ b/src/Umbraco.Web.UI/umbraco/config/lang/fr.xml @@ -985,6 +985,7 @@ Pour gérer votre site, ouvrez simplement le backoffice Umbraco et commencez à Modèles Fichiers XSLT Types d'utilisateurs + Utilisateurs Nouvelle mise à jour prête diff --git a/src/Umbraco.Web.UI/umbraco/config/lang/he.xml b/src/Umbraco.Web.UI/umbraco/config/lang/he.xml index 8722008a2e..e42c382b20 100644 --- a/src/Umbraco.Web.UI/umbraco/config/lang/he.xml +++ b/src/Umbraco.Web.UI/umbraco/config/lang/he.xml @@ -870,6 +870,7 @@ To manage your website, simply open the Umbraco back office and start adding con תבניות קבצי XSLT משתמש מקליד + משתמש עידכון חדש זמין diff --git a/src/Umbraco.Web.UI/umbraco/config/lang/it.xml b/src/Umbraco.Web.UI/umbraco/config/lang/it.xml index f4475cb23c..039d727044 100644 --- a/src/Umbraco.Web.UI/umbraco/config/lang/it.xml +++ b/src/Umbraco.Web.UI/umbraco/config/lang/it.xml @@ -843,6 +843,7 @@ Per gestire il tuo sito web, è sufficiente aprire il back office di Umbraco e i Templates Files XSLT Tipi di Utente + Utenti diff --git a/src/Umbraco.Web.UI/umbraco/config/lang/ja.xml b/src/Umbraco.Web.UI/umbraco/config/lang/ja.xml index b92f17a57e..bbe3152464 100644 --- a/src/Umbraco.Web.UI/umbraco/config/lang/ja.xml +++ b/src/Umbraco.Web.UI/umbraco/config/lang/ja.xml @@ -242,7 +242,7 @@ 項目の選択 キャッシュされている項目の表示 フォルダーの作成... - + オリジナルに関連付ける フレンドリーなコミュニティ @@ -267,7 +267,8 @@ 外部ログイン プロバイダー 例外の詳細 - スタックトレース + スタックトレース + Inner Exception 次をリンク: 次をリンク解除: @@ -475,7 +476,7 @@ 移動 埋め込み - + ブラック グリーン @@ -484,7 +485,7 @@ ブルー レッド - + タブの追加 プロパティの追加 @@ -503,7 +504,7 @@ リスト ビューの切り替え ルートとして許可に切り替え - + 背景色 太字 @@ -537,7 +538,7 @@ アップグレードボタンを押すとUmbraco %0% 用にデータベースをアップグレードします。

心配ありません。 - コンテントが消える事はありませんし、後で続けることもできます。 -

+

]]> 次へ を押して続行してください。]]> @@ -583,7 +584,7 @@ ]]> スクラッチから始めたい どうしたらいいの?) 後からRunwayをインストールする事もできます。そうしたくなった時は、Developerセクションのパッケージへどうぞ。 ]]> @@ -597,8 +598,8 @@ 簡単なウェブサイトから始めたい - "Runway"(≈滑走路)は幾つかの基本的なテンプレートから簡単なウェブサイトを用意します。このインストーラーは自動的にRnwayをセットアップできますが、 - これを編集したり、拡張したり、削除する事も簡単にできます。もしUmbracoを完璧に使いこなせるならばこれは不要です。とはいえ、 + "Runway"(≈滑走路)は幾つかの基本的なテンプレートから簡単なウェブサイトを用意します。このインストーラーは自動的にRnwayをセットアップできますが、 + これを編集したり、拡張したり、削除する事も簡単にできます。もしUmbracoを完璧に使いこなせるならばこれは不要です。とはいえ、 Runwayを使う事は、手間なく簡単にUmbracoを始める為には良い選択肢です。 Runwayをインストールすれば、必要に応じてRunwayによる基本的な構成のページをRunwayのモジュールから選択できます。

@@ -692,7 +693,7 @@ Runwayをインストールして作られた新しいウェブサイトがど

ユーザー '%3%' によりページ '%2%' 上のタスク '%1%' から自動的にメールします。

@@ -704,7 +705,7 @@ Runwayをインストールして作られた新しいウェブサイトがど

@@ -1064,7 +1065,7 @@ Runwayをインストールして作られた新しいウェブサイトがど このエディターを使用すると新しい設定で更新されます - + 代替フィールド 代替テキスト @@ -1159,7 +1160,7 @@ Runwayをインストールして作られた新しいウェブサイトがど 役割 メンバーの種類 ドキュメントタイプ - 関連タイプ + 関連タイプ パッケージ パッケージ Python ファイル @@ -1173,6 +1174,7 @@ Runwayをインストールして作られた新しいウェブサイトがど XSLT ファイル アナリティクス ユーザータイプ + ユーザー 新しい更新があります diff --git a/src/Umbraco.Web.UI/umbraco/config/lang/ko.xml b/src/Umbraco.Web.UI/umbraco/config/lang/ko.xml index 9743954202..8435cb9c48 100644 --- a/src/Umbraco.Web.UI/umbraco/config/lang/ko.xml +++ b/src/Umbraco.Web.UI/umbraco/config/lang/ko.xml @@ -847,6 +847,7 @@ 템플릿 XSLT 파일 사용자 유형 + 사용자 새 업데이트가 준비되었습니다. diff --git a/src/Umbraco.Web.UI/umbraco/config/lang/nl.xml b/src/Umbraco.Web.UI/umbraco/config/lang/nl.xml index 9cf8e76337..d69d5954dd 100644 --- a/src/Umbraco.Web.UI/umbraco/config/lang/nl.xml +++ b/src/Umbraco.Web.UI/umbraco/config/lang/nl.xml @@ -952,6 +952,7 @@ Om een vertalingstaak te sluiten, ga aub naar het detailoverzicht en klik op de Sjablonen XSLT Bestanden Gebruiker Types + Gebruikers Nieuwe update beschikbaar diff --git a/src/Umbraco.Web.UI/umbraco/config/lang/pl.xml b/src/Umbraco.Web.UI/umbraco/config/lang/pl.xml index 132f5ee65e..dbdefcb6c2 100644 --- a/src/Umbraco.Web.UI/umbraco/config/lang/pl.xml +++ b/src/Umbraco.Web.UI/umbraco/config/lang/pl.xml @@ -743,6 +743,7 @@ Miłego dnia!]]>
Szablony Pliki XSLT Typy Użytkowników + Użytkowników Aktualizacja jest gotowa diff --git a/src/Umbraco.Web.UI/umbraco/config/lang/pt.xml b/src/Umbraco.Web.UI/umbraco/config/lang/pt.xml index 9cf9181c80..86887b00df 100644 --- a/src/Umbraco.Web.UI/umbraco/config/lang/pt.xml +++ b/src/Umbraco.Web.UI/umbraco/config/lang/pt.xml @@ -831,6 +831,7 @@ Para fechar a tarefa de tradução vá até os detalhes e clique no botão "Fech Modelos Arquivos XSLT Tipos de Usuários + Usuários Nova atualização pronta diff --git a/src/Umbraco.Web.UI/umbraco/config/lang/ru.xml b/src/Umbraco.Web.UI/umbraco/config/lang/ru.xml index 5075fd8eb9..09edfdeb6a 100644 --- a/src/Umbraco.Web.UI/umbraco/config/lang/ru.xml +++ b/src/Umbraco.Web.UI/umbraco/config/lang/ru.xml @@ -189,10 +189,10 @@ Унаследован от Добавить свойство Обязательная метка - + Представление в формате списка Устанавливает представление документа данного типа в виде сортируемого списка дочерних документов с функцией поиска, в отличие от обычного представления дочерних документов в виде дерева - + Допустимые шаблоны Выберите перечень допустимых шаблонов для сопоставления документам данного типа Разрешить в качестве корневого @@ -206,31 +206,31 @@ Унаследовать вкладки и свойства из уже существующего типа документов. Вкладки будут либо добавлены в создаваемый тип, либо в случае совпадения названий вкладок будут добавлены наследуемые свойства. Этот тип документов уже участвует в композиции другого типа, поэтому сам не может быть композицией. В настоящее время нет типов документов, допустимых для построения композиции. - + Доступные редакторы Переиспользовать Установки редактора - + Конфигурирование - + ДА, удалить - + была перемещена внутрь Выбрать папку для перемещения в структуре дерева - + Все типы документов Все документы Все медиа-элементы - + , использующие этот тип документов, будут безвозвратно удалены, пожалуйста, подтвердите это действие. , использующие этот тип медиа, будут безвозвратно удалены, пожалуйста, подтвердите это действие. , использующие этот тип участников, будут безвозвратно удалены, пожалуйста, подтвердите это действие. - + и все документы, использующие данный тип и все медиа-элементы, использующие данный тип и все участники, использующие данный тип - + , использующие этот редактор, будут обновлены с применением этих установок Участник может изменить @@ -302,18 +302,18 @@ Выберите элемент Просмотр элемента кэша Создать папку... - + Связать с оригиналом Самое дружелюбное сообщество - + Ссылка на страницу - + Открывает документ по ссылке в новом окне или вкладке браузера Открывает документ по ссылке в полноэкранном режиме Открывает документ по ссылке в родительском фрейме - + Ссылка на медиа-файл - + Выбрать медиа Выбрать значок Выбрать элемент @@ -322,23 +322,24 @@ Выбрать содержимое Выбрать участника Выбрать группу участников - + Это макрос без параметров - + Провайдеры аутентификации Подробное сообщение об ошибке - Трассировка стека - + Трассировка стека + Inner Exception + Связать Разорвать связь - + учетную запись - + Выбрать редактор %0%'
Добавить другие языки можно, воспользовавшись пунктом 'Языки' в меню слева + Ниже Вы можете указать различные переводы данной статьи словаря '%0%'
Добавить другие языки можно, воспользовавшись пунктом 'Языки' в меню слева ]]>
Название языка (культуры) @@ -397,7 +398,7 @@ Ошибка загрузки внешнего типа (сборка: %0%, тип: '%1%') Ошибка загрузки макроса (файл: %0%) "Ошибка разбора кода XSLT в файле: %0% - "Ошибка чтения XSLT-файла: %0% + "Ошибка чтения XSLT-файла: %0% Ошибка в конфигурации типа данных, используемого для свойства, проверьте тип данных Укажите заголовок Выберите тип @@ -876,7 +877,7 @@ ]]> + ]]> @@ -959,14 +960,14 @@ Добавить шаблон Добавить дочерний узел Добавить дочерний - + Изменить тип данных - + Навигация по разделам - + Ярлыки показать ярлыки - + В формате списка Разрешить в качестве корневого @@ -1108,7 +1109,7 @@ http://%3%. Удачи! - + Генератор уведомлений Umbraco. ]]> [%0%] Задание по переводу %1% @@ -1162,6 +1163,7 @@ Шаблоны Файлы XSLT Типы пользователей + пользователи Доступны обновления diff --git a/src/Umbraco.Web.UI/umbraco/config/lang/sv.xml b/src/Umbraco.Web.UI/umbraco/config/lang/sv.xml index 3c7947ccee..ae7e8a479e 100644 --- a/src/Umbraco.Web.UI/umbraco/config/lang/sv.xml +++ b/src/Umbraco.Web.UI/umbraco/config/lang/sv.xml @@ -852,6 +852,7 @@ Sidmallar XSLT-filer Användartyper + Användare Ny uppdatering tillgänglig diff --git a/src/Umbraco.Web.UI/umbraco/config/lang/zh.xml b/src/Umbraco.Web.UI/umbraco/config/lang/zh.xml index 9ced516644..4e25e92ef2 100644 --- a/src/Umbraco.Web.UI/umbraco/config/lang/zh.xml +++ b/src/Umbraco.Web.UI/umbraco/config/lang/zh.xml @@ -921,6 +921,7 @@ 模板 XSLT文件 用户类型 + Users 有可用更新 diff --git a/src/Umbraco.Web.UI/umbraco/dashboard/ExamineManagement.ascx b/src/Umbraco.Web.UI/umbraco/dashboard/ExamineManagement.ascx deleted file mode 100644 index f713f35bee..0000000000 --- a/src/Umbraco.Web.UI/umbraco/dashboard/ExamineManagement.ascx +++ /dev/null @@ -1,216 +0,0 @@ -<%@ Control Language="C#" AutoEventWireup="true" CodeBehind="ExamineManagement.ascx.cs" Inherits="Umbraco.Web.UI.Umbraco.Dashboard.ExamineManagement" %> -<%@ Import Namespace="Umbraco.Core" %> -<%@ Import Namespace="Umbraco.Web" %> -<%@ Import Namespace="umbraco" %> -<%@ Register TagPrefix="cc1" Namespace="Umbraco.Web.UI.Controls" Assembly="umbraco" %> -<%@ Register TagPrefix="umb" Namespace="ClientDependency.Core.Controls" Assembly="ClientDependency.Core" %> - - - - - - - - -
- -
-
- -

Examine Management

- -
- -
- -

Indexers

- -
-
- - -
- -
- Index info & tools -
-
-
- - -
-
- -
-
- The process is taking longer than expected, check the umbraco log to see if there have been any errors during this operation -
-
- - - - - - - - - - - - - -
Documents in index
Fields in index
Has deletions? / Optimized? - - ()/ - -
-
-
- -
- Node types - - - - - - - - - - - - - -
Include node types
Exclude node types
Parent node id
-
- -
- System fields - - - - - - - - - - - - - - - -
NameEnable sortingType
-
- -
- User fields - - - - - - - - - - - - - - - -
NameEnable sortingType
-
- -
- Provider properties - - - - - -
-
-
-
-
- -

Searchers

- -
-
- - -
- -
- Search tools -
- Hide search results - - - - - - -
-
- -
- - - - - - - - - - - - - - - -
ScoreIdValues
- - -
-
-
-
- -
- Provider properties - - - - - -
-
- -
- -
-
- -
-
- -
diff --git a/src/Umbraco.Web.UI/umbraco/dashboard/ExamineManagement.ascx.cs b/src/Umbraco.Web.UI/umbraco/dashboard/ExamineManagement.ascx.cs deleted file mode 100644 index 77a04423c0..0000000000 --- a/src/Umbraco.Web.UI/umbraco/dashboard/ExamineManagement.ascx.cs +++ /dev/null @@ -1,14 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Web; -using System.Web.UI; -using System.Web.UI.WebControls; - -namespace Umbraco.Web.UI.Umbraco.Dashboard -{ - public partial class ExamineManagement : UI.Controls.UmbracoUserControl - { - - } -} \ No newline at end of file diff --git a/src/Umbraco.Web.UI/umbraco/dashboard/ExamineManagement.ascx.designer.cs b/src/Umbraco.Web.UI/umbraco/dashboard/ExamineManagement.ascx.designer.cs deleted file mode 100644 index 71251692aa..0000000000 --- a/src/Umbraco.Web.UI/umbraco/dashboard/ExamineManagement.ascx.designer.cs +++ /dev/null @@ -1,60 +0,0 @@ -//------------------------------------------------------------------------------ -// -// This code was generated by a tool. -// -// Changes to this file may cause incorrect behavior and will be lost if -// the code is regenerated. -// -//------------------------------------------------------------------------------ - -namespace Umbraco.Web.UI.Umbraco.Dashboard { - - - public partial class ExamineManagement { - - /// - /// JsInclude1 control. - /// - /// - /// Auto-generated field. - /// To modify move field declaration from designer file to code-behind file. - /// - protected global::ClientDependency.Core.Controls.JsInclude JsInclude1; - - /// - /// CssInclude1 control. - /// - /// - /// Auto-generated field. - /// To modify move field declaration from designer file to code-behind file. - /// - protected global::ClientDependency.Core.Controls.CssInclude CssInclude1; - - /// - /// ProgBar1 control. - /// - /// - /// Auto-generated field. - /// To modify move field declaration from designer file to code-behind file. - /// - protected global::Umbraco.Web.UI.Controls.ProgressBar ProgBar1; - - /// - /// ProgressBar1 control. - /// - /// - /// Auto-generated field. - /// To modify move field declaration from designer file to code-behind file. - /// - protected global::Umbraco.Web.UI.Controls.ProgressBar ProgressBar1; - - /// - /// ProgressBar2 control. - /// - /// - /// Auto-generated field. - /// To modify move field declaration from designer file to code-behind file. - /// - protected global::Umbraco.Web.UI.Controls.ProgressBar ProgressBar2; - } -} diff --git a/src/Umbraco.Web.UI/umbraco/dashboard/LatestEdits.ascx b/src/Umbraco.Web.UI/umbraco/dashboard/LatestEdits.ascx deleted file mode 100644 index ed85a604f0..0000000000 --- a/src/Umbraco.Web.UI/umbraco/dashboard/LatestEdits.ascx +++ /dev/null @@ -1,11 +0,0 @@ -<%@ Control Language="c#" AutoEventWireup="True" Codebehind="LatestEdits.ascx.cs" Inherits="dashboardUtilities.LatestEdits" %> -<%@ Register TagPrefix="umb" Namespace="ClientDependency.Core.Controls" Assembly="ClientDependency.Core" %> - -

<%=Services.TextService.Localize("defaultdialogs/lastEdited")%>

- \ No newline at end of file diff --git a/src/Umbraco.Web.UI/umbraco/developer/Packages/installedPackage.aspx b/src/Umbraco.Web.UI/umbraco/developer/Packages/installedPackage.aspx index 5939e1abbd..22db3e58cf 100644 --- a/src/Umbraco.Web.UI/umbraco/developer/Packages/installedPackage.aspx +++ b/src/Umbraco.Web.UI/umbraco/developer/Packages/installedPackage.aspx @@ -1,11 +1,12 @@ <%@ Page Language="C#" MasterPageFile="../../masterpages/umbracoPage.Master" AutoEventWireup="true" CodeBehind="installedPackage.aspx.cs" Inherits="umbraco.presentation.developer.packages.installedPackage" %> +<%@ Import Namespace="Umbraco.Core.Configuration" %> <%@ Register TagPrefix="cc2" Namespace="umbraco.uicontrols" Assembly="controls" %> @@ -159,7 +160,7 @@ //This is all a bit zany with double encoding because we have a URL in a hash (#) url part // but it works and maintains query strings - var umbPath = "<%=umbraco.GlobalSettings.Path%>"; + var umbPath = "<%=GlobalSettings.Path%>"; setTimeout(function () { var mainWindow = UmbClientMgr.mainWindow(); diff --git a/src/Umbraco.Web.UI/umbraco/developer/Packages/installer.aspx b/src/Umbraco.Web.UI/umbraco/developer/Packages/installer.aspx index 05f2de9666..f452d7d0e4 100644 --- a/src/Umbraco.Web.UI/umbraco/developer/Packages/installer.aspx +++ b/src/Umbraco.Web.UI/umbraco/developer/Packages/installer.aspx @@ -2,6 +2,7 @@ AutoEventWireup="True" Inherits="umbraco.presentation.developer.packages.Installer" Trace="false" ValidateRequest="false" %> <%@ Import Namespace="umbraco" %> +<%@ Import Namespace="Umbraco.Core.Configuration" %> <%@ Register TagPrefix="cc1" Namespace="umbraco.uicontrols" Assembly="controls" %> diff --git a/src/Umbraco.Web.UI/umbraco/developer/RelationTypes/EditRelationType.aspx b/src/Umbraco.Web.UI/umbraco/developer/RelationTypes/EditRelationType.aspx index e0559a3807..d8f0954331 100644 --- a/src/Umbraco.Web.UI/umbraco/developer/RelationTypes/EditRelationType.aspx +++ b/src/Umbraco.Web.UI/umbraco/developer/RelationTypes/EditRelationType.aspx @@ -1,4 +1,4 @@ -<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="EditRelationType.aspx.cs" Inherits="umbraco.cms.presentation.developer.RelationTypes.EditRelationType" MasterPageFile="../../masterpages/umbracoPage.Master" %> +<%@ Page Language="C#" AutoEventWireup="true" Inherits="umbraco.cms.presentation.developer.RelationTypes.EditRelationType" MasterPageFile="../../masterpages/umbracoPage.Master" %> <%@ Register TagPrefix="umb" Namespace="umbraco.uicontrols" Assembly="controls" %> diff --git a/src/Umbraco.Web.UI/umbraco/images/Lminus.png b/src/Umbraco.Web.UI/umbraco/images/Lminus.png deleted file mode 100644 index f7c43c0aa3..0000000000 Binary files a/src/Umbraco.Web.UI/umbraco/images/Lminus.png and /dev/null differ diff --git a/src/Umbraco.Web.UI/umbraco/images/Lplus.png b/src/Umbraco.Web.UI/umbraco/images/Lplus.png deleted file mode 100644 index 848ec2fc3b..0000000000 Binary files a/src/Umbraco.Web.UI/umbraco/images/Lplus.png and /dev/null differ diff --git a/src/Umbraco.Web.UI/umbraco/images/T.png b/src/Umbraco.Web.UI/umbraco/images/T.png deleted file mode 100644 index 3017325406..0000000000 Binary files a/src/Umbraco.Web.UI/umbraco/images/T.png and /dev/null differ diff --git a/src/Umbraco.Web.UI/umbraco/images/Tminus.png b/src/Umbraco.Web.UI/umbraco/images/Tminus.png deleted file mode 100644 index 2260e4248c..0000000000 Binary files a/src/Umbraco.Web.UI/umbraco/images/Tminus.png and /dev/null differ diff --git a/src/Umbraco.Web.UI/umbraco/images/Tplus.png b/src/Umbraco.Web.UI/umbraco/images/Tplus.png deleted file mode 100644 index 2c8d8f4fd3..0000000000 Binary files a/src/Umbraco.Web.UI/umbraco/images/Tplus.png and /dev/null differ diff --git a/src/Umbraco.Web.UI/umbraco/images/aboutNew.png b/src/Umbraco.Web.UI/umbraco/images/aboutNew.png deleted file mode 100644 index 94e1380167..0000000000 Binary files a/src/Umbraco.Web.UI/umbraco/images/aboutNew.png and /dev/null differ diff --git a/src/Umbraco.Web.UI/umbraco/images/arrawBack.gif b/src/Umbraco.Web.UI/umbraco/images/arrawBack.gif deleted file mode 100644 index 9d3f0ca686..0000000000 Binary files a/src/Umbraco.Web.UI/umbraco/images/arrawBack.gif and /dev/null differ diff --git a/src/Umbraco.Web.UI/umbraco/images/arrowDown.gif b/src/Umbraco.Web.UI/umbraco/images/arrowDown.gif deleted file mode 100644 index a02ccbf6f8..0000000000 Binary files a/src/Umbraco.Web.UI/umbraco/images/arrowDown.gif and /dev/null differ diff --git a/src/Umbraco.Web.UI/umbraco/images/arrowForward.gif b/src/Umbraco.Web.UI/umbraco/images/arrowForward.gif deleted file mode 100644 index bf3f49e024..0000000000 Binary files a/src/Umbraco.Web.UI/umbraco/images/arrowForward.gif and /dev/null differ diff --git a/src/Umbraco.Web.UI/umbraco/images/audit.png b/src/Umbraco.Web.UI/umbraco/images/audit.png deleted file mode 100644 index 71b6ffaf42..0000000000 Binary files a/src/Umbraco.Web.UI/umbraco/images/audit.png and /dev/null differ diff --git a/src/Umbraco.Web.UI/umbraco/images/back.png b/src/Umbraco.Web.UI/umbraco/images/back.png deleted file mode 100644 index d0ab2e28b5..0000000000 Binary files a/src/Umbraco.Web.UI/umbraco/images/back.png and /dev/null differ diff --git a/src/Umbraco.Web.UI/umbraco/images/blank.png b/src/Umbraco.Web.UI/umbraco/images/blank.png deleted file mode 100644 index cee9cd37a1..0000000000 Binary files a/src/Umbraco.Web.UI/umbraco/images/blank.png and /dev/null differ diff --git a/src/Umbraco.Web.UI/umbraco/images/c_b.gif b/src/Umbraco.Web.UI/umbraco/images/c_b.gif deleted file mode 100644 index e5f9404a4c..0000000000 Binary files a/src/Umbraco.Web.UI/umbraco/images/c_b.gif and /dev/null differ diff --git a/src/Umbraco.Web.UI/umbraco/images/c_b_label.gif b/src/Umbraco.Web.UI/umbraco/images/c_b_label.gif deleted file mode 100644 index 8989fb47c9..0000000000 Binary files a/src/Umbraco.Web.UI/umbraco/images/c_b_label.gif and /dev/null differ diff --git a/src/Umbraco.Web.UI/umbraco/images/c_bl.gif b/src/Umbraco.Web.UI/umbraco/images/c_bl.gif deleted file mode 100644 index 0f750a6dfa..0000000000 Binary files a/src/Umbraco.Web.UI/umbraco/images/c_bl.gif and /dev/null differ diff --git a/src/Umbraco.Web.UI/umbraco/images/c_bl_label.gif b/src/Umbraco.Web.UI/umbraco/images/c_bl_label.gif deleted file mode 100644 index 1f55e5b558..0000000000 Binary files a/src/Umbraco.Web.UI/umbraco/images/c_bl_label.gif and /dev/null differ diff --git a/src/Umbraco.Web.UI/umbraco/images/c_br.gif b/src/Umbraco.Web.UI/umbraco/images/c_br.gif deleted file mode 100644 index 2674d46df5..0000000000 Binary files a/src/Umbraco.Web.UI/umbraco/images/c_br.gif and /dev/null differ diff --git a/src/Umbraco.Web.UI/umbraco/images/c_br_label.gif b/src/Umbraco.Web.UI/umbraco/images/c_br_label.gif deleted file mode 100644 index eef15054fe..0000000000 Binary files a/src/Umbraco.Web.UI/umbraco/images/c_br_label.gif and /dev/null differ diff --git a/src/Umbraco.Web.UI/umbraco/images/c_r.gif b/src/Umbraco.Web.UI/umbraco/images/c_r.gif deleted file mode 100644 index c3976c6282..0000000000 Binary files a/src/Umbraco.Web.UI/umbraco/images/c_r.gif and /dev/null differ diff --git a/src/Umbraco.Web.UI/umbraco/images/c_t.gif b/src/Umbraco.Web.UI/umbraco/images/c_t.gif deleted file mode 100644 index 0275958d29..0000000000 Binary files a/src/Umbraco.Web.UI/umbraco/images/c_t.gif and /dev/null differ diff --git a/src/Umbraco.Web.UI/umbraco/images/c_tl.gif b/src/Umbraco.Web.UI/umbraco/images/c_tl.gif deleted file mode 100644 index 836446e39b..0000000000 Binary files a/src/Umbraco.Web.UI/umbraco/images/c_tl.gif and /dev/null differ diff --git a/src/Umbraco.Web.UI/umbraco/images/c_tr.gif b/src/Umbraco.Web.UI/umbraco/images/c_tr.gif deleted file mode 100644 index d88dc80ea4..0000000000 Binary files a/src/Umbraco.Web.UI/umbraco/images/c_tr.gif and /dev/null differ diff --git a/src/Umbraco.Web.UI/umbraco/images/close.png b/src/Umbraco.Web.UI/umbraco/images/close.png deleted file mode 100644 index 443c804940..0000000000 Binary files a/src/Umbraco.Web.UI/umbraco/images/close.png and /dev/null differ diff --git a/src/Umbraco.Web.UI/umbraco/images/collapse.png b/src/Umbraco.Web.UI/umbraco/images/collapse.png deleted file mode 100644 index 9cb8909df2..0000000000 Binary files a/src/Umbraco.Web.UI/umbraco/images/collapse.png and /dev/null differ diff --git a/src/Umbraco.Web.UI/umbraco/images/copy.small.png b/src/Umbraco.Web.UI/umbraco/images/copy.small.png deleted file mode 100644 index ae5ee8c939..0000000000 Binary files a/src/Umbraco.Web.UI/umbraco/images/copy.small.png and /dev/null differ diff --git a/src/Umbraco.Web.UI/umbraco/images/cut.small.png b/src/Umbraco.Web.UI/umbraco/images/cut.small.png deleted file mode 100644 index 9e93684597..0000000000 Binary files a/src/Umbraco.Web.UI/umbraco/images/cut.small.png and /dev/null differ diff --git a/src/Umbraco.Web.UI/umbraco/images/date.gif b/src/Umbraco.Web.UI/umbraco/images/date.gif deleted file mode 100644 index 8f73cb39a6..0000000000 Binary files a/src/Umbraco.Web.UI/umbraco/images/date.gif and /dev/null differ diff --git a/src/Umbraco.Web.UI/umbraco/images/delete.gif b/src/Umbraco.Web.UI/umbraco/images/delete.gif deleted file mode 100644 index b39d476bec..0000000000 Binary files a/src/Umbraco.Web.UI/umbraco/images/delete.gif and /dev/null differ diff --git a/src/Umbraco.Web.UI/umbraco/images/delete.png b/src/Umbraco.Web.UI/umbraco/images/delete.png deleted file mode 100644 index 08f249365a..0000000000 Binary files a/src/Umbraco.Web.UI/umbraco/images/delete.png and /dev/null differ diff --git a/src/Umbraco.Web.UI/umbraco/images/delete.small.png b/src/Umbraco.Web.UI/umbraco/images/delete.small.png deleted file mode 100644 index 294830deda..0000000000 Binary files a/src/Umbraco.Web.UI/umbraco/images/delete.small.png and /dev/null differ diff --git a/src/Umbraco.Web.UI/umbraco/images/delete_button.png b/src/Umbraco.Web.UI/umbraco/images/delete_button.png deleted file mode 100644 index d1d6a64135..0000000000 Binary files a/src/Umbraco.Web.UI/umbraco/images/delete_button.png and /dev/null differ diff --git a/src/Umbraco.Web.UI/umbraco/images/developer/customControlIcon.png b/src/Umbraco.Web.UI/umbraco/images/developer/customControlIcon.png deleted file mode 100644 index b2dcaaa038..0000000000 Binary files a/src/Umbraco.Web.UI/umbraco/images/developer/customControlIcon.png and /dev/null differ diff --git a/src/Umbraco.Web.UI/umbraco/images/developer/usercontrolIcon.png b/src/Umbraco.Web.UI/umbraco/images/developer/usercontrolIcon.png deleted file mode 100644 index d0a01f5179..0000000000 Binary files a/src/Umbraco.Web.UI/umbraco/images/developer/usercontrolIcon.png and /dev/null differ diff --git a/src/Umbraco.Web.UI/umbraco/images/developer/xsltIcon.png b/src/Umbraco.Web.UI/umbraco/images/developer/xsltIcon.png deleted file mode 100644 index 0ed41a0bec..0000000000 Binary files a/src/Umbraco.Web.UI/umbraco/images/developer/xsltIcon.png and /dev/null differ diff --git a/src/Umbraco.Web.UI/umbraco/images/dialogBg.png b/src/Umbraco.Web.UI/umbraco/images/dialogBg.png deleted file mode 100644 index dc8fde7ce6..0000000000 Binary files a/src/Umbraco.Web.UI/umbraco/images/dialogBg.png and /dev/null differ diff --git a/src/Umbraco.Web.UI/umbraco/images/domain.gif b/src/Umbraco.Web.UI/umbraco/images/domain.gif deleted file mode 100644 index c9515d6b74..0000000000 Binary files a/src/Umbraco.Web.UI/umbraco/images/domain.gif and /dev/null differ diff --git a/src/Umbraco.Web.UI/umbraco/images/domain_on.png b/src/Umbraco.Web.UI/umbraco/images/domain_on.png deleted file mode 100644 index a9e7204fdb..0000000000 Binary files a/src/Umbraco.Web.UI/umbraco/images/domain_on.png and /dev/null differ diff --git a/src/Umbraco.Web.UI/umbraco/images/download.png b/src/Umbraco.Web.UI/umbraco/images/download.png deleted file mode 100644 index 0885c935e4..0000000000 Binary files a/src/Umbraco.Web.UI/umbraco/images/download.png and /dev/null differ diff --git a/src/Umbraco.Web.UI/umbraco/images/editor/Bold.GIF b/src/Umbraco.Web.UI/umbraco/images/editor/Bold.GIF deleted file mode 100644 index d6a9cc2cd4..0000000000 Binary files a/src/Umbraco.Web.UI/umbraco/images/editor/Bold.GIF and /dev/null differ diff --git a/src/Umbraco.Web.UI/umbraco/images/editor/Center.GIF b/src/Umbraco.Web.UI/umbraco/images/editor/Center.GIF deleted file mode 100644 index e3f2414e0b..0000000000 Binary files a/src/Umbraco.Web.UI/umbraco/images/editor/Center.GIF and /dev/null differ diff --git a/src/Umbraco.Web.UI/umbraco/images/editor/Copy.GIF b/src/Umbraco.Web.UI/umbraco/images/editor/Copy.GIF deleted file mode 100644 index dc146865c5..0000000000 Binary files a/src/Umbraco.Web.UI/umbraco/images/editor/Copy.GIF and /dev/null differ diff --git a/src/Umbraco.Web.UI/umbraco/images/editor/Cut.GIF b/src/Umbraco.Web.UI/umbraco/images/editor/Cut.GIF deleted file mode 100644 index 4e9a70b6e2..0000000000 Binary files a/src/Umbraco.Web.UI/umbraco/images/editor/Cut.GIF and /dev/null differ diff --git a/src/Umbraco.Web.UI/umbraco/images/editor/DeIndent.GIF b/src/Umbraco.Web.UI/umbraco/images/editor/DeIndent.GIF deleted file mode 100644 index ca939c639d..0000000000 Binary files a/src/Umbraco.Web.UI/umbraco/images/editor/DeIndent.GIF and /dev/null differ diff --git a/src/Umbraco.Web.UI/umbraco/images/editor/Italic.GIF b/src/Umbraco.Web.UI/umbraco/images/editor/Italic.GIF deleted file mode 100644 index 8bb330bd0b..0000000000 Binary files a/src/Umbraco.Web.UI/umbraco/images/editor/Italic.GIF and /dev/null differ diff --git a/src/Umbraco.Web.UI/umbraco/images/editor/Link.GIF b/src/Umbraco.Web.UI/umbraco/images/editor/Link.GIF deleted file mode 100644 index 1accf42626..0000000000 Binary files a/src/Umbraco.Web.UI/umbraco/images/editor/Link.GIF and /dev/null differ diff --git a/src/Umbraco.Web.UI/umbraco/images/editor/Lock.GIF b/src/Umbraco.Web.UI/umbraco/images/editor/Lock.GIF deleted file mode 100644 index 3db8bfe900..0000000000 Binary files a/src/Umbraco.Web.UI/umbraco/images/editor/Lock.GIF and /dev/null differ diff --git a/src/Umbraco.Web.UI/umbraco/images/editor/Open.GIF b/src/Umbraco.Web.UI/umbraco/images/editor/Open.GIF deleted file mode 100644 index 813ad860f4..0000000000 Binary files a/src/Umbraco.Web.UI/umbraco/images/editor/Open.GIF and /dev/null differ diff --git a/src/Umbraco.Web.UI/umbraco/images/editor/Paste.GIF b/src/Umbraco.Web.UI/umbraco/images/editor/Paste.GIF deleted file mode 100644 index 1b45000a01..0000000000 Binary files a/src/Umbraco.Web.UI/umbraco/images/editor/Paste.GIF and /dev/null differ diff --git a/src/Umbraco.Web.UI/umbraco/images/editor/Redo.GIF b/src/Umbraco.Web.UI/umbraco/images/editor/Redo.GIF deleted file mode 100644 index 3af90697f0..0000000000 Binary files a/src/Umbraco.Web.UI/umbraco/images/editor/Redo.GIF and /dev/null differ diff --git a/src/Umbraco.Web.UI/umbraco/images/editor/Save.GIF b/src/Umbraco.Web.UI/umbraco/images/editor/Save.GIF deleted file mode 100644 index 88cb06e446..0000000000 Binary files a/src/Umbraco.Web.UI/umbraco/images/editor/Save.GIF and /dev/null differ diff --git a/src/Umbraco.Web.UI/umbraco/images/editor/SaveAndPublish.gif b/src/Umbraco.Web.UI/umbraco/images/editor/SaveAndPublish.gif deleted file mode 100644 index fa7f4e61f1..0000000000 Binary files a/src/Umbraco.Web.UI/umbraco/images/editor/SaveAndPublish.gif and /dev/null differ diff --git a/src/Umbraco.Web.UI/umbraco/images/editor/SaveAndPublish.png b/src/Umbraco.Web.UI/umbraco/images/editor/SaveAndPublish.png deleted file mode 100644 index 6c42fa3a0c..0000000000 Binary files a/src/Umbraco.Web.UI/umbraco/images/editor/SaveAndPublish.png and /dev/null differ diff --git a/src/Umbraco.Web.UI/umbraco/images/editor/SaveToPublish.gif b/src/Umbraco.Web.UI/umbraco/images/editor/SaveToPublish.gif deleted file mode 100644 index 772f8b0dd0..0000000000 Binary files a/src/Umbraco.Web.UI/umbraco/images/editor/SaveToPublish.gif and /dev/null differ diff --git a/src/Umbraco.Web.UI/umbraco/images/editor/TaskList.GIF b/src/Umbraco.Web.UI/umbraco/images/editor/TaskList.GIF deleted file mode 100644 index 52761babff..0000000000 Binary files a/src/Umbraco.Web.UI/umbraco/images/editor/TaskList.GIF and /dev/null differ diff --git a/src/Umbraco.Web.UI/umbraco/images/editor/Undo.GIF b/src/Umbraco.Web.UI/umbraco/images/editor/Undo.GIF deleted file mode 100644 index 520796d69d..0000000000 Binary files a/src/Umbraco.Web.UI/umbraco/images/editor/Undo.GIF and /dev/null differ diff --git a/src/Umbraco.Web.UI/umbraco/images/editor/anchor.gif b/src/Umbraco.Web.UI/umbraco/images/editor/anchor.gif deleted file mode 100644 index 34ab71534b..0000000000 Binary files a/src/Umbraco.Web.UI/umbraco/images/editor/anchor.gif and /dev/null differ diff --git a/src/Umbraco.Web.UI/umbraco/images/editor/anchor.png b/src/Umbraco.Web.UI/umbraco/images/editor/anchor.png deleted file mode 100644 index f5e292c46d..0000000000 Binary files a/src/Umbraco.Web.UI/umbraco/images/editor/anchor.png and /dev/null differ diff --git a/src/Umbraco.Web.UI/umbraco/images/editor/anchor_symbol.gif b/src/Umbraco.Web.UI/umbraco/images/editor/anchor_symbol.gif deleted file mode 100644 index 2eafd7954e..0000000000 Binary files a/src/Umbraco.Web.UI/umbraco/images/editor/anchor_symbol.gif and /dev/null differ diff --git a/src/Umbraco.Web.UI/umbraco/images/editor/backcolor.gif b/src/Umbraco.Web.UI/umbraco/images/editor/backcolor.gif deleted file mode 100644 index 8a532e5e62..0000000000 Binary files a/src/Umbraco.Web.UI/umbraco/images/editor/backcolor.gif and /dev/null differ diff --git a/src/Umbraco.Web.UI/umbraco/images/editor/bold_de_se.gif b/src/Umbraco.Web.UI/umbraco/images/editor/bold_de_se.gif deleted file mode 100644 index 9b129de25e..0000000000 Binary files a/src/Umbraco.Web.UI/umbraco/images/editor/bold_de_se.gif and /dev/null differ diff --git a/src/Umbraco.Web.UI/umbraco/images/editor/bold_es.gif b/src/Umbraco.Web.UI/umbraco/images/editor/bold_es.gif deleted file mode 100644 index ea341e6089..0000000000 Binary files a/src/Umbraco.Web.UI/umbraco/images/editor/bold_es.gif and /dev/null differ diff --git a/src/Umbraco.Web.UI/umbraco/images/editor/bold_fr.gif b/src/Umbraco.Web.UI/umbraco/images/editor/bold_fr.gif deleted file mode 100644 index 2816454515..0000000000 Binary files a/src/Umbraco.Web.UI/umbraco/images/editor/bold_fr.gif and /dev/null differ diff --git a/src/Umbraco.Web.UI/umbraco/images/editor/bold_ru.gif b/src/Umbraco.Web.UI/umbraco/images/editor/bold_ru.gif deleted file mode 100644 index e000d461c9..0000000000 Binary files a/src/Umbraco.Web.UI/umbraco/images/editor/bold_ru.gif and /dev/null differ diff --git a/src/Umbraco.Web.UI/umbraco/images/editor/bold_tw.gif b/src/Umbraco.Web.UI/umbraco/images/editor/bold_tw.gif deleted file mode 100644 index 82085432c6..0000000000 Binary files a/src/Umbraco.Web.UI/umbraco/images/editor/bold_tw.gif and /dev/null differ diff --git a/src/Umbraco.Web.UI/umbraco/images/editor/browse.gif b/src/Umbraco.Web.UI/umbraco/images/editor/browse.gif deleted file mode 100644 index c786d0b205..0000000000 Binary files a/src/Umbraco.Web.UI/umbraco/images/editor/browse.gif and /dev/null differ diff --git a/src/Umbraco.Web.UI/umbraco/images/editor/bullist.GIF b/src/Umbraco.Web.UI/umbraco/images/editor/bullist.GIF deleted file mode 100644 index 6e19467c70..0000000000 Binary files a/src/Umbraco.Web.UI/umbraco/images/editor/bullist.GIF and /dev/null differ diff --git a/src/Umbraco.Web.UI/umbraco/images/editor/button_menu.gif b/src/Umbraco.Web.UI/umbraco/images/editor/button_menu.gif deleted file mode 100644 index c3d8fa2311..0000000000 Binary files a/src/Umbraco.Web.UI/umbraco/images/editor/button_menu.gif and /dev/null differ diff --git a/src/Umbraco.Web.UI/umbraco/images/editor/buttons.gif b/src/Umbraco.Web.UI/umbraco/images/editor/buttons.gif deleted file mode 100644 index 6196350de8..0000000000 Binary files a/src/Umbraco.Web.UI/umbraco/images/editor/buttons.gif and /dev/null differ diff --git a/src/Umbraco.Web.UI/umbraco/images/editor/calendar.gif b/src/Umbraco.Web.UI/umbraco/images/editor/calendar.gif deleted file mode 100644 index f032ce1570..0000000000 Binary files a/src/Umbraco.Web.UI/umbraco/images/editor/calendar.gif and /dev/null differ diff --git a/src/Umbraco.Web.UI/umbraco/images/editor/calendarButton.gif b/src/Umbraco.Web.UI/umbraco/images/editor/calendarButton.gif deleted file mode 100644 index f8f5f2a132..0000000000 Binary files a/src/Umbraco.Web.UI/umbraco/images/editor/calendarButton.gif and /dev/null differ diff --git a/src/Umbraco.Web.UI/umbraco/images/editor/cancel_button_bg.gif b/src/Umbraco.Web.UI/umbraco/images/editor/cancel_button_bg.gif deleted file mode 100644 index 4b4aeefcbb..0000000000 Binary files a/src/Umbraco.Web.UI/umbraco/images/editor/cancel_button_bg.gif and /dev/null differ diff --git a/src/Umbraco.Web.UI/umbraco/images/editor/charmap.gif b/src/Umbraco.Web.UI/umbraco/images/editor/charmap.gif deleted file mode 100644 index 3cdc4ac913..0000000000 Binary files a/src/Umbraco.Web.UI/umbraco/images/editor/charmap.gif and /dev/null differ diff --git a/src/Umbraco.Web.UI/umbraco/images/editor/cleanup.gif b/src/Umbraco.Web.UI/umbraco/images/editor/cleanup.gif deleted file mode 100644 index 16491f6cfc..0000000000 Binary files a/src/Umbraco.Web.UI/umbraco/images/editor/cleanup.gif and /dev/null differ diff --git a/src/Umbraco.Web.UI/umbraco/images/editor/close.gif b/src/Umbraco.Web.UI/umbraco/images/editor/close.gif deleted file mode 100644 index 679ca2aa47..0000000000 Binary files a/src/Umbraco.Web.UI/umbraco/images/editor/close.gif and /dev/null differ diff --git a/src/Umbraco.Web.UI/umbraco/images/editor/code.gif b/src/Umbraco.Web.UI/umbraco/images/editor/code.gif deleted file mode 100644 index c5d5a67275..0000000000 Binary files a/src/Umbraco.Web.UI/umbraco/images/editor/code.gif and /dev/null differ diff --git a/src/Umbraco.Web.UI/umbraco/images/editor/color.gif b/src/Umbraco.Web.UI/umbraco/images/editor/color.gif deleted file mode 100644 index 1ecd5743b6..0000000000 Binary files a/src/Umbraco.Web.UI/umbraco/images/editor/color.gif and /dev/null differ diff --git a/src/Umbraco.Web.UI/umbraco/images/editor/custom_1.gif b/src/Umbraco.Web.UI/umbraco/images/editor/custom_1.gif deleted file mode 100644 index 4cbccdadf6..0000000000 Binary files a/src/Umbraco.Web.UI/umbraco/images/editor/custom_1.gif and /dev/null differ diff --git a/src/Umbraco.Web.UI/umbraco/images/editor/delcell.GIF b/src/Umbraco.Web.UI/umbraco/images/editor/delcell.GIF deleted file mode 100644 index 21eacbcf1d..0000000000 Binary files a/src/Umbraco.Web.UI/umbraco/images/editor/delcell.GIF and /dev/null differ diff --git a/src/Umbraco.Web.UI/umbraco/images/editor/delcol.GIF b/src/Umbraco.Web.UI/umbraco/images/editor/delcol.GIF deleted file mode 100644 index 3c2d5b6a86..0000000000 Binary files a/src/Umbraco.Web.UI/umbraco/images/editor/delcol.GIF and /dev/null differ diff --git a/src/Umbraco.Web.UI/umbraco/images/editor/delrow.GIF b/src/Umbraco.Web.UI/umbraco/images/editor/delrow.GIF deleted file mode 100644 index 4b66eb2433..0000000000 Binary files a/src/Umbraco.Web.UI/umbraco/images/editor/delrow.GIF and /dev/null differ diff --git a/src/Umbraco.Web.UI/umbraco/images/editor/dezoom.gif b/src/Umbraco.Web.UI/umbraco/images/editor/dezoom.gif deleted file mode 100644 index adf24449a6..0000000000 Binary files a/src/Umbraco.Web.UI/umbraco/images/editor/dezoom.gif and /dev/null differ diff --git a/src/Umbraco.Web.UI/umbraco/images/editor/doc.gif b/src/Umbraco.Web.UI/umbraco/images/editor/doc.gif deleted file mode 100644 index 1d70fcc88d..0000000000 Binary files a/src/Umbraco.Web.UI/umbraco/images/editor/doc.gif and /dev/null differ diff --git a/src/Umbraco.Web.UI/umbraco/images/editor/documentType.gif b/src/Umbraco.Web.UI/umbraco/images/editor/documentType.gif deleted file mode 100644 index 0fb441068a..0000000000 Binary files a/src/Umbraco.Web.UI/umbraco/images/editor/documentType.gif and /dev/null differ diff --git a/src/Umbraco.Web.UI/umbraco/images/editor/forecolor.gif b/src/Umbraco.Web.UI/umbraco/images/editor/forecolor.gif deleted file mode 100644 index d5e381425f..0000000000 Binary files a/src/Umbraco.Web.UI/umbraco/images/editor/forecolor.gif and /dev/null differ diff --git a/src/Umbraco.Web.UI/umbraco/images/editor/form.gif b/src/Umbraco.Web.UI/umbraco/images/editor/form.gif deleted file mode 100644 index 113dc8ca67..0000000000 Binary files a/src/Umbraco.Web.UI/umbraco/images/editor/form.gif and /dev/null differ diff --git a/src/Umbraco.Web.UI/umbraco/images/editor/formButton.gif b/src/Umbraco.Web.UI/umbraco/images/editor/formButton.gif deleted file mode 100644 index a2519973ab..0000000000 Binary files a/src/Umbraco.Web.UI/umbraco/images/editor/formButton.gif and /dev/null differ diff --git a/src/Umbraco.Web.UI/umbraco/images/editor/formCheckbox.gif b/src/Umbraco.Web.UI/umbraco/images/editor/formCheckbox.gif deleted file mode 100644 index 1783cade9e..0000000000 Binary files a/src/Umbraco.Web.UI/umbraco/images/editor/formCheckbox.gif and /dev/null differ diff --git a/src/Umbraco.Web.UI/umbraco/images/editor/formHidden.gif b/src/Umbraco.Web.UI/umbraco/images/editor/formHidden.gif deleted file mode 100644 index 306a5cacc9..0000000000 Binary files a/src/Umbraco.Web.UI/umbraco/images/editor/formHidden.gif and /dev/null differ diff --git a/src/Umbraco.Web.UI/umbraco/images/editor/formRadio.gif b/src/Umbraco.Web.UI/umbraco/images/editor/formRadio.gif deleted file mode 100644 index fef3b52f8f..0000000000 Binary files a/src/Umbraco.Web.UI/umbraco/images/editor/formRadio.gif and /dev/null differ diff --git a/src/Umbraco.Web.UI/umbraco/images/editor/formSelect.gif b/src/Umbraco.Web.UI/umbraco/images/editor/formSelect.gif deleted file mode 100644 index 784a82d68e..0000000000 Binary files a/src/Umbraco.Web.UI/umbraco/images/editor/formSelect.gif and /dev/null differ diff --git a/src/Umbraco.Web.UI/umbraco/images/editor/formText.gif b/src/Umbraco.Web.UI/umbraco/images/editor/formText.gif deleted file mode 100644 index 180e890d9d..0000000000 Binary files a/src/Umbraco.Web.UI/umbraco/images/editor/formText.gif and /dev/null differ diff --git a/src/Umbraco.Web.UI/umbraco/images/editor/formTextarea.gif b/src/Umbraco.Web.UI/umbraco/images/editor/formTextarea.gif deleted file mode 100644 index 6840719407..0000000000 Binary files a/src/Umbraco.Web.UI/umbraco/images/editor/formTextarea.gif and /dev/null differ diff --git a/src/Umbraco.Web.UI/umbraco/images/editor/fullscrn.GIF b/src/Umbraco.Web.UI/umbraco/images/editor/fullscrn.GIF deleted file mode 100644 index 11d7dc8c5f..0000000000 Binary files a/src/Umbraco.Web.UI/umbraco/images/editor/fullscrn.GIF and /dev/null differ diff --git a/src/Umbraco.Web.UI/umbraco/images/editor/help.gif b/src/Umbraco.Web.UI/umbraco/images/editor/help.gif deleted file mode 100644 index 51a1ee4207..0000000000 Binary files a/src/Umbraco.Web.UI/umbraco/images/editor/help.gif and /dev/null differ diff --git a/src/Umbraco.Web.UI/umbraco/images/editor/hr.gif b/src/Umbraco.Web.UI/umbraco/images/editor/hr.gif deleted file mode 100644 index 1a1ba2a015..0000000000 Binary files a/src/Umbraco.Web.UI/umbraco/images/editor/hr.gif and /dev/null differ diff --git a/src/Umbraco.Web.UI/umbraco/images/editor/html.gif b/src/Umbraco.Web.UI/umbraco/images/editor/html.gif deleted file mode 100644 index 7cc39ae4f1..0000000000 Binary files a/src/Umbraco.Web.UI/umbraco/images/editor/html.gif and /dev/null differ diff --git a/src/Umbraco.Web.UI/umbraco/images/editor/image.GIF b/src/Umbraco.Web.UI/umbraco/images/editor/image.GIF deleted file mode 100644 index 4b88eddc26..0000000000 Binary files a/src/Umbraco.Web.UI/umbraco/images/editor/image.GIF and /dev/null differ diff --git a/src/Umbraco.Web.UI/umbraco/images/editor/indent.gif b/src/Umbraco.Web.UI/umbraco/images/editor/indent.gif deleted file mode 100644 index acd315bb16..0000000000 Binary files a/src/Umbraco.Web.UI/umbraco/images/editor/indent.gif and /dev/null differ diff --git a/src/Umbraco.Web.UI/umbraco/images/editor/inindent.GIF b/src/Umbraco.Web.UI/umbraco/images/editor/inindent.GIF deleted file mode 100644 index 5afc8877ed..0000000000 Binary files a/src/Umbraco.Web.UI/umbraco/images/editor/inindent.GIF and /dev/null differ diff --git a/src/Umbraco.Web.UI/umbraco/images/editor/insBreadcrum.gif b/src/Umbraco.Web.UI/umbraco/images/editor/insBreadcrum.gif deleted file mode 100644 index 6ec277bc7d..0000000000 Binary files a/src/Umbraco.Web.UI/umbraco/images/editor/insBreadcrum.gif and /dev/null differ diff --git a/src/Umbraco.Web.UI/umbraco/images/editor/insChildTemplate.gif b/src/Umbraco.Web.UI/umbraco/images/editor/insChildTemplate.gif deleted file mode 100644 index 1463e9de5e..0000000000 Binary files a/src/Umbraco.Web.UI/umbraco/images/editor/insChildTemplate.gif and /dev/null differ diff --git a/src/Umbraco.Web.UI/umbraco/images/editor/inscell.GIF b/src/Umbraco.Web.UI/umbraco/images/editor/inscell.GIF deleted file mode 100644 index a2d1285456..0000000000 Binary files a/src/Umbraco.Web.UI/umbraco/images/editor/inscell.GIF and /dev/null differ diff --git a/src/Umbraco.Web.UI/umbraco/images/editor/inscol.GIF b/src/Umbraco.Web.UI/umbraco/images/editor/inscol.GIF deleted file mode 100644 index e3d132dae1..0000000000 Binary files a/src/Umbraco.Web.UI/umbraco/images/editor/inscol.GIF and /dev/null differ diff --git a/src/Umbraco.Web.UI/umbraco/images/editor/insert_button_bg.gif b/src/Umbraco.Web.UI/umbraco/images/editor/insert_button_bg.gif deleted file mode 100644 index 69c131ce29..0000000000 Binary files a/src/Umbraco.Web.UI/umbraco/images/editor/insert_button_bg.gif and /dev/null differ diff --git a/src/Umbraco.Web.UI/umbraco/images/editor/insform.gif b/src/Umbraco.Web.UI/umbraco/images/editor/insform.gif deleted file mode 100644 index 361804565d..0000000000 Binary files a/src/Umbraco.Web.UI/umbraco/images/editor/insform.gif and /dev/null differ diff --git a/src/Umbraco.Web.UI/umbraco/images/editor/insrow.GIF b/src/Umbraco.Web.UI/umbraco/images/editor/insrow.GIF deleted file mode 100644 index 2e6a774377..0000000000 Binary files a/src/Umbraco.Web.UI/umbraco/images/editor/insrow.GIF and /dev/null differ diff --git a/src/Umbraco.Web.UI/umbraco/images/editor/instable.GIF b/src/Umbraco.Web.UI/umbraco/images/editor/instable.GIF deleted file mode 100644 index 24ec60df7e..0000000000 Binary files a/src/Umbraco.Web.UI/umbraco/images/editor/instable.GIF and /dev/null differ diff --git a/src/Umbraco.Web.UI/umbraco/images/editor/italic_de_se.gif b/src/Umbraco.Web.UI/umbraco/images/editor/italic_de_se.gif deleted file mode 100644 index feb0309e74..0000000000 Binary files a/src/Umbraco.Web.UI/umbraco/images/editor/italic_de_se.gif and /dev/null differ diff --git a/src/Umbraco.Web.UI/umbraco/images/editor/italic_es.gif b/src/Umbraco.Web.UI/umbraco/images/editor/italic_es.gif deleted file mode 100644 index 4572cdb1d0..0000000000 Binary files a/src/Umbraco.Web.UI/umbraco/images/editor/italic_es.gif and /dev/null differ diff --git a/src/Umbraco.Web.UI/umbraco/images/editor/italic_ru.gif b/src/Umbraco.Web.UI/umbraco/images/editor/italic_ru.gif deleted file mode 100644 index a2bb69a725..0000000000 Binary files a/src/Umbraco.Web.UI/umbraco/images/editor/italic_ru.gif and /dev/null differ diff --git a/src/Umbraco.Web.UI/umbraco/images/editor/italic_tw.gif b/src/Umbraco.Web.UI/umbraco/images/editor/italic_tw.gif deleted file mode 100644 index 4f6eeaa2b2..0000000000 Binary files a/src/Umbraco.Web.UI/umbraco/images/editor/italic_tw.gif and /dev/null differ diff --git a/src/Umbraco.Web.UI/umbraco/images/editor/justifycenter.gif b/src/Umbraco.Web.UI/umbraco/images/editor/justifycenter.gif deleted file mode 100644 index 42d609a991..0000000000 Binary files a/src/Umbraco.Web.UI/umbraco/images/editor/justifycenter.gif and /dev/null differ diff --git a/src/Umbraco.Web.UI/umbraco/images/editor/justifyfull.gif b/src/Umbraco.Web.UI/umbraco/images/editor/justifyfull.gif deleted file mode 100644 index c8504f626f..0000000000 Binary files a/src/Umbraco.Web.UI/umbraco/images/editor/justifyfull.gif and /dev/null differ diff --git a/src/Umbraco.Web.UI/umbraco/images/editor/justifyleft.gif b/src/Umbraco.Web.UI/umbraco/images/editor/justifyleft.gif deleted file mode 100644 index e8f7e42769..0000000000 Binary files a/src/Umbraco.Web.UI/umbraco/images/editor/justifyleft.gif and /dev/null differ diff --git a/src/Umbraco.Web.UI/umbraco/images/editor/justifyright.gif b/src/Umbraco.Web.UI/umbraco/images/editor/justifyright.gif deleted file mode 100644 index e4cea97148..0000000000 Binary files a/src/Umbraco.Web.UI/umbraco/images/editor/justifyright.gif and /dev/null differ diff --git a/src/Umbraco.Web.UI/umbraco/images/editor/left.GIF b/src/Umbraco.Web.UI/umbraco/images/editor/left.GIF deleted file mode 100644 index d1af83383d..0000000000 Binary files a/src/Umbraco.Web.UI/umbraco/images/editor/left.GIF and /dev/null differ diff --git a/src/Umbraco.Web.UI/umbraco/images/editor/media.gif b/src/Umbraco.Web.UI/umbraco/images/editor/media.gif deleted file mode 100644 index 76216085d3..0000000000 Binary files a/src/Umbraco.Web.UI/umbraco/images/editor/media.gif and /dev/null differ diff --git a/src/Umbraco.Web.UI/umbraco/images/editor/menu_check.gif b/src/Umbraco.Web.UI/umbraco/images/editor/menu_check.gif deleted file mode 100644 index 50d6afd505..0000000000 Binary files a/src/Umbraco.Web.UI/umbraco/images/editor/menu_check.gif and /dev/null differ diff --git a/src/Umbraco.Web.UI/umbraco/images/editor/mrgcell.GIF b/src/Umbraco.Web.UI/umbraco/images/editor/mrgcell.GIF deleted file mode 100644 index 7f14362fd1..0000000000 Binary files a/src/Umbraco.Web.UI/umbraco/images/editor/mrgcell.GIF and /dev/null differ diff --git a/src/Umbraco.Web.UI/umbraco/images/editor/newdoc.GIF b/src/Umbraco.Web.UI/umbraco/images/editor/newdoc.GIF deleted file mode 100644 index 24e85821ff..0000000000 Binary files a/src/Umbraco.Web.UI/umbraco/images/editor/newdoc.GIF and /dev/null differ diff --git a/src/Umbraco.Web.UI/umbraco/images/editor/newdocument.gif b/src/Umbraco.Web.UI/umbraco/images/editor/newdocument.gif deleted file mode 100644 index a9d2938423..0000000000 Binary files a/src/Umbraco.Web.UI/umbraco/images/editor/newdocument.gif and /dev/null differ diff --git a/src/Umbraco.Web.UI/umbraco/images/editor/numlist.GIF b/src/Umbraco.Web.UI/umbraco/images/editor/numlist.GIF deleted file mode 100644 index a2683522f4..0000000000 Binary files a/src/Umbraco.Web.UI/umbraco/images/editor/numlist.GIF and /dev/null differ diff --git a/src/Umbraco.Web.UI/umbraco/images/editor/opacity.png b/src/Umbraco.Web.UI/umbraco/images/editor/opacity.png deleted file mode 100644 index b4217cb212..0000000000 Binary files a/src/Umbraco.Web.UI/umbraco/images/editor/opacity.png and /dev/null differ diff --git a/src/Umbraco.Web.UI/umbraco/images/editor/outdent.gif b/src/Umbraco.Web.UI/umbraco/images/editor/outdent.gif deleted file mode 100644 index 23f6aa4086..0000000000 Binary files a/src/Umbraco.Web.UI/umbraco/images/editor/outdent.gif and /dev/null differ diff --git a/src/Umbraco.Web.UI/umbraco/images/editor/project.GIF b/src/Umbraco.Web.UI/umbraco/images/editor/project.GIF deleted file mode 100644 index 98eff56ee1..0000000000 Binary files a/src/Umbraco.Web.UI/umbraco/images/editor/project.GIF and /dev/null differ diff --git a/src/Umbraco.Web.UI/umbraco/images/editor/properties.gif b/src/Umbraco.Web.UI/umbraco/images/editor/properties.gif deleted file mode 100644 index d9f67a89c6..0000000000 Binary files a/src/Umbraco.Web.UI/umbraco/images/editor/properties.gif and /dev/null differ diff --git a/src/Umbraco.Web.UI/umbraco/images/editor/propertiesNew.gif b/src/Umbraco.Web.UI/umbraco/images/editor/propertiesNew.gif deleted file mode 100644 index 65d137019d..0000000000 Binary files a/src/Umbraco.Web.UI/umbraco/images/editor/propertiesNew.gif and /dev/null differ diff --git a/src/Umbraco.Web.UI/umbraco/images/editor/props.GIF b/src/Umbraco.Web.UI/umbraco/images/editor/props.GIF deleted file mode 100644 index 24450f02cb..0000000000 Binary files a/src/Umbraco.Web.UI/umbraco/images/editor/props.GIF and /dev/null differ diff --git a/src/Umbraco.Web.UI/umbraco/images/editor/rel.gif b/src/Umbraco.Web.UI/umbraco/images/editor/rel.gif deleted file mode 100644 index 79e22138f8..0000000000 Binary files a/src/Umbraco.Web.UI/umbraco/images/editor/rel.gif and /dev/null differ diff --git a/src/Umbraco.Web.UI/umbraco/images/editor/removeformat.gif b/src/Umbraco.Web.UI/umbraco/images/editor/removeformat.gif deleted file mode 100644 index 0fa3cb7973..0000000000 Binary files a/src/Umbraco.Web.UI/umbraco/images/editor/removeformat.gif and /dev/null differ diff --git a/src/Umbraco.Web.UI/umbraco/images/editor/right.GIF b/src/Umbraco.Web.UI/umbraco/images/editor/right.GIF deleted file mode 100644 index d661bdde22..0000000000 Binary files a/src/Umbraco.Web.UI/umbraco/images/editor/right.GIF and /dev/null differ diff --git a/src/Umbraco.Web.UI/umbraco/images/editor/saveToPublish.png b/src/Umbraco.Web.UI/umbraco/images/editor/saveToPublish.png deleted file mode 100644 index edf8e05d97..0000000000 Binary files a/src/Umbraco.Web.UI/umbraco/images/editor/saveToPublish.png and /dev/null differ diff --git a/src/Umbraco.Web.UI/umbraco/images/editor/separator.gif b/src/Umbraco.Web.UI/umbraco/images/editor/separator.gif deleted file mode 100644 index 4f39b809e9..0000000000 Binary files a/src/Umbraco.Web.UI/umbraco/images/editor/separator.gif and /dev/null differ diff --git a/src/Umbraco.Web.UI/umbraco/images/editor/showStyles.gif b/src/Umbraco.Web.UI/umbraco/images/editor/showStyles.gif deleted file mode 100644 index d71976f8a0..0000000000 Binary files a/src/Umbraco.Web.UI/umbraco/images/editor/showStyles.gif and /dev/null differ diff --git a/src/Umbraco.Web.UI/umbraco/images/editor/showStyles.png b/src/Umbraco.Web.UI/umbraco/images/editor/showStyles.png deleted file mode 100644 index 6dfbe2c0b2..0000000000 Binary files a/src/Umbraco.Web.UI/umbraco/images/editor/showStyles.png and /dev/null differ diff --git a/src/Umbraco.Web.UI/umbraco/images/editor/skin.gif b/src/Umbraco.Web.UI/umbraco/images/editor/skin.gif deleted file mode 100644 index dde295b0fb..0000000000 Binary files a/src/Umbraco.Web.UI/umbraco/images/editor/skin.gif and /dev/null differ diff --git a/src/Umbraco.Web.UI/umbraco/images/editor/spacer.gif b/src/Umbraco.Web.UI/umbraco/images/editor/spacer.gif deleted file mode 100644 index 388486517f..0000000000 Binary files a/src/Umbraco.Web.UI/umbraco/images/editor/spacer.gif and /dev/null differ diff --git a/src/Umbraco.Web.UI/umbraco/images/editor/spellchecker.gif b/src/Umbraco.Web.UI/umbraco/images/editor/spellchecker.gif deleted file mode 100644 index 294a9d2ef5..0000000000 Binary files a/src/Umbraco.Web.UI/umbraco/images/editor/spellchecker.gif and /dev/null differ diff --git a/src/Umbraco.Web.UI/umbraco/images/editor/split.gif b/src/Umbraco.Web.UI/umbraco/images/editor/split.gif deleted file mode 100644 index 1c92ef7a9f..0000000000 Binary files a/src/Umbraco.Web.UI/umbraco/images/editor/split.gif and /dev/null differ diff --git a/src/Umbraco.Web.UI/umbraco/images/editor/spltcell.GIF b/src/Umbraco.Web.UI/umbraco/images/editor/spltcell.GIF deleted file mode 100644 index 4f63fe6279..0000000000 Binary files a/src/Umbraco.Web.UI/umbraco/images/editor/spltcell.GIF and /dev/null differ diff --git a/src/Umbraco.Web.UI/umbraco/images/editor/statusbar_resize.gif b/src/Umbraco.Web.UI/umbraco/images/editor/statusbar_resize.gif deleted file mode 100644 index af89d803f8..0000000000 Binary files a/src/Umbraco.Web.UI/umbraco/images/editor/statusbar_resize.gif and /dev/null differ diff --git a/src/Umbraco.Web.UI/umbraco/images/editor/strikethrough.gif b/src/Umbraco.Web.UI/umbraco/images/editor/strikethrough.gif deleted file mode 100644 index 3264635918..0000000000 Binary files a/src/Umbraco.Web.UI/umbraco/images/editor/strikethrough.gif and /dev/null differ diff --git a/src/Umbraco.Web.UI/umbraco/images/editor/styleMarkEnd.gif b/src/Umbraco.Web.UI/umbraco/images/editor/styleMarkEnd.gif deleted file mode 100644 index 800807116f..0000000000 Binary files a/src/Umbraco.Web.UI/umbraco/images/editor/styleMarkEnd.gif and /dev/null differ diff --git a/src/Umbraco.Web.UI/umbraco/images/editor/styleMarkStart.gif b/src/Umbraco.Web.UI/umbraco/images/editor/styleMarkStart.gif deleted file mode 100644 index 4de5d4aa50..0000000000 Binary files a/src/Umbraco.Web.UI/umbraco/images/editor/styleMarkStart.gif and /dev/null differ diff --git a/src/Umbraco.Web.UI/umbraco/images/editor/sub.gif b/src/Umbraco.Web.UI/umbraco/images/editor/sub.gif deleted file mode 100644 index 4d7ce30ff9..0000000000 Binary files a/src/Umbraco.Web.UI/umbraco/images/editor/sub.gif and /dev/null differ diff --git a/src/Umbraco.Web.UI/umbraco/images/editor/sup.gif b/src/Umbraco.Web.UI/umbraco/images/editor/sup.gif deleted file mode 100644 index a7145e019a..0000000000 Binary files a/src/Umbraco.Web.UI/umbraco/images/editor/sup.gif and /dev/null differ diff --git a/src/Umbraco.Web.UI/umbraco/images/editor/table.gif b/src/Umbraco.Web.UI/umbraco/images/editor/table.gif deleted file mode 100644 index 2911830c3c..0000000000 Binary files a/src/Umbraco.Web.UI/umbraco/images/editor/table.gif and /dev/null differ diff --git a/src/Umbraco.Web.UI/umbraco/images/editor/umbracoField.gif b/src/Umbraco.Web.UI/umbraco/images/editor/umbracoField.gif deleted file mode 100644 index 549f726921..0000000000 Binary files a/src/Umbraco.Web.UI/umbraco/images/editor/umbracoField.gif and /dev/null differ diff --git a/src/Umbraco.Web.UI/umbraco/images/editor/umbracoScriptlet.gif b/src/Umbraco.Web.UI/umbraco/images/editor/umbracoScriptlet.gif deleted file mode 100644 index a6b3cde117..0000000000 Binary files a/src/Umbraco.Web.UI/umbraco/images/editor/umbracoScriptlet.gif and /dev/null differ diff --git a/src/Umbraco.Web.UI/umbraco/images/editor/umbracoTextGen.gif b/src/Umbraco.Web.UI/umbraco/images/editor/umbracoTextGen.gif deleted file mode 100644 index c2b12c8d5f..0000000000 Binary files a/src/Umbraco.Web.UI/umbraco/images/editor/umbracoTextGen.gif and /dev/null differ diff --git a/src/Umbraco.Web.UI/umbraco/images/editor/under.GIF b/src/Umbraco.Web.UI/umbraco/images/editor/under.GIF deleted file mode 100644 index a1301dd9ba..0000000000 Binary files a/src/Umbraco.Web.UI/umbraco/images/editor/under.GIF and /dev/null differ diff --git a/src/Umbraco.Web.UI/umbraco/images/editor/underline.gif b/src/Umbraco.Web.UI/umbraco/images/editor/underline.gif deleted file mode 100644 index 1dfeb5f6d0..0000000000 Binary files a/src/Umbraco.Web.UI/umbraco/images/editor/underline.gif and /dev/null differ diff --git a/src/Umbraco.Web.UI/umbraco/images/editor/underline_es.gif b/src/Umbraco.Web.UI/umbraco/images/editor/underline_es.gif deleted file mode 100644 index 551d9148d3..0000000000 Binary files a/src/Umbraco.Web.UI/umbraco/images/editor/underline_es.gif and /dev/null differ diff --git a/src/Umbraco.Web.UI/umbraco/images/editor/underline_fr.gif b/src/Umbraco.Web.UI/umbraco/images/editor/underline_fr.gif deleted file mode 100644 index 551d9148d3..0000000000 Binary files a/src/Umbraco.Web.UI/umbraco/images/editor/underline_fr.gif and /dev/null differ diff --git a/src/Umbraco.Web.UI/umbraco/images/editor/underline_ru.gif b/src/Umbraco.Web.UI/umbraco/images/editor/underline_ru.gif deleted file mode 100644 index b78e2a498f..0000000000 Binary files a/src/Umbraco.Web.UI/umbraco/images/editor/underline_ru.gif and /dev/null differ diff --git a/src/Umbraco.Web.UI/umbraco/images/editor/underline_tw.gif b/src/Umbraco.Web.UI/umbraco/images/editor/underline_tw.gif deleted file mode 100644 index b715390484..0000000000 Binary files a/src/Umbraco.Web.UI/umbraco/images/editor/underline_tw.gif and /dev/null differ diff --git a/src/Umbraco.Web.UI/umbraco/images/editor/unlink.gif b/src/Umbraco.Web.UI/umbraco/images/editor/unlink.gif deleted file mode 100644 index 5c8a33db8d..0000000000 Binary files a/src/Umbraco.Web.UI/umbraco/images/editor/unlink.gif and /dev/null differ diff --git a/src/Umbraco.Web.UI/umbraco/images/editor/upload.png b/src/Umbraco.Web.UI/umbraco/images/editor/upload.png deleted file mode 100644 index 95b67ac1da..0000000000 Binary files a/src/Umbraco.Web.UI/umbraco/images/editor/upload.png and /dev/null differ diff --git a/src/Umbraco.Web.UI/umbraco/images/editor/vis.gif b/src/Umbraco.Web.UI/umbraco/images/editor/vis.gif deleted file mode 100644 index 67baa7914f..0000000000 Binary files a/src/Umbraco.Web.UI/umbraco/images/editor/vis.gif and /dev/null differ diff --git a/src/Umbraco.Web.UI/umbraco/images/editor/visualaid.gif b/src/Umbraco.Web.UI/umbraco/images/editor/visualaid.gif deleted file mode 100644 index 63caf18071..0000000000 Binary files a/src/Umbraco.Web.UI/umbraco/images/editor/visualaid.gif and /dev/null differ diff --git a/src/Umbraco.Web.UI/umbraco/images/editor/zoom.gif b/src/Umbraco.Web.UI/umbraco/images/editor/zoom.gif deleted file mode 100644 index 88892fdb28..0000000000 Binary files a/src/Umbraco.Web.UI/umbraco/images/editor/zoom.gif and /dev/null differ diff --git a/src/Umbraco.Web.UI/umbraco/images/errorLayerBackground.gif b/src/Umbraco.Web.UI/umbraco/images/errorLayerBackground.gif deleted file mode 100644 index 5ff1abba8b..0000000000 Binary files a/src/Umbraco.Web.UI/umbraco/images/errorLayerBackground.gif and /dev/null differ diff --git a/src/Umbraco.Web.UI/umbraco/images/expand.png b/src/Umbraco.Web.UI/umbraco/images/expand.png deleted file mode 100644 index a072867321..0000000000 Binary files a/src/Umbraco.Web.UI/umbraco/images/expand.png and /dev/null differ diff --git a/src/Umbraco.Web.UI/umbraco/images/exportDocumenttype.png b/src/Umbraco.Web.UI/umbraco/images/exportDocumenttype.png deleted file mode 100644 index 03ad80b439..0000000000 Binary files a/src/Umbraco.Web.UI/umbraco/images/exportDocumenttype.png and /dev/null differ diff --git a/src/Umbraco.Web.UI/umbraco/images/false.png b/src/Umbraco.Web.UI/umbraco/images/false.png deleted file mode 100644 index 561460d601..0000000000 Binary files a/src/Umbraco.Web.UI/umbraco/images/false.png and /dev/null differ diff --git a/src/Umbraco.Web.UI/umbraco/images/file.png b/src/Umbraco.Web.UI/umbraco/images/file.png deleted file mode 100644 index a20c6fa0c8..0000000000 Binary files a/src/Umbraco.Web.UI/umbraco/images/file.png and /dev/null differ diff --git a/src/Umbraco.Web.UI/umbraco/images/find.small.png b/src/Umbraco.Web.UI/umbraco/images/find.small.png deleted file mode 100644 index c3f3f42e25..0000000000 Binary files a/src/Umbraco.Web.UI/umbraco/images/find.small.png and /dev/null differ diff --git a/src/Umbraco.Web.UI/umbraco/images/findDocument.gif b/src/Umbraco.Web.UI/umbraco/images/findDocument.gif deleted file mode 100644 index bbcc91e5d0..0000000000 Binary files a/src/Umbraco.Web.UI/umbraco/images/findDocument.gif and /dev/null differ diff --git a/src/Umbraco.Web.UI/umbraco/images/findDocument.png b/src/Umbraco.Web.UI/umbraco/images/findDocument.png deleted file mode 100644 index 73e9be3e1f..0000000000 Binary files a/src/Umbraco.Web.UI/umbraco/images/findDocument.png and /dev/null differ diff --git a/src/Umbraco.Web.UI/umbraco/images/folder.small.png b/src/Umbraco.Web.UI/umbraco/images/folder.small.png deleted file mode 100644 index 7b6835d041..0000000000 Binary files a/src/Umbraco.Web.UI/umbraco/images/folder.small.png and /dev/null differ diff --git a/src/Umbraco.Web.UI/umbraco/images/foldericon.png b/src/Umbraco.Web.UI/umbraco/images/foldericon.png deleted file mode 100644 index 2684748b0a..0000000000 Binary files a/src/Umbraco.Web.UI/umbraco/images/foldericon.png and /dev/null differ diff --git a/src/Umbraco.Web.UI/umbraco/images/forward.png b/src/Umbraco.Web.UI/umbraco/images/forward.png deleted file mode 100644 index 4876480518..0000000000 Binary files a/src/Umbraco.Web.UI/umbraco/images/forward.png and /dev/null differ diff --git a/src/Umbraco.Web.UI/umbraco/images/gradientBackground.png b/src/Umbraco.Web.UI/umbraco/images/gradientBackground.png deleted file mode 100644 index 312ed304e4..0000000000 Binary files a/src/Umbraco.Web.UI/umbraco/images/gradientBackground.png and /dev/null differ diff --git a/src/Umbraco.Web.UI/umbraco/images/gradientLine.gif b/src/Umbraco.Web.UI/umbraco/images/gradientLine.gif deleted file mode 100644 index 2b359cca13..0000000000 Binary files a/src/Umbraco.Web.UI/umbraco/images/gradientLine.gif and /dev/null differ diff --git a/src/Umbraco.Web.UI/umbraco/images/help.gif b/src/Umbraco.Web.UI/umbraco/images/help.gif deleted file mode 100644 index de8c2f2492..0000000000 Binary files a/src/Umbraco.Web.UI/umbraco/images/help.gif and /dev/null differ diff --git a/src/Umbraco.Web.UI/umbraco/images/help.png b/src/Umbraco.Web.UI/umbraco/images/help.png deleted file mode 100644 index eaa43eb050..0000000000 Binary files a/src/Umbraco.Web.UI/umbraco/images/help.png and /dev/null differ diff --git a/src/Umbraco.Web.UI/umbraco/images/htmldoc.small.png b/src/Umbraco.Web.UI/umbraco/images/htmldoc.small.png deleted file mode 100644 index 61074a4d94..0000000000 Binary files a/src/Umbraco.Web.UI/umbraco/images/htmldoc.small.png and /dev/null differ diff --git a/src/Umbraco.Web.UI/umbraco/images/importDocumenttype.png b/src/Umbraco.Web.UI/umbraco/images/importDocumenttype.png deleted file mode 100644 index bd898de94b..0000000000 Binary files a/src/Umbraco.Web.UI/umbraco/images/importDocumenttype.png and /dev/null differ diff --git a/src/Umbraco.Web.UI/umbraco/images/information.png b/src/Umbraco.Web.UI/umbraco/images/information.png deleted file mode 100644 index 121c7336dc..0000000000 Binary files a/src/Umbraco.Web.UI/umbraco/images/information.png and /dev/null differ diff --git a/src/Umbraco.Web.UI/umbraco/images/listItemOrange.gif b/src/Umbraco.Web.UI/umbraco/images/listItemOrange.gif deleted file mode 100644 index ab6bef08c6..0000000000 Binary files a/src/Umbraco.Web.UI/umbraco/images/listItemOrange.gif and /dev/null differ diff --git a/src/Umbraco.Web.UI/umbraco/images/loginBg.png b/src/Umbraco.Web.UI/umbraco/images/loginBg.png deleted file mode 100644 index 18d3f1387f..0000000000 Binary files a/src/Umbraco.Web.UI/umbraco/images/loginBg.png and /dev/null differ diff --git a/src/Umbraco.Web.UI/umbraco/images/logout.png b/src/Umbraco.Web.UI/umbraco/images/logout.png deleted file mode 100644 index 97d15fa6b6..0000000000 Binary files a/src/Umbraco.Web.UI/umbraco/images/logout.png and /dev/null differ diff --git a/src/Umbraco.Web.UI/umbraco/images/logout_small.gif b/src/Umbraco.Web.UI/umbraco/images/logout_small.gif deleted file mode 100644 index 67182329f2..0000000000 Binary files a/src/Umbraco.Web.UI/umbraco/images/logout_small.gif and /dev/null differ diff --git a/src/Umbraco.Web.UI/umbraco/images/logout_small.png b/src/Umbraco.Web.UI/umbraco/images/logout_small.png deleted file mode 100644 index 98b8a32a24..0000000000 Binary files a/src/Umbraco.Web.UI/umbraco/images/logout_small.png and /dev/null differ diff --git a/src/Umbraco.Web.UI/umbraco/images/macro.gif b/src/Umbraco.Web.UI/umbraco/images/macro.gif deleted file mode 100644 index 2ad8a722fb..0000000000 Binary files a/src/Umbraco.Web.UI/umbraco/images/macro.gif and /dev/null differ diff --git a/src/Umbraco.Web.UI/umbraco/images/mediaThumbnails/pdf.png b/src/Umbraco.Web.UI/umbraco/images/mediaThumbnails/pdf.png deleted file mode 100644 index 3ed7608e32..0000000000 Binary files a/src/Umbraco.Web.UI/umbraco/images/mediaThumbnails/pdf.png and /dev/null differ diff --git a/src/Umbraco.Web.UI/umbraco/images/nada.gif b/src/Umbraco.Web.UI/umbraco/images/nada.gif deleted file mode 100644 index a5a99828b8..0000000000 Binary files a/src/Umbraco.Web.UI/umbraco/images/nada.gif and /dev/null differ diff --git a/src/Umbraco.Web.UI/umbraco/images/new.gif b/src/Umbraco.Web.UI/umbraco/images/new.gif deleted file mode 100644 index ef0178cfa4..0000000000 Binary files a/src/Umbraco.Web.UI/umbraco/images/new.gif and /dev/null differ diff --git a/src/Umbraco.Web.UI/umbraco/images/new.png b/src/Umbraco.Web.UI/umbraco/images/new.png deleted file mode 100644 index 0ee2a7d79e..0000000000 Binary files a/src/Umbraco.Web.UI/umbraco/images/new.png and /dev/null differ diff --git a/src/Umbraco.Web.UI/umbraco/images/newStar.gif b/src/Umbraco.Web.UI/umbraco/images/newStar.gif deleted file mode 100644 index be41a07299..0000000000 Binary files a/src/Umbraco.Web.UI/umbraco/images/newStar.gif and /dev/null differ diff --git a/src/Umbraco.Web.UI/umbraco/images/notepad.png b/src/Umbraco.Web.UI/umbraco/images/notepad.png deleted file mode 100644 index f8b8ccacc6..0000000000 Binary files a/src/Umbraco.Web.UI/umbraco/images/notepad.png and /dev/null differ diff --git a/src/Umbraco.Web.UI/umbraco/images/notify.gif b/src/Umbraco.Web.UI/umbraco/images/notify.gif deleted file mode 100644 index 55671b5b47..0000000000 Binary files a/src/Umbraco.Web.UI/umbraco/images/notify.gif and /dev/null differ diff --git a/src/Umbraco.Web.UI/umbraco/images/notifyOld.gif b/src/Umbraco.Web.UI/umbraco/images/notifyOld.gif deleted file mode 100644 index 55671b5b47..0000000000 Binary files a/src/Umbraco.Web.UI/umbraco/images/notifyOld.gif and /dev/null differ diff --git a/src/Umbraco.Web.UI/umbraco/images/okLayerBackground.gif b/src/Umbraco.Web.UI/umbraco/images/okLayerBackground.gif deleted file mode 100644 index e6800fa08b..0000000000 Binary files a/src/Umbraco.Web.UI/umbraco/images/okLayerBackground.gif and /dev/null differ diff --git a/src/Umbraco.Web.UI/umbraco/images/openfoldericon.png b/src/Umbraco.Web.UI/umbraco/images/openfoldericon.png deleted file mode 100644 index 15fcd56711..0000000000 Binary files a/src/Umbraco.Web.UI/umbraco/images/openfoldericon.png and /dev/null differ diff --git a/src/Umbraco.Web.UI/umbraco/images/options.small.png b/src/Umbraco.Web.UI/umbraco/images/options.small.png deleted file mode 100644 index 01665deda7..0000000000 Binary files a/src/Umbraco.Web.UI/umbraco/images/options.small.png and /dev/null differ diff --git a/src/Umbraco.Web.UI/umbraco/images/package.png b/src/Umbraco.Web.UI/umbraco/images/package.png deleted file mode 100644 index f3296d552b..0000000000 Binary files a/src/Umbraco.Web.UI/umbraco/images/package.png and /dev/null differ diff --git a/src/Umbraco.Web.UI/umbraco/images/package2.png b/src/Umbraco.Web.UI/umbraco/images/package2.png deleted file mode 100644 index 3ee17b4e3b..0000000000 Binary files a/src/Umbraco.Web.UI/umbraco/images/package2.png and /dev/null differ diff --git a/src/Umbraco.Web.UI/umbraco/images/paste.small.png b/src/Umbraco.Web.UI/umbraco/images/paste.small.png deleted file mode 100644 index 3169d26d0f..0000000000 Binary files a/src/Umbraco.Web.UI/umbraco/images/paste.small.png and /dev/null differ diff --git a/src/Umbraco.Web.UI/umbraco/images/pencil.png b/src/Umbraco.Web.UI/umbraco/images/pencil.png deleted file mode 100644 index 0bfecd50ee..0000000000 Binary files a/src/Umbraco.Web.UI/umbraco/images/pencil.png and /dev/null differ diff --git a/src/Umbraco.Web.UI/umbraco/images/permission.gif b/src/Umbraco.Web.UI/umbraco/images/permission.gif deleted file mode 100644 index 26e0aae4d1..0000000000 Binary files a/src/Umbraco.Web.UI/umbraco/images/permission.gif and /dev/null differ diff --git a/src/Umbraco.Web.UI/umbraco/images/permission.png b/src/Umbraco.Web.UI/umbraco/images/permission.png deleted file mode 100644 index e8b99447e6..0000000000 Binary files a/src/Umbraco.Web.UI/umbraco/images/permission.png and /dev/null differ diff --git a/src/Umbraco.Web.UI/umbraco/images/protect.gif b/src/Umbraco.Web.UI/umbraco/images/protect.gif deleted file mode 100644 index 51323c0869..0000000000 Binary files a/src/Umbraco.Web.UI/umbraco/images/protect.gif and /dev/null differ diff --git a/src/Umbraco.Web.UI/umbraco/images/protect.png b/src/Umbraco.Web.UI/umbraco/images/protect.png deleted file mode 100644 index a71c88b709..0000000000 Binary files a/src/Umbraco.Web.UI/umbraco/images/protect.png and /dev/null differ diff --git a/src/Umbraco.Web.UI/umbraco/images/publish.gif b/src/Umbraco.Web.UI/umbraco/images/publish.gif deleted file mode 100644 index aafd42b889..0000000000 Binary files a/src/Umbraco.Web.UI/umbraco/images/publish.gif and /dev/null differ diff --git a/src/Umbraco.Web.UI/umbraco/images/publish.png b/src/Umbraco.Web.UI/umbraco/images/publish.png deleted file mode 100644 index 3de0e52d0d..0000000000 Binary files a/src/Umbraco.Web.UI/umbraco/images/publish.png and /dev/null differ diff --git a/src/Umbraco.Web.UI/umbraco/images/refresh.png b/src/Umbraco.Web.UI/umbraco/images/refresh.png deleted file mode 100644 index 0807294e9b..0000000000 Binary files a/src/Umbraco.Web.UI/umbraco/images/refresh.png and /dev/null differ diff --git a/src/Umbraco.Web.UI/umbraco/images/rollback.gif b/src/Umbraco.Web.UI/umbraco/images/rollback.gif deleted file mode 100644 index e0bd818ca8..0000000000 Binary files a/src/Umbraco.Web.UI/umbraco/images/rollback.gif and /dev/null differ diff --git a/src/Umbraco.Web.UI/umbraco/images/rollback.png b/src/Umbraco.Web.UI/umbraco/images/rollback.png deleted file mode 100644 index 0f76f58a60..0000000000 Binary files a/src/Umbraco.Web.UI/umbraco/images/rollback.png and /dev/null differ diff --git a/src/Umbraco.Web.UI/umbraco/images/save.png b/src/Umbraco.Web.UI/umbraco/images/save.png deleted file mode 100644 index 169699cc8f..0000000000 Binary files a/src/Umbraco.Web.UI/umbraco/images/save.png and /dev/null differ diff --git a/src/Umbraco.Web.UI/umbraco/images/sendToTranslate.png b/src/Umbraco.Web.UI/umbraco/images/sendToTranslate.png deleted file mode 100644 index 77a0daf79c..0000000000 Binary files a/src/Umbraco.Web.UI/umbraco/images/sendToTranslate.png and /dev/null differ diff --git a/src/Umbraco.Web.UI/umbraco/images/small_minus.png b/src/Umbraco.Web.UI/umbraco/images/small_minus.png deleted file mode 100644 index d323089983..0000000000 Binary files a/src/Umbraco.Web.UI/umbraco/images/small_minus.png and /dev/null differ diff --git a/src/Umbraco.Web.UI/umbraco/images/small_plus.png b/src/Umbraco.Web.UI/umbraco/images/small_plus.png deleted file mode 100644 index 523cacee98..0000000000 Binary files a/src/Umbraco.Web.UI/umbraco/images/small_plus.png and /dev/null differ diff --git a/src/Umbraco.Web.UI/umbraco/images/sort.gif b/src/Umbraco.Web.UI/umbraco/images/sort.gif deleted file mode 100644 index 26285563e8..0000000000 Binary files a/src/Umbraco.Web.UI/umbraco/images/sort.gif and /dev/null differ diff --git a/src/Umbraco.Web.UI/umbraco/images/sort.png b/src/Umbraco.Web.UI/umbraco/images/sort.png deleted file mode 100644 index 8845651fb3..0000000000 Binary files a/src/Umbraco.Web.UI/umbraco/images/sort.png and /dev/null differ diff --git a/src/Umbraco.Web.UI/umbraco/images/sort.small.png b/src/Umbraco.Web.UI/umbraco/images/sort.small.png deleted file mode 100644 index 8845651fb3..0000000000 Binary files a/src/Umbraco.Web.UI/umbraco/images/sort.small.png and /dev/null differ diff --git a/src/Umbraco.Web.UI/umbraco/images/speechBubble/error.gif b/src/Umbraco.Web.UI/umbraco/images/speechBubble/error.gif deleted file mode 100644 index 314b1718c2..0000000000 Binary files a/src/Umbraco.Web.UI/umbraco/images/speechBubble/error.gif and /dev/null differ diff --git a/src/Umbraco.Web.UI/umbraco/images/speechBubble/error.png b/src/Umbraco.Web.UI/umbraco/images/speechBubble/error.png deleted file mode 100644 index 03e25b8358..0000000000 Binary files a/src/Umbraco.Web.UI/umbraco/images/speechBubble/error.png and /dev/null differ diff --git a/src/Umbraco.Web.UI/umbraco/images/speechBubble/info.gif b/src/Umbraco.Web.UI/umbraco/images/speechBubble/info.gif deleted file mode 100644 index 6dd76db6b2..0000000000 Binary files a/src/Umbraco.Web.UI/umbraco/images/speechBubble/info.gif and /dev/null differ diff --git a/src/Umbraco.Web.UI/umbraco/images/speechBubble/info.png b/src/Umbraco.Web.UI/umbraco/images/speechBubble/info.png deleted file mode 100644 index e5734da6ed..0000000000 Binary files a/src/Umbraco.Web.UI/umbraco/images/speechBubble/info.png and /dev/null differ diff --git a/src/Umbraco.Web.UI/umbraco/images/speechBubble/save.gif b/src/Umbraco.Web.UI/umbraco/images/speechBubble/save.gif deleted file mode 100644 index 89d75c110e..0000000000 Binary files a/src/Umbraco.Web.UI/umbraco/images/speechBubble/save.gif and /dev/null differ diff --git a/src/Umbraco.Web.UI/umbraco/images/speechBubble/save.png b/src/Umbraco.Web.UI/umbraco/images/speechBubble/save.png deleted file mode 100644 index 90b70efcd1..0000000000 Binary files a/src/Umbraco.Web.UI/umbraco/images/speechBubble/save.png and /dev/null differ diff --git a/src/Umbraco.Web.UI/umbraco/images/speechBubble/speechbubble.gif b/src/Umbraco.Web.UI/umbraco/images/speechBubble/speechbubble.gif deleted file mode 100644 index 1f1117e809..0000000000 Binary files a/src/Umbraco.Web.UI/umbraco/images/speechBubble/speechbubble.gif and /dev/null differ diff --git a/src/Umbraco.Web.UI/umbraco/images/speechBubble/speechbubble.png b/src/Umbraco.Web.UI/umbraco/images/speechBubble/speechbubble.png deleted file mode 100644 index a9d025ddcd..0000000000 Binary files a/src/Umbraco.Web.UI/umbraco/images/speechBubble/speechbubble.png and /dev/null differ diff --git a/src/Umbraco.Web.UI/umbraco/images/speechBubble/speechbubbleShadow.png b/src/Umbraco.Web.UI/umbraco/images/speechBubble/speechbubbleShadow.png deleted file mode 100644 index 40c875982f..0000000000 Binary files a/src/Umbraco.Web.UI/umbraco/images/speechBubble/speechbubbleShadow.png and /dev/null differ diff --git a/src/Umbraco.Web.UI/umbraco/images/speechBubble/speechbubbleShadowNew.gif b/src/Umbraco.Web.UI/umbraco/images/speechBubble/speechbubbleShadowNew.gif deleted file mode 100644 index d2e68a15e7..0000000000 Binary files a/src/Umbraco.Web.UI/umbraco/images/speechBubble/speechbubbleShadowNew.gif and /dev/null differ diff --git a/src/Umbraco.Web.UI/umbraco/images/speechBubble/speechbubble_body.png b/src/Umbraco.Web.UI/umbraco/images/speechBubble/speechbubble_body.png deleted file mode 100644 index 17a676f2f4..0000000000 Binary files a/src/Umbraco.Web.UI/umbraco/images/speechBubble/speechbubble_body.png and /dev/null differ diff --git a/src/Umbraco.Web.UI/umbraco/images/speechBubble/speechbubble_bottom.png b/src/Umbraco.Web.UI/umbraco/images/speechBubble/speechbubble_bottom.png deleted file mode 100644 index 7d213a9a71..0000000000 Binary files a/src/Umbraco.Web.UI/umbraco/images/speechBubble/speechbubble_bottom.png and /dev/null differ diff --git a/src/Umbraco.Web.UI/umbraco/images/speechBubble/speechbubble_close.gif b/src/Umbraco.Web.UI/umbraco/images/speechBubble/speechbubble_close.gif deleted file mode 100644 index e6763535b0..0000000000 Binary files a/src/Umbraco.Web.UI/umbraco/images/speechBubble/speechbubble_close.gif and /dev/null differ diff --git a/src/Umbraco.Web.UI/umbraco/images/speechBubble/speechbubble_close_over.gif b/src/Umbraco.Web.UI/umbraco/images/speechBubble/speechbubble_close_over.gif deleted file mode 100644 index b5958a5552..0000000000 Binary files a/src/Umbraco.Web.UI/umbraco/images/speechBubble/speechbubble_close_over.gif and /dev/null differ diff --git a/src/Umbraco.Web.UI/umbraco/images/speechBubble/speechbubble_shadow.gif b/src/Umbraco.Web.UI/umbraco/images/speechBubble/speechbubble_shadow.gif deleted file mode 100644 index 2f49604df5..0000000000 Binary files a/src/Umbraco.Web.UI/umbraco/images/speechBubble/speechbubble_shadow.gif and /dev/null differ diff --git a/src/Umbraco.Web.UI/umbraco/images/speechBubble/speechbubble_top.png b/src/Umbraco.Web.UI/umbraco/images/speechBubble/speechbubble_top.png deleted file mode 100644 index f4fe6dee85..0000000000 Binary files a/src/Umbraco.Web.UI/umbraco/images/speechBubble/speechbubble_top.png and /dev/null differ diff --git a/src/Umbraco.Web.UI/umbraco/images/speechBubble/success.png b/src/Umbraco.Web.UI/umbraco/images/speechBubble/success.png deleted file mode 100644 index 90b70efcd1..0000000000 Binary files a/src/Umbraco.Web.UI/umbraco/images/speechBubble/success.png and /dev/null differ diff --git a/src/Umbraco.Web.UI/umbraco/images/speechBubble/warning.png b/src/Umbraco.Web.UI/umbraco/images/speechBubble/warning.png deleted file mode 100644 index 8dfe6c235b..0000000000 Binary files a/src/Umbraco.Web.UI/umbraco/images/speechBubble/warning.png and /dev/null differ diff --git a/src/Umbraco.Web.UI/umbraco/images/throbber.gif b/src/Umbraco.Web.UI/umbraco/images/throbber.gif deleted file mode 100644 index 95ff649d41..0000000000 Binary files a/src/Umbraco.Web.UI/umbraco/images/throbber.gif and /dev/null differ diff --git a/src/Umbraco.Web.UI/umbraco/images/thumbnails/developer.png b/src/Umbraco.Web.UI/umbraco/images/thumbnails/developer.png deleted file mode 100644 index a5b3122072..0000000000 Binary files a/src/Umbraco.Web.UI/umbraco/images/thumbnails/developer.png and /dev/null differ diff --git a/src/Umbraco.Web.UI/umbraco/images/thumbnails/doc.png b/src/Umbraco.Web.UI/umbraco/images/thumbnails/doc.png deleted file mode 100644 index bb18553f07..0000000000 Binary files a/src/Umbraco.Web.UI/umbraco/images/thumbnails/doc.png and /dev/null differ diff --git a/src/Umbraco.Web.UI/umbraco/images/thumbnails/docWithImage.png b/src/Umbraco.Web.UI/umbraco/images/thumbnails/docWithImage.png deleted file mode 100644 index 73d47021ac..0000000000 Binary files a/src/Umbraco.Web.UI/umbraco/images/thumbnails/docWithImage.png and /dev/null differ diff --git a/src/Umbraco.Web.UI/umbraco/images/thumbnails/folder.png b/src/Umbraco.Web.UI/umbraco/images/thumbnails/folder.png deleted file mode 100644 index 4dad21524a..0000000000 Binary files a/src/Umbraco.Web.UI/umbraco/images/thumbnails/folder.png and /dev/null differ diff --git a/src/Umbraco.Web.UI/umbraco/images/thumbnails/folder_media.png b/src/Umbraco.Web.UI/umbraco/images/thumbnails/folder_media.png deleted file mode 100644 index ccb1285928..0000000000 Binary files a/src/Umbraco.Web.UI/umbraco/images/thumbnails/folder_media.png and /dev/null differ diff --git a/src/Umbraco.Web.UI/umbraco/images/thumbnails/mediaFile.png b/src/Umbraco.Web.UI/umbraco/images/thumbnails/mediaFile.png deleted file mode 100644 index bb18553f07..0000000000 Binary files a/src/Umbraco.Web.UI/umbraco/images/thumbnails/mediaFile.png and /dev/null differ diff --git a/src/Umbraco.Web.UI/umbraco/images/thumbnails/mediaPhoto.png b/src/Umbraco.Web.UI/umbraco/images/thumbnails/mediaPhoto.png deleted file mode 100644 index 73d47021ac..0000000000 Binary files a/src/Umbraco.Web.UI/umbraco/images/thumbnails/mediaPhoto.png and /dev/null differ diff --git a/src/Umbraco.Web.UI/umbraco/images/thumbnails/member.png b/src/Umbraco.Web.UI/umbraco/images/thumbnails/member.png deleted file mode 100644 index f6a7bc2249..0000000000 Binary files a/src/Umbraco.Web.UI/umbraco/images/thumbnails/member.png and /dev/null differ diff --git a/src/Umbraco.Web.UI/umbraco/images/thumbnails/memberGroup.png b/src/Umbraco.Web.UI/umbraco/images/thumbnails/memberGroup.png deleted file mode 100644 index b65640ed6c..0000000000 Binary files a/src/Umbraco.Web.UI/umbraco/images/thumbnails/memberGroup.png and /dev/null differ diff --git a/src/Umbraco.Web.UI/umbraco/images/thumbnails/members.png b/src/Umbraco.Web.UI/umbraco/images/thumbnails/members.png deleted file mode 100644 index 44e393e8a6..0000000000 Binary files a/src/Umbraco.Web.UI/umbraco/images/thumbnails/members.png and /dev/null differ diff --git a/src/Umbraco.Web.UI/umbraco/images/thumbnails/template.png b/src/Umbraco.Web.UI/umbraco/images/thumbnails/template.png deleted file mode 100644 index 1f31ccd07b..0000000000 Binary files a/src/Umbraco.Web.UI/umbraco/images/thumbnails/template.png and /dev/null differ diff --git a/src/Umbraco.Web.UI/umbraco/images/thumbnails/xml.png b/src/Umbraco.Web.UI/umbraco/images/thumbnails/xml.png deleted file mode 100644 index bed12d2316..0000000000 Binary files a/src/Umbraco.Web.UI/umbraco/images/thumbnails/xml.png and /dev/null differ diff --git a/src/Umbraco.Web.UI/umbraco/images/thumbs_lrg.png b/src/Umbraco.Web.UI/umbraco/images/thumbs_lrg.png deleted file mode 100644 index 7d2ed81c24..0000000000 Binary files a/src/Umbraco.Web.UI/umbraco/images/thumbs_lrg.png and /dev/null differ diff --git a/src/Umbraco.Web.UI/umbraco/images/thumbs_med.png b/src/Umbraco.Web.UI/umbraco/images/thumbs_med.png deleted file mode 100644 index 59af8634e2..0000000000 Binary files a/src/Umbraco.Web.UI/umbraco/images/thumbs_med.png and /dev/null differ diff --git a/src/Umbraco.Web.UI/umbraco/images/thumbs_smll.png b/src/Umbraco.Web.UI/umbraco/images/thumbs_smll.png deleted file mode 100644 index 081159777d..0000000000 Binary files a/src/Umbraco.Web.UI/umbraco/images/thumbs_smll.png and /dev/null differ diff --git a/src/Umbraco.Web.UI/umbraco/images/toggleTreeOff.png b/src/Umbraco.Web.UI/umbraco/images/toggleTreeOff.png deleted file mode 100644 index f165e78807..0000000000 Binary files a/src/Umbraco.Web.UI/umbraco/images/toggleTreeOff.png and /dev/null differ diff --git a/src/Umbraco.Web.UI/umbraco/images/toggleTreeOn.png b/src/Umbraco.Web.UI/umbraco/images/toggleTreeOn.png deleted file mode 100644 index 0107bb4e9d..0000000000 Binary files a/src/Umbraco.Web.UI/umbraco/images/toggleTreeOn.png and /dev/null differ diff --git a/src/Umbraco.Web.UI/umbraco/images/topGradient.gif b/src/Umbraco.Web.UI/umbraco/images/topGradient.gif deleted file mode 100644 index 1eda56057a..0000000000 Binary files a/src/Umbraco.Web.UI/umbraco/images/topGradient.gif and /dev/null differ diff --git a/src/Umbraco.Web.UI/umbraco/images/tray/traySprites.png b/src/Umbraco.Web.UI/umbraco/images/tray/traySprites.png deleted file mode 100644 index 2b4f0c9a78..0000000000 Binary files a/src/Umbraco.Web.UI/umbraco/images/tray/traySprites.png and /dev/null differ diff --git a/src/Umbraco.Web.UI/umbraco/images/true.png b/src/Umbraco.Web.UI/umbraco/images/true.png deleted file mode 100644 index 2f86f0ae6b..0000000000 Binary files a/src/Umbraco.Web.UI/umbraco/images/true.png and /dev/null differ diff --git a/src/Umbraco.Web.UI/umbraco/images/umbraco/bin.png b/src/Umbraco.Web.UI/umbraco/images/umbraco/bin.png deleted file mode 100644 index e7a32d3de7..0000000000 Binary files a/src/Umbraco.Web.UI/umbraco/images/umbraco/bin.png and /dev/null differ diff --git a/src/Umbraco.Web.UI/umbraco/images/umbraco/bin_closed.png b/src/Umbraco.Web.UI/umbraco/images/umbraco/bin_closed.png deleted file mode 100644 index afe22ba99e..0000000000 Binary files a/src/Umbraco.Web.UI/umbraco/images/umbraco/bin_closed.png and /dev/null differ diff --git a/src/Umbraco.Web.UI/umbraco/images/umbraco/bin_empty.png b/src/Umbraco.Web.UI/umbraco/images/umbraco/bin_empty.png deleted file mode 100644 index 7d7dd1b221..0000000000 Binary files a/src/Umbraco.Web.UI/umbraco/images/umbraco/bin_empty.png and /dev/null differ diff --git a/src/Umbraco.Web.UI/umbraco/images/umbraco/developerCacheItem.gif b/src/Umbraco.Web.UI/umbraco/images/umbraco/developerCacheItem.gif deleted file mode 100644 index 8a441c6261..0000000000 Binary files a/src/Umbraco.Web.UI/umbraco/images/umbraco/developerCacheItem.gif and /dev/null differ diff --git a/src/Umbraco.Web.UI/umbraco/images/umbraco/developerCacheTypes.gif b/src/Umbraco.Web.UI/umbraco/images/umbraco/developerCacheTypes.gif deleted file mode 100644 index affe7476eb..0000000000 Binary files a/src/Umbraco.Web.UI/umbraco/images/umbraco/developerCacheTypes.gif and /dev/null differ diff --git a/src/Umbraco.Web.UI/umbraco/images/umbraco/developerDatatype.gif b/src/Umbraco.Web.UI/umbraco/images/umbraco/developerDatatype.gif deleted file mode 100644 index fd922b92de..0000000000 Binary files a/src/Umbraco.Web.UI/umbraco/images/umbraco/developerDatatype.gif and /dev/null differ diff --git a/src/Umbraco.Web.UI/umbraco/images/umbraco/developerMacro.gif b/src/Umbraco.Web.UI/umbraco/images/umbraco/developerMacro.gif deleted file mode 100644 index e66d10972c..0000000000 Binary files a/src/Umbraco.Web.UI/umbraco/images/umbraco/developerMacro.gif and /dev/null differ diff --git a/src/Umbraco.Web.UI/umbraco/images/umbraco/developerRegistry.gif b/src/Umbraco.Web.UI/umbraco/images/umbraco/developerRegistry.gif deleted file mode 100644 index 40d496f7ca..0000000000 Binary files a/src/Umbraco.Web.UI/umbraco/images/umbraco/developerRegistry.gif and /dev/null differ diff --git a/src/Umbraco.Web.UI/umbraco/images/umbraco/developerRegistryItem.gif b/src/Umbraco.Web.UI/umbraco/images/umbraco/developerRegistryItem.gif deleted file mode 100644 index 0b19ec1607..0000000000 Binary files a/src/Umbraco.Web.UI/umbraco/images/umbraco/developerRegistryItem.gif and /dev/null differ diff --git a/src/Umbraco.Web.UI/umbraco/images/umbraco/developerScript.gif b/src/Umbraco.Web.UI/umbraco/images/umbraco/developerScript.gif deleted file mode 100644 index 87a04a5f67..0000000000 Binary files a/src/Umbraco.Web.UI/umbraco/images/umbraco/developerScript.gif and /dev/null differ diff --git a/src/Umbraco.Web.UI/umbraco/images/umbraco/developerXslt.gif b/src/Umbraco.Web.UI/umbraco/images/umbraco/developerXslt.gif deleted file mode 100644 index 7204e1b54f..0000000000 Binary files a/src/Umbraco.Web.UI/umbraco/images/umbraco/developerXslt.gif and /dev/null differ diff --git a/src/Umbraco.Web.UI/umbraco/images/umbraco/doc.gif b/src/Umbraco.Web.UI/umbraco/images/umbraco/doc.gif deleted file mode 100644 index 1d70fcc88d..0000000000 Binary files a/src/Umbraco.Web.UI/umbraco/images/umbraco/doc.gif and /dev/null differ diff --git a/src/Umbraco.Web.UI/umbraco/images/umbraco/doc2.gif b/src/Umbraco.Web.UI/umbraco/images/umbraco/doc2.gif deleted file mode 100644 index a8edddd970..0000000000 Binary files a/src/Umbraco.Web.UI/umbraco/images/umbraco/doc2.gif and /dev/null differ diff --git a/src/Umbraco.Web.UI/umbraco/images/umbraco/doc3.gif b/src/Umbraco.Web.UI/umbraco/images/umbraco/doc3.gif deleted file mode 100644 index ec577f78b5..0000000000 Binary files a/src/Umbraco.Web.UI/umbraco/images/umbraco/doc3.gif and /dev/null differ diff --git a/src/Umbraco.Web.UI/umbraco/images/umbraco/doc4.gif b/src/Umbraco.Web.UI/umbraco/images/umbraco/doc4.gif deleted file mode 100644 index d9dbaecfd7..0000000000 Binary files a/src/Umbraco.Web.UI/umbraco/images/umbraco/doc4.gif and /dev/null differ diff --git a/src/Umbraco.Web.UI/umbraco/images/umbraco/doc5.gif b/src/Umbraco.Web.UI/umbraco/images/umbraco/doc5.gif deleted file mode 100644 index aa4c644d63..0000000000 Binary files a/src/Umbraco.Web.UI/umbraco/images/umbraco/doc5.gif and /dev/null differ diff --git a/src/Umbraco.Web.UI/umbraco/images/umbraco/docPic.gif b/src/Umbraco.Web.UI/umbraco/images/umbraco/docPic.gif deleted file mode 100644 index 3985e9d786..0000000000 Binary files a/src/Umbraco.Web.UI/umbraco/images/umbraco/docPic.gif and /dev/null differ diff --git a/src/Umbraco.Web.UI/umbraco/images/umbraco/folder.gif b/src/Umbraco.Web.UI/umbraco/images/umbraco/folder.gif deleted file mode 100644 index 4d4fdc8e92..0000000000 Binary files a/src/Umbraco.Web.UI/umbraco/images/umbraco/folder.gif and /dev/null differ diff --git a/src/Umbraco.Web.UI/umbraco/images/umbraco/folder_o.gif b/src/Umbraco.Web.UI/umbraco/images/umbraco/folder_o.gif deleted file mode 100644 index 4d4fdc8e92..0000000000 Binary files a/src/Umbraco.Web.UI/umbraco/images/umbraco/folder_o.gif and /dev/null differ diff --git a/src/Umbraco.Web.UI/umbraco/images/umbraco/mediaFile.gif b/src/Umbraco.Web.UI/umbraco/images/umbraco/mediaFile.gif deleted file mode 100644 index 76485276e0..0000000000 Binary files a/src/Umbraco.Web.UI/umbraco/images/umbraco/mediaFile.gif and /dev/null differ diff --git a/src/Umbraco.Web.UI/umbraco/images/umbraco/mediaMovie.gif b/src/Umbraco.Web.UI/umbraco/images/umbraco/mediaMovie.gif deleted file mode 100644 index b5f91ce010..0000000000 Binary files a/src/Umbraco.Web.UI/umbraco/images/umbraco/mediaMovie.gif and /dev/null differ diff --git a/src/Umbraco.Web.UI/umbraco/images/umbraco/mediaMulti.gif b/src/Umbraco.Web.UI/umbraco/images/umbraco/mediaMulti.gif deleted file mode 100644 index 28994c8e0c..0000000000 Binary files a/src/Umbraco.Web.UI/umbraco/images/umbraco/mediaMulti.gif and /dev/null differ diff --git a/src/Umbraco.Web.UI/umbraco/images/umbraco/mediaPhoto.gif b/src/Umbraco.Web.UI/umbraco/images/umbraco/mediaPhoto.gif deleted file mode 100644 index 99f8285ac7..0000000000 Binary files a/src/Umbraco.Web.UI/umbraco/images/umbraco/mediaPhoto.gif and /dev/null differ diff --git a/src/Umbraco.Web.UI/umbraco/images/umbraco/member.gif b/src/Umbraco.Web.UI/umbraco/images/umbraco/member.gif deleted file mode 100644 index 5b67adae90..0000000000 Binary files a/src/Umbraco.Web.UI/umbraco/images/umbraco/member.gif and /dev/null differ diff --git a/src/Umbraco.Web.UI/umbraco/images/umbraco/memberGroup.gif b/src/Umbraco.Web.UI/umbraco/images/umbraco/memberGroup.gif deleted file mode 100644 index a2fdf3bf16..0000000000 Binary files a/src/Umbraco.Web.UI/umbraco/images/umbraco/memberGroup.gif and /dev/null differ diff --git a/src/Umbraco.Web.UI/umbraco/images/umbraco/memberType.gif b/src/Umbraco.Web.UI/umbraco/images/umbraco/memberType.gif deleted file mode 100644 index 241f647f70..0000000000 Binary files a/src/Umbraco.Web.UI/umbraco/images/umbraco/memberType.gif and /dev/null differ diff --git a/src/Umbraco.Web.UI/umbraco/images/umbraco/newsletter.gif b/src/Umbraco.Web.UI/umbraco/images/umbraco/newsletter.gif deleted file mode 100644 index d00a6452b7..0000000000 Binary files a/src/Umbraco.Web.UI/umbraco/images/umbraco/newsletter.gif and /dev/null differ diff --git a/src/Umbraco.Web.UI/umbraco/images/umbraco/nitros.gif b/src/Umbraco.Web.UI/umbraco/images/umbraco/nitros.gif deleted file mode 100644 index 029b441e76..0000000000 Binary files a/src/Umbraco.Web.UI/umbraco/images/umbraco/nitros.gif and /dev/null differ diff --git a/src/Umbraco.Web.UI/umbraco/images/umbraco/package.gif b/src/Umbraco.Web.UI/umbraco/images/umbraco/package.gif deleted file mode 100644 index a770d93f4e..0000000000 Binary files a/src/Umbraco.Web.UI/umbraco/images/umbraco/package.gif and /dev/null differ diff --git a/src/Umbraco.Web.UI/umbraco/images/umbraco/package.png b/src/Umbraco.Web.UI/umbraco/images/umbraco/package.png deleted file mode 100644 index 70eb21db5f..0000000000 Binary files a/src/Umbraco.Web.UI/umbraco/images/umbraco/package.png and /dev/null differ diff --git a/src/Umbraco.Web.UI/umbraco/images/umbraco/repository.gif b/src/Umbraco.Web.UI/umbraco/images/umbraco/repository.gif deleted file mode 100644 index 35fd5a8f81..0000000000 Binary files a/src/Umbraco.Web.UI/umbraco/images/umbraco/repository.gif and /dev/null differ diff --git a/src/Umbraco.Web.UI/umbraco/images/umbraco/settingAgent.gif b/src/Umbraco.Web.UI/umbraco/images/umbraco/settingAgent.gif deleted file mode 100644 index 8d726fcdf4..0000000000 Binary files a/src/Umbraco.Web.UI/umbraco/images/umbraco/settingAgent.gif and /dev/null differ diff --git a/src/Umbraco.Web.UI/umbraco/images/umbraco/settingCss.gif b/src/Umbraco.Web.UI/umbraco/images/umbraco/settingCss.gif deleted file mode 100644 index c2c7af9670..0000000000 Binary files a/src/Umbraco.Web.UI/umbraco/images/umbraco/settingCss.gif and /dev/null differ diff --git a/src/Umbraco.Web.UI/umbraco/images/umbraco/settingCssItem.gif b/src/Umbraco.Web.UI/umbraco/images/umbraco/settingCssItem.gif deleted file mode 100644 index a697b9adce..0000000000 Binary files a/src/Umbraco.Web.UI/umbraco/images/umbraco/settingCssItem.gif and /dev/null differ diff --git a/src/Umbraco.Web.UI/umbraco/images/umbraco/settingDataTypeChild.gif b/src/Umbraco.Web.UI/umbraco/images/umbraco/settingDataTypeChild.gif deleted file mode 100644 index cc557f784b..0000000000 Binary files a/src/Umbraco.Web.UI/umbraco/images/umbraco/settingDataTypeChild.gif and /dev/null differ diff --git a/src/Umbraco.Web.UI/umbraco/images/umbraco/settingDatatype.gif b/src/Umbraco.Web.UI/umbraco/images/umbraco/settingDatatype.gif deleted file mode 100644 index 0fb441068a..0000000000 Binary files a/src/Umbraco.Web.UI/umbraco/images/umbraco/settingDatatype.gif and /dev/null differ diff --git a/src/Umbraco.Web.UI/umbraco/images/umbraco/settingDomain.gif b/src/Umbraco.Web.UI/umbraco/images/umbraco/settingDomain.gif deleted file mode 100644 index 8612effcad..0000000000 Binary files a/src/Umbraco.Web.UI/umbraco/images/umbraco/settingDomain.gif and /dev/null differ diff --git a/src/Umbraco.Web.UI/umbraco/images/umbraco/settingLanguage.gif b/src/Umbraco.Web.UI/umbraco/images/umbraco/settingLanguage.gif deleted file mode 100644 index cce48e2e6e..0000000000 Binary files a/src/Umbraco.Web.UI/umbraco/images/umbraco/settingLanguage.gif and /dev/null differ diff --git a/src/Umbraco.Web.UI/umbraco/images/umbraco/settingMasterDatatype.gif b/src/Umbraco.Web.UI/umbraco/images/umbraco/settingMasterDatatype.gif deleted file mode 100644 index 2ac4ddbc68..0000000000 Binary files a/src/Umbraco.Web.UI/umbraco/images/umbraco/settingMasterDatatype.gif and /dev/null differ diff --git a/src/Umbraco.Web.UI/umbraco/images/umbraco/settingMasterTemplate.gif b/src/Umbraco.Web.UI/umbraco/images/umbraco/settingMasterTemplate.gif deleted file mode 100644 index 6c79a948fe..0000000000 Binary files a/src/Umbraco.Web.UI/umbraco/images/umbraco/settingMasterTemplate.gif and /dev/null differ diff --git a/src/Umbraco.Web.UI/umbraco/images/umbraco/settingSkin.gif b/src/Umbraco.Web.UI/umbraco/images/umbraco/settingSkin.gif deleted file mode 100644 index 45b3c7a3ff..0000000000 Binary files a/src/Umbraco.Web.UI/umbraco/images/umbraco/settingSkin.gif and /dev/null differ diff --git a/src/Umbraco.Web.UI/umbraco/images/umbraco/settingTemplate.gif b/src/Umbraco.Web.UI/umbraco/images/umbraco/settingTemplate.gif deleted file mode 100644 index d84b0243c1..0000000000 Binary files a/src/Umbraco.Web.UI/umbraco/images/umbraco/settingTemplate.gif and /dev/null differ diff --git a/src/Umbraco.Web.UI/umbraco/images/umbraco/settingView.gif b/src/Umbraco.Web.UI/umbraco/images/umbraco/settingView.gif deleted file mode 100644 index 74f64b87ce..0000000000 Binary files a/src/Umbraco.Web.UI/umbraco/images/umbraco/settingView.gif and /dev/null differ diff --git a/src/Umbraco.Web.UI/umbraco/images/umbraco/settingXML.gif b/src/Umbraco.Web.UI/umbraco/images/umbraco/settingXML.gif deleted file mode 100644 index b7b1e5ca96..0000000000 Binary files a/src/Umbraco.Web.UI/umbraco/images/umbraco/settingXML.gif and /dev/null differ diff --git a/src/Umbraco.Web.UI/umbraco/images/umbraco/settingsScript.gif b/src/Umbraco.Web.UI/umbraco/images/umbraco/settingsScript.gif deleted file mode 100644 index 556ac66c30..0000000000 Binary files a/src/Umbraco.Web.UI/umbraco/images/umbraco/settingsScript.gif and /dev/null differ diff --git a/src/Umbraco.Web.UI/umbraco/images/umbraco/sprites.png b/src/Umbraco.Web.UI/umbraco/images/umbraco/sprites.png deleted file mode 100644 index 16aa533cf7..0000000000 Binary files a/src/Umbraco.Web.UI/umbraco/images/umbraco/sprites.png and /dev/null differ diff --git a/src/Umbraco.Web.UI/umbraco/images/umbraco/sprites_ie6.gif b/src/Umbraco.Web.UI/umbraco/images/umbraco/sprites_ie6.gif deleted file mode 100644 index 782631ddc6..0000000000 Binary files a/src/Umbraco.Web.UI/umbraco/images/umbraco/sprites_ie6.gif and /dev/null differ diff --git a/src/Umbraco.Web.UI/umbraco/images/umbraco/statistik.gif b/src/Umbraco.Web.UI/umbraco/images/umbraco/statistik.gif deleted file mode 100644 index d526390307..0000000000 Binary files a/src/Umbraco.Web.UI/umbraco/images/umbraco/statistik.gif and /dev/null differ diff --git a/src/Umbraco.Web.UI/umbraco/images/umbraco/uploadpackage.gif b/src/Umbraco.Web.UI/umbraco/images/umbraco/uploadpackage.gif deleted file mode 100644 index 9f9c830d15..0000000000 Binary files a/src/Umbraco.Web.UI/umbraco/images/umbraco/uploadpackage.gif and /dev/null differ diff --git a/src/Umbraco.Web.UI/umbraco/images/umbraco/user.gif b/src/Umbraco.Web.UI/umbraco/images/umbraco/user.gif deleted file mode 100644 index 5b67adae90..0000000000 Binary files a/src/Umbraco.Web.UI/umbraco/images/umbraco/user.gif and /dev/null differ diff --git a/src/Umbraco.Web.UI/umbraco/images/umbraco/userGroup.gif b/src/Umbraco.Web.UI/umbraco/images/umbraco/userGroup.gif deleted file mode 100644 index a2fdf3bf16..0000000000 Binary files a/src/Umbraco.Web.UI/umbraco/images/umbraco/userGroup.gif and /dev/null differ diff --git a/src/Umbraco.Web.UI/umbraco/images/umbraco/userType.gif b/src/Umbraco.Web.UI/umbraco/images/umbraco/userType.gif deleted file mode 100644 index 241f647f70..0000000000 Binary files a/src/Umbraco.Web.UI/umbraco/images/umbraco/userType.gif and /dev/null differ diff --git a/src/Umbraco.Web.UI/umbraco/images/umbracoSplash.png b/src/Umbraco.Web.UI/umbraco/images/umbracoSplash.png deleted file mode 100644 index 0d03a6e1dc..0000000000 Binary files a/src/Umbraco.Web.UI/umbraco/images/umbracoSplash.png and /dev/null differ diff --git a/src/Umbraco.Web.UI/umbraco/members/MemberSearch.ascx b/src/Umbraco.Web.UI/umbraco/members/MemberSearch.ascx deleted file mode 100644 index e1c6f6e664..0000000000 --- a/src/Umbraco.Web.UI/umbraco/members/MemberSearch.ascx +++ /dev/null @@ -1,40 +0,0 @@ -<%@ Control Language="C#" AutoEventWireup="True" CodeBehind="MemberSearch.ascx.cs" Inherits="umbraco.presentation.umbraco.members.MemberSearch" %> -<%@ Register TagPrefix="cc1" Namespace="umbraco.uicontrols" Assembly="controls" %> -
-

Member Search

- " alt="Member Search" class="dashboardIcon" /> -

- -

- - - - - - - - - - - - - - - - - - - - - - - - - - - -
<%= Services.TextService.Localize("name") %><%= Services.TextService.Localize("email") %><%= Services.TextService.Localize("login") %>
<%# Eval("Name") %><%# Eval("Email") %><%# Eval("LoginName") %>
<%# Eval("Name") %><%# Eval("Email") %><%# Eval("LoginName") %>
- -
-
-
diff --git a/src/Umbraco.Web.UI/umbraco/members/ViewMembers.aspx b/src/Umbraco.Web.UI/umbraco/members/ViewMembers.aspx deleted file mode 100644 index 3dd8012118..0000000000 --- a/src/Umbraco.Web.UI/umbraco/members/ViewMembers.aspx +++ /dev/null @@ -1,41 +0,0 @@ -<%@ Page Title="" Language="C#" MasterPageFile="../masterpages/umbracoPage.Master" AutoEventWireup="true" CodeBehind="ViewMembers.aspx.cs" Inherits="umbraco.presentation.members.ViewMembers" %> - -<%@ Register TagPrefix="cc1" Namespace="umbraco.uicontrols" Assembly="controls" %> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
<%= Services.TextService.Localize("name") %><%= Services.TextService.Localize("email") %><%= Services.TextService.Localize("login") %>
- -
-
-
-
- - diff --git a/src/Umbraco.Web.UI/umbraco/members/search.aspx b/src/Umbraco.Web.UI/umbraco/members/search.aspx deleted file mode 100644 index 2bb21660f0..0000000000 --- a/src/Umbraco.Web.UI/umbraco/members/search.aspx +++ /dev/null @@ -1,13 +0,0 @@ -<%@ Page Language="C#" AutoEventWireup="true" MasterPageFile="../masterpages/umbracoPage.Master" CodeBehind="search.aspx.cs" Inherits="umbraco.presentation.members.search" %> -<%@ Register TagPrefix="cc1" Namespace="umbraco.uicontrols" Assembly="controls" %> -<%@ Register Src="~/umbraco/members/MemberSearch.ascx" TagName="MemberSearch" TagPrefix="umb" %> - - - - - - - - - - diff --git a/src/Umbraco.Web.UI/umbraco/ping.aspx b/src/Umbraco.Web.UI/umbraco/ping.aspx new file mode 100644 index 0000000000..d79e25b2a1 --- /dev/null +++ b/src/Umbraco.Web.UI/umbraco/ping.aspx @@ -0,0 +1,2 @@ +<%@ Page language="c#" AutoEventWireup="True" %> +I'm alive! \ No newline at end of file diff --git a/src/Umbraco.Web.UI/umbraco/settings/views/EditView.aspx.cs b/src/Umbraco.Web.UI/umbraco/settings/views/EditView.aspx.cs index 58c78827ec..a91414fd02 100644 --- a/src/Umbraco.Web.UI/umbraco/settings/views/EditView.aspx.cs +++ b/src/Umbraco.Web.UI/umbraco/settings/views/EditView.aspx.cs @@ -64,9 +64,9 @@ namespace Umbraco.Web.UI.Umbraco.Settings.Views get { if (Request.QueryString["treeType"].IsNullOrWhiteSpace()) - { - return TreeDefinitionCollection.Instance.FindTree().Tree.Alias; - } + { + return Constants.Trees.PartialViews; + } return Request.CleanForXss("treeType"); } } diff --git a/src/Umbraco.Web.UI/umbraco_client/Application/UmbracoApplicationActions.js b/src/Umbraco.Web.UI/umbraco_client/Application/UmbracoApplicationActions.js index 46b7a15e48..e40e59e792 100644 --- a/src/Umbraco.Web.UI/umbraco_client/Application/UmbracoApplicationActions.js +++ b/src/Umbraco.Web.UI/umbraco_client/Application/UmbracoApplicationActions.js @@ -415,18 +415,6 @@ Umbraco.Application.Actions = function() { }, - actionDisable: function() { - /// - /// Used for users when disable is selected. - /// - - if (confirm(uiKeys['defaultdialogs_confirmdisable'] + ' "' + UmbClientMgr.mainTree().getActionNode().nodeName + '"?\n\n')) { - umbraco.presentation.webservices.legacyAjaxCalls.DisableUser(UmbClientMgr.mainTree().getActionNode().nodeId, function() { - UmbClientMgr.mainTree().reloadActionNode(); - }); - } - }, - actionMove: function() { /// diff --git a/src/Umbraco.Web.UI/web.Template.Debug.config b/src/Umbraco.Web.UI/web.Template.Debug.config index 7816568561..6d91008f79 100644 --- a/src/Umbraco.Web.UI/web.Template.Debug.config +++ b/src/Umbraco.Web.UI/web.Template.Debug.config @@ -371,14 +371,14 @@ xdt:Locator="Condition(_defaultNamespace:assemblyIdentity[@name='HtmlAgilityPack']])" /> - + - + - + @@ -376,10 +376,10 @@ - - - - + + + + diff --git a/src/Umbraco.Web/Cache/DomainCacheRefresher.cs b/src/Umbraco.Web/Cache/DomainCacheRefresher.cs index 955d87ff59..d19d4f6ea0 100644 --- a/src/Umbraco.Web/Cache/DomainCacheRefresher.cs +++ b/src/Umbraco.Web/Cache/DomainCacheRefresher.cs @@ -28,6 +28,12 @@ namespace Umbraco.Web.Cache get { return "Domain cache refresher"; } } + public override void RefreshAll() + { + ClearCache(); + base.RefreshAll(); + } + public override void Refresh(int id) { ClearCache(); diff --git a/src/Umbraco.Web/Editors/AuthenticationController.cs b/src/Umbraco.Web/Editors/AuthenticationController.cs index e3a3005731..0b9b555287 100644 --- a/src/Umbraco.Web/Editors/AuthenticationController.cs +++ b/src/Umbraco.Web/Editors/AuthenticationController.cs @@ -4,26 +4,29 @@ using System.Net; using System.Net.Http; using System.Collections.Generic; using System.Threading.Tasks; +using System.Web; using System.Web.Http; +using System.Web.Mvc; using AutoMapper; using Microsoft.AspNet.Identity; +using Microsoft.AspNet.Identity.Owin; using Microsoft.Owin; using Umbraco.Core; +using Umbraco.Core.Models; +using Umbraco.Core.Security; +using Umbraco.Core.Services; using Umbraco.Web.Models; using Umbraco.Web.Models.ContentEditing; using Umbraco.Web.Mvc; -using Umbraco.Core.Security; using Umbraco.Web.Security; +using Umbraco.Web.Security.Identity; using Umbraco.Web.WebApi; using Umbraco.Web.WebApi.Filters; -using Microsoft.AspNet.Identity.Owin; -using Umbraco.Core.Logging; using Umbraco.Core.Configuration; -using Umbraco.Web.Security.Identity; +using Umbraco.Core.Logging; namespace Umbraco.Web.Editors { - /// /// The API controller used for editing content /// @@ -97,7 +100,7 @@ namespace Umbraco.Web.Editors /// Checks if the current user's cookie is valid and if so returns OK or a 400 (BadRequest) ///
/// - [HttpGet] + [System.Web.Http.HttpGet] public bool IsAuthenticated() { var attempt = UmbracoContext.Security.AuthorizeRequest(); @@ -149,9 +152,7 @@ namespace Umbraco.Web.Editors [SetAngularAntiForgeryTokens] public async Task PostLogin(LoginModel loginModel) { - var http = this.TryGetHttpContext(); - if (http.Success == false) - throw new InvalidOperationException("This method requires that an HttpContext be active"); + var http = EnsureHttpContext(); var result = await SignInManager.PasswordSignInAsync( loginModel.Username, loginModel.Password, isPersistent: true, shouldLockout: true); @@ -217,6 +218,91 @@ namespace Umbraco.Web.Editors } } + /// + /// Processes a password reset request. Looks for a match on the provided email address + /// and if found sends an email with a link to reset it + /// + /// + [SetAngularAntiForgeryTokens] + public async Task PostRequestPasswordReset(RequestPasswordResetModel model) + { + // If this feature is switched off in configuration the UI will be amended to not make the request to reset password available. + // So this is just a server-side secondary check. + if (UmbracoConfig.For.UmbracoSettings().Security.AllowPasswordReset == false) + { + throw new HttpResponseException(HttpStatusCode.BadRequest); + } + var identityUser = await SignInManager.UserManager.FindByEmailAsync(model.Email); + if (identityUser != null) + { + var user = Services.UserService.GetByEmail(model.Email); + if (user != null && user.IsLockedOut == false) + { + var code = await UserManager.GeneratePasswordResetTokenAsync(identityUser.Id); + var callbackUrl = ConstuctCallbackUrl(identityUser.Id, code); + + var message = Services.TextService.Localize("resetPasswordEmailCopyFormat", + //Ensure the culture of the found user is used for the email! + UserExtensions.GetUserCulture(identityUser.Culture, Services.TextService), + new[] {identityUser.UserName, callbackUrl}); + + await UserManager.SendEmailAsync(identityUser.Id, + Services.TextService.Localize("login/resetPasswordEmailCopySubject", + //Ensure the culture of the found user is used for the email! + UserExtensions.GetUserCulture(identityUser.Culture, Services.TextService)), + message); + } + } + + return Request.CreateResponse(HttpStatusCode.OK); + } + + private string ConstuctCallbackUrl(int userId, string code) + { + //get an mvc helper to get the url + var http = EnsureHttpContext(); + var urlHelper = new UrlHelper(http.Request.RequestContext); + + var action = urlHelper.Action("ValidatePasswordResetCode", "BackOffice", + new + { + area = GlobalSettings.UmbracoMvcArea, + u = userId, + r = code + }); + + //TODO: Virtual path? + + return string.Format("{0}://{1}{2}", + http.Request.Url.Scheme, + http.Request.Url.Host + (http.Request.Url.Port == 80 ? string.Empty : ":" + http.Request.Url.Port), + action); + } + + /// + /// Processes a set password request. Validates the request and sets a new password. + /// + /// + [SetAngularAntiForgeryTokens] + public async Task PostSetPassword(SetPasswordModel model) + { + var result = await UserManager.ResetPasswordAsync(model.UserId, model.ResetCode, model.Password); + if (result.Succeeded) + { + return Request.CreateResponse(HttpStatusCode.OK); + } + + return Request.CreateValidationErrorResponse( + result.Errors.Any() ? result.Errors.First() : "Set password failed"); + } + + private HttpContextBase EnsureHttpContext() + { + var attempt = this.TryGetHttpContext(); + if (attempt.Success == false) + throw new InvalidOperationException("This method requires that an HttpContext be active"); + return attempt.Result; + } /// /// Logs the current user out diff --git a/src/Umbraco.Web/Editors/BackOfficeController.cs b/src/Umbraco.Web/Editors/BackOfficeController.cs index f4742e3e9f..59ccac2de8 100644 --- a/src/Umbraco.Web/Editors/BackOfficeController.cs +++ b/src/Umbraco.Web/Editors/BackOfficeController.cs @@ -4,6 +4,8 @@ using System.Configuration; using System.Globalization; using System.IO; using System.Linq; +using System.Net; +using System.Net.Http; using System.Text; using System.Threading; using System.Threading.Tasks; @@ -26,6 +28,7 @@ using Umbraco.Core.Manifest; using Umbraco.Core.Models; using Umbraco.Core.Models.Identity; using Umbraco.Core.Security; +using Umbraco.Web.Models; using Umbraco.Web.Models.ContentEditing; using Umbraco.Web.Mvc; using Umbraco.Web.PropertyEditors; @@ -34,6 +37,7 @@ using Umbraco.Web.Trees; using Umbraco.Web.UI.JavaScript; using Umbraco.Web.WebApi.Filters; using Umbraco.Web.WebServices; +using Umbraco.Core.Services; using Action = Umbraco.Web._Legacy.Actions.Action; using Constants = Umbraco.Core.Constants; @@ -54,6 +58,10 @@ namespace Umbraco.Web.Editors private BackOfficeUserManager _userManager; private BackOfficeSignInManager _signInManager; + private const string TokenExternalSignInError = "ExternalSignInError"; + private const string TokenPasswordResetCode = "PasswordResetCode"; + private static readonly string[] TempDataTokenNames = { TokenExternalSignInError, TokenPasswordResetCode }; + protected BackOfficeSignInManager SignInManager { get { return _signInManager ?? (_signInManager = OwinContext.Get()); } @@ -364,6 +372,7 @@ namespace Umbraco.Web.Editors }, {"keepUserLoggedIn", UmbracoConfig.For.UmbracoSettings().Security.KeepUserLoggedIn}, {"cssPath", IOHelper.ResolveUrl(SystemDirectories.Css).TrimEnd('/')}, + {"allowPasswordReset", UmbracoConfig.For.UmbracoSettings().Security.AllowPasswordReset}, } }, { @@ -433,7 +442,25 @@ namespace Umbraco.Web.Editors User.Identity.GetUserId()); } + [HttpGet] + public async Task ValidatePasswordResetCode([Bind(Prefix = "u")]int userId, [Bind(Prefix = "r")]string resetCode) + { + var user = UserManager.FindById(userId); + if (user != null) + { + var result = await UserManager.UserTokenProvider.ValidateAsync("ResetPassword", resetCode, UserManager, user); + if (result) + { + //Add a flag and redirect for it to be displayed + TempData[TokenPasswordResetCode] = new ValidatePasswordResetCodeModel {UserId = userId, ResetCode = resetCode}; + return RedirectToLocal(Url.Action("Default", "BackOffice")); + } + } + //Add error and redirect for it to be displayed + TempData[TokenPasswordResetCode] = new[] { Services.TextService.Localize("login/resetCodeExpired") }; + return RedirectToLocal(Url.Action("Default", "BackOffice")); + } [HttpGet] public async Task ExternalLinkLoginCallback() @@ -445,7 +472,7 @@ namespace Umbraco.Web.Editors if (loginInfo == null) { //Add error and redirect for it to be displayed - TempData["ExternalSignInError"] = new[] { "An error occurred, could not get external login info" }; + TempData[TokenExternalSignInError] = new[] { "An error occurred, could not get external login info" }; return RedirectToLocal(Url.Action("Default", "BackOffice")); } @@ -456,7 +483,7 @@ namespace Umbraco.Web.Editors } //Add errors and redirect for it to be displayed - TempData["ExternalSignInError"] = result.Errors; + TempData[TokenExternalSignInError] = result.Errors; return RedirectToLocal(Url.Action("Default", "BackOffice")); } @@ -468,22 +495,27 @@ namespace Umbraco.Web.Editors } /// - /// Used by Default and AuthorizeUpgrade to render as per normal if there's no external login info, otherwise - /// process the external login info. + /// Used by Default and AuthorizeUpgrade to render as per normal if there's no external login info, + /// otherwise process the external login info. /// - /// - private async Task RenderDefaultOrProcessExternalLoginAsync(Func defaultResponse, Func externalSignInResponse) + /// + private async Task RenderDefaultOrProcessExternalLoginAsync( + Func defaultResponse, + Func externalSignInResponse) { if (defaultResponse == null) throw new ArgumentNullException("defaultResponse"); if (externalSignInResponse == null) throw new ArgumentNullException("externalSignInResponse"); ViewBag.UmbracoPath = GlobalSettings.UmbracoMvcArea; - //check if there's errors in the TempData, assign to view bag and render the view - if (TempData["ExternalSignInError"] != null) - { - ViewBag.ExternalSignInError = TempData["ExternalSignInError"]; - return defaultResponse(); + //check if there is the TempData with the any token name specified, if so, assign to view bag and render the view + foreach (var tempDataTokenName in TempDataTokenNames) + { + if (TempData[tempDataTokenName] != null) + { + ViewData[tempDataTokenName] = TempData[tempDataTokenName]; + return defaultResponse(); + } } //First check if there's external login info, if there's not proceed as normal @@ -521,7 +553,7 @@ namespace Umbraco.Web.Editors { if (await AutoLinkAndSignInExternalAccount(loginInfo) == false) { - ViewBag.ExternalSignInError = new[] { "The requested provider (" + loginInfo.Login.LoginProvider + ") has not been linked to to an account" }; + ViewData[TokenExternalSignInError] = new[] { "The requested provider (" + loginInfo.Login.LoginProvider + ") has not been linked to to an account" }; } //Remove the cookie otherwise this message will keep appearing @@ -556,7 +588,7 @@ namespace Umbraco.Web.Editors //we are allowing auto-linking/creating of local accounts if (loginInfo.Email.IsNullOrWhiteSpace()) { - ViewBag.ExternalSignInError = new[] { "The requested provider (" + loginInfo.Login.LoginProvider + ") has not provided an email address, the account cannot be linked." }; + ViewData[TokenExternalSignInError] = new[] { "The requested provider (" + loginInfo.Login.LoginProvider + ") has not provided an email address, the account cannot be linked." }; } else { @@ -565,7 +597,7 @@ namespace Umbraco.Web.Editors var foundByEmail = Services.UserService.GetByEmail(loginInfo.Email); if (foundByEmail != null) { - ViewBag.ExternalSignInError = new[] { "A user with this email address already exists locally. You will need to login locally to Umbraco and link this external provider: " + loginInfo.Login.LoginProvider }; + ViewData[TokenExternalSignInError] = new[] { "A user with this email address already exists locally. You will need to login locally to Umbraco and link this external provider: " + loginInfo.Login.LoginProvider }; } else { @@ -573,7 +605,7 @@ namespace Umbraco.Web.Editors var userType = Services.UserService.GetUserTypeByAlias(defaultUserType); if (userType == null) { - ViewBag.ExternalSignInError = new[] { "Could not auto-link this account, the specified User Type does not exist: " + defaultUserType }; + ViewData[TokenExternalSignInError] = new[] { "Could not auto-link this account, the specified User Type does not exist: " + defaultUserType }; } else { @@ -601,21 +633,21 @@ namespace Umbraco.Web.Editors if (userCreationResult.Succeeded == false) { - ViewBag.ExternalSignInError = userCreationResult.Errors; + ViewData[TokenExternalSignInError] = userCreationResult.Errors; } else { var linkResult = await UserManager.AddLoginAsync(autoLinkUser.Id, loginInfo.Login); if (linkResult.Succeeded == false) { - ViewBag.ExternalSignInError = linkResult.Errors; + ViewData[TokenExternalSignInError] = linkResult.Errors; //If this fails, we should really delete the user since it will be in an inconsistent state! var deleteResult = await UserManager.DeleteAsync(autoLinkUser); if (deleteResult.Succeeded == false) { //DOH! ... this isn't good, combine all errors to be shown - ViewBag.ExternalSignInError = linkResult.Errors.Concat(deleteResult.Errors); + ViewData[TokenExternalSignInError] = linkResult.Errors.Concat(deleteResult.Errors); } } else diff --git a/src/Umbraco.Web/Editors/ContentController.cs b/src/Umbraco.Web/Editors/ContentController.cs index aaf99a0519..d1604f6a8e 100644 --- a/src/Umbraco.Web/Editors/ContentController.cs +++ b/src/Umbraco.Web/Editors/ContentController.cs @@ -47,13 +47,13 @@ namespace Umbraco.Web.Editors [PluginController("UmbracoApi")] [UmbracoApplicationAuthorizeAttribute(Constants.Applications.Content)] public class ContentController : ContentControllerBase - { + { /// /// Constructor /// public ContentController() - : this(UmbracoContext.Current) - { + : this(UmbracoContext.Current) + { } /// @@ -61,8 +61,8 @@ namespace Umbraco.Web.Editors /// /// public ContentController(UmbracoContext umbracoContext) - : base(umbracoContext) - { + : base(umbracoContext) + { } /// @@ -109,15 +109,15 @@ namespace Umbraco.Web.Editors [EnsureUserPermissionForContent("id")] public ContentItemDisplay GetById(int id) { - var foundContent = GetObjectFromRequest(() => Services.ContentService.GetById(id)); + var foundContent = GetObjectFromRequest(() => Services.ContentService.GetById(id)); if (foundContent == null) { HandleContentNotFound(id); } - + var content = Mapper.Map(foundContent); return content; - } + } [EnsureUserPermissionForContent("id")] public ContentItemDisplay GetWithTreeDefinition(int id) @@ -155,7 +155,7 @@ namespace Umbraco.Web.Editors //remove this tab if it exists: umbContainerView var containerTab = mapped.Tabs.FirstOrDefault(x => x.Alias == Constants.Conventions.PropertyGroups.ListViewGroupName); - mapped.Tabs = mapped.Tabs.Except(new[] {containerTab}); + mapped.Tabs = mapped.Tabs.Except(new[] { containerTab }); return mapped; } @@ -168,7 +168,7 @@ namespace Umbraco.Web.Editors { var url = Umbraco.NiceUrl(id); var response = Request.CreateResponse(HttpStatusCode.OK); - response.Content = new StringContent(url, Encoding.UTF8, "application/json"); + response.Content = new StringContent(url, Encoding.UTF8, "application/json"); return response; } @@ -178,18 +178,21 @@ namespace Umbraco.Web.Editors /// [FilterAllowedOutgoingContent(typeof(IEnumerable>), "Items")] public PagedResult> GetChildren( - int id, - int pageNumber = 0, //TODO: This should be '1' as it's not the index - int pageSize = 0, - string orderBy = "SortOrder", - Direction orderDirection = Direction.Ascending, - string filter = "") - { + int id, + int pageNumber = 0, //TODO: This should be '1' as it's not the index + int pageSize = 0, + string orderBy = "SortOrder", + Direction orderDirection = Direction.Ascending, + bool orderBySystemField = true, + string filter = "") + { long totalChildren; IContent[] children; if (pageNumber > 0 && pageSize > 0) { - children = Services.ContentService.GetPagedChildren(id, (pageNumber - 1), pageSize, out totalChildren, orderBy, orderDirection, filter).ToArray(); + children = Services.ContentService + .GetPagedChildren(id, (pageNumber - 1), pageSize, out totalChildren + , orderBy, orderDirection, orderBySystemField, filter).ToArray(); } else { @@ -204,7 +207,7 @@ namespace Umbraco.Web.Editors var pagedResult = new PagedResult>(totalChildren, pageNumber, pageSize); pagedResult.Items = children - .Select(Mapper.Map>); + .Select(Mapper.Map>); return pagedResult; } @@ -212,7 +215,7 @@ namespace Umbraco.Web.Editors [Obsolete("Dont use this, it is incorrectly named, use HasPermission instead")] public bool GetHasPermission(string permissionToCheck, int nodeId) { - return HasPermission(permissionToCheck, nodeId); + return HasPermission(permissionToCheck, nodeId); } /// @@ -224,8 +227,8 @@ namespace Umbraco.Web.Editors public Dictionary GetPermissions(int[] nodeIds) { return Services.UserService - .GetPermissions(Security.CurrentUser, nodeIds) - .ToDictionary(x => x.EntityId, x => x.AssignedPermissions); + .GetPermissions(Security.CurrentUser, nodeIds) + .ToDictionary(x => x.EntityId, x => x.AssignedPermissions); } [HttpGet] @@ -239,7 +242,7 @@ namespace Umbraco.Web.Editors return false; } - + /// /// Saves content /// @@ -247,16 +250,16 @@ namespace Umbraco.Web.Editors [FileUploadCleanupFilter] [ContentPostValidate] public ContentItemDisplay PostSave( - [ModelBinder(typeof(ContentItemBinder))] - ContentItemSave contentItem) - { + [ModelBinder(typeof(ContentItemBinder))] + ContentItemSave contentItem) + { //If we've reached here it means: // * Our model has been bound // * and validated // * any file attachments have been saved to their temporary location for us to use // * we have a reference to the DTO object and the persisted object // * Permissions are valid - + MapPropertyValues(contentItem); //We need to manually check the validation results here because: @@ -274,7 +277,7 @@ namespace Umbraco.Web.Editors var forDisplay = Mapper.Map(contentItem.PersistedContent); forDisplay.Errors = ModelState.ToErrorDictionary(); throw new HttpResponseException(Request.CreateValidationErrorResponse(forDisplay)); - + } //if the model state is not valid we cannot publish so change it to save @@ -291,7 +294,7 @@ namespace Umbraco.Web.Editors //initialize this to successful var publishStatus = Attempt.Succeed(); - var wasCancelled = false; + var wasCancelled = false; if (contentItem.Action == ContentSaveAction.Save || contentItem.Action == ContentSaveAction.SaveNew) { @@ -326,8 +329,8 @@ namespace Umbraco.Web.Editors if (wasCancelled == false) { display.AddSuccessNotification( - Services.TextService.Localize("speechBubbles/editContentSavedHeader"), - Services.TextService.Localize("speechBubbles/editContentSavedText")); + Services.TextService.Localize("speechBubbles/editContentSavedHeader"), + Services.TextService.Localize("speechBubbles/editContentSavedText")); } else { @@ -339,8 +342,8 @@ namespace Umbraco.Web.Editors if (wasCancelled == false) { display.AddSuccessNotification( - Services.TextService.Localize("speechBubbles/editContentSendToPublish"), - Services.TextService.Localize("speechBubbles/editContentSendToPublishText")); + Services.TextService.Localize("speechBubbles/editContentSendToPublish"), + Services.TextService.Localize("speechBubbles/editContentSendToPublishText")); } else { @@ -365,7 +368,7 @@ namespace Umbraco.Web.Editors return display; } - + /// /// Publishes a document with a given ID /// @@ -391,7 +394,7 @@ namespace Umbraco.Web.Editors { var notificationModel = new SimpleNotificationModel(); ShowMessageForPublishStatus(publishResult.Result, notificationModel); - return Request.CreateValidationErrorResponse(notificationModel); + return Request.CreateValidationErrorResponse(notificationModel); } //return ok @@ -439,7 +442,7 @@ namespace Umbraco.Web.Editors //returning an object of INotificationModel will ensure that any pending // notification messages are added to the response. return Request.CreateValidationErrorResponse(new SimpleNotificationModel()); - } + } } return Request.CreateResponse(HttpStatusCode.OK); @@ -456,7 +459,7 @@ namespace Umbraco.Web.Editors [HttpPost] [EnsureUserPermissionForContent(Constants.System.RecycleBinContent)] public HttpResponseMessage EmptyRecycleBin() - { + { Services.ContentService.EmptyRecycleBin(); return Request.CreateResponse(HttpStatusCode.OK); } @@ -515,7 +518,7 @@ namespace Umbraco.Web.Editors var response = Request.CreateResponse(HttpStatusCode.OK); response.Content = new StringContent(toMove.Path, Encoding.UTF8, "application/json"); - return response; + return response; } /// @@ -547,7 +550,7 @@ namespace Umbraco.Web.Editors if (foundContent == null) HandleContentNotFound(id); - + var unpublishResult = Services.ContentService.WithResult().UnPublish(foundContent, Security.CurrentUser.Id); var content = Mapper.Map(foundContent); @@ -558,7 +561,7 @@ namespace Umbraco.Web.Editors throw new HttpResponseException(Request.CreateValidationErrorResponse(content)); } else - { + { content.AddSuccessNotification(Services.TextService.Localize("content/unPublish"), Services.TextService.Localize("speechBubbles/contentUnpublished")); return content; } @@ -596,8 +599,8 @@ namespace Umbraco.Web.Editors contentItem.PersistedContent.ReleaseDate = contentItem.ReleaseDate; //only set the template if it didn't change var templateChanged = (contentItem.PersistedContent.Template == null && contentItem.TemplateAlias.IsNullOrWhiteSpace() == false) - || (contentItem.PersistedContent.Template != null && contentItem.PersistedContent.Template.Alias != contentItem.TemplateAlias) - || (contentItem.PersistedContent.Template != null && contentItem.TemplateAlias.IsNullOrWhiteSpace()); + || (contentItem.PersistedContent.Template != null && contentItem.PersistedContent.Template.Alias != contentItem.TemplateAlias) + || (contentItem.PersistedContent.Template != null && contentItem.TemplateAlias.IsNullOrWhiteSpace()); if (templateChanged) { var template = Services.FileService.GetTemplate(contentItem.TemplateAlias); @@ -640,8 +643,8 @@ namespace Umbraco.Web.Editors if (toMove.ContentType.AllowedAsRoot == false) { throw new HttpResponseException( - Request.CreateNotificationValidationErrorResponse( - Services.TextService.Localize("moveOrCopy/notAllowedAtRoot"))); + Request.CreateNotificationValidationErrorResponse( + Services.TextService.Localize("moveOrCopy/notAllowedAtRoot"))); } } else @@ -654,19 +657,19 @@ namespace Umbraco.Web.Editors //check if the item is allowed under this one if (parent.ContentType.AllowedContentTypes.Select(x => x.Id).ToArray() - .Any(x => x.Value == toMove.ContentType.Id) == false) + .Any(x => x.Value == toMove.ContentType.Id) == false) { throw new HttpResponseException( - Request.CreateNotificationValidationErrorResponse( - Services.TextService.Localize("moveOrCopy/notAllowedByContentType"))); + Request.CreateNotificationValidationErrorResponse( + Services.TextService.Localize("moveOrCopy/notAllowedByContentType"))); } // Check on paths if ((string.Format(",{0},", parent.Path)).IndexOf(string.Format(",{0},", toMove.Id), StringComparison.Ordinal) > -1) - { + { throw new HttpResponseException( - Request.CreateNotificationValidationErrorResponse( - Services.TextService.Localize("moveOrCopy/notAllowedByPath"))); + Request.CreateNotificationValidationErrorResponse( + Services.TextService.Localize("moveOrCopy/notAllowedByPath"))); } } @@ -680,52 +683,52 @@ namespace Umbraco.Web.Editors case PublishStatusType.Success: case PublishStatusType.SuccessAlreadyPublished: display.AddSuccessNotification( - Services.TextService.Localize("speechBubbles/editContentPublishedHeader"), - Services.TextService.Localize("speechBubbles/editContentPublishedText")); + Services.TextService.Localize("speechBubbles/editContentPublishedHeader"), + Services.TextService.Localize("speechBubbles/editContentPublishedText")); break; case PublishStatusType.FailedPathNotPublished: display.AddWarningNotification( - Services.TextService.Localize("publish"), - Services.TextService.Localize("publish/contentPublishedFailedByParent", - new[] {string.Format("{0} ({1})", status.ContentItem.Name, status.ContentItem.Id)}).Trim()); + Services.TextService.Localize("publish"), + Services.TextService.Localize("publish/contentPublishedFailedByParent", + new[] { string.Format("{0} ({1})", status.ContentItem.Name, status.ContentItem.Id) }).Trim()); break; case PublishStatusType.FailedCancelledByEvent: AddCancelMessage(display, "publish", "speechBubbles/contentPublishedFailedByEvent"); - break; + break; case PublishStatusType.FailedAwaitingRelease: display.AddWarningNotification( - Services.TextService.Localize("publish"), - Services.TextService.Localize("publish/contentPublishedFailedAwaitingRelease", - new[] {string.Format("{0} ({1})", status.ContentItem.Name, status.ContentItem.Id)}).Trim()); + Services.TextService.Localize("publish"), + Services.TextService.Localize("publish/contentPublishedFailedAwaitingRelease", + new[] { string.Format("{0} ({1})", status.ContentItem.Name, status.ContentItem.Id) }).Trim()); break; case PublishStatusType.FailedHasExpired: display.AddWarningNotification( - Services.TextService.Localize("publish"), - Services.TextService.Localize("publish/contentPublishedFailedExpired", - new[] - { - string.Format("{0} ({1})", status.ContentItem.Name, status.ContentItem.Id), - }).Trim()); + Services.TextService.Localize("publish"), + Services.TextService.Localize("publish/contentPublishedFailedExpired", + new[] + { + string.Format("{0} ({1})", status.ContentItem.Name, status.ContentItem.Id), + }).Trim()); break; case PublishStatusType.FailedIsTrashed: //TODO: We should add proper error messaging for this! break; case PublishStatusType.FailedContentInvalid: display.AddWarningNotification( - Services.TextService.Localize("publish"), - Services.TextService.Localize("publish/contentPublishedFailedInvalid", - new[] - { - string.Format("{0} ({1})", status.ContentItem.Name, status.ContentItem.Id), - string.Join(",", status.InvalidProperties.Select(x => x.Alias)) - }).Trim()); + Services.TextService.Localize("publish"), + Services.TextService.Localize("publish/contentPublishedFailedInvalid", + new[] + { + string.Format("{0} ({1})", status.ContentItem.Name, status.ContentItem.Id), + string.Join(",", status.InvalidProperties.Select(x => x.Alias)) + }).Trim()); break; default: throw new IndexOutOfRangeException(); } } - + /// /// Performs a permissions check for the user to check if it has access to the node based on @@ -740,15 +743,15 @@ namespace Umbraco.Web.Editors /// Specifies the already resolved content item to check against /// internal static bool CheckPermissions( - IDictionary storage, - IUser user, - IUserService userService, - IContentService contentService, - int nodeId, - char[] permissionsToCheck = null, - IContent contentItem = null) + IDictionary storage, + IUser user, + IUserService userService, + IContentService contentService, + int nodeId, + char[] permissionsToCheck = null, + IContent contentItem = null) { - + if (contentItem == null && nodeId != Constants.System.Root && nodeId != Constants.System.RecycleBinContent) { contentItem = contentService.GetById(nodeId); @@ -763,16 +766,16 @@ namespace Umbraco.Web.Editors } var hasPathAccess = (nodeId == Constants.System.Root) - ? UserExtensions.HasPathAccess( - Constants.System.Root.ToInvariantString(), - user.StartContentId, - Constants.System.RecycleBinContent) - : (nodeId == Constants.System.RecycleBinContent) - ? UserExtensions.HasPathAccess( - Constants.System.RecycleBinContent.ToInvariantString(), - user.StartContentId, - Constants.System.RecycleBinContent) - : user.HasPathAccess(contentItem); + ? UserExtensions.HasPathAccess( + Constants.System.Root.ToInvariantString(), + user.StartContentId, + Constants.System.RecycleBinContent) + : (nodeId == Constants.System.RecycleBinContent) + ? UserExtensions.HasPathAccess( + Constants.System.RecycleBinContent.ToInvariantString(), + user.StartContentId, + Constants.System.RecycleBinContent) + : user.HasPathAccess(contentItem); if (hasPathAccess == false) { diff --git a/src/Umbraco.Web/Editors/MediaController.cs b/src/Umbraco.Web/Editors/MediaController.cs index 05f15b4250..dbdd9bea40 100644 --- a/src/Umbraco.Web/Editors/MediaController.cs +++ b/src/Umbraco.Web/Editors/MediaController.cs @@ -51,7 +51,7 @@ namespace Umbraco.Web.Editors /// public MediaController() : this(UmbracoContext.Current) - { + { } /// @@ -155,7 +155,7 @@ namespace Umbraco.Web.Editors var folderTypes = Services.ContentTypeService.GetAllMediaTypes().ToArray().Where(x => x.Alias.EndsWith("Folder")).Select(x => x.Id); var children = (id < 0) ? Services.MediaService.GetRootMedia() : Services.MediaService.GetById(id).Children(); - return children.Where(x => folderTypes.Contains(x.ContentTypeId)).Select(Mapper.Map>); + return children.Where(x => folderTypes.Contains(x.ContentTypeId)).Select(Mapper.Map>); } /// @@ -179,13 +179,16 @@ namespace Umbraco.Web.Editors int pageSize = 0, string orderBy = "SortOrder", Direction orderDirection = Direction.Ascending, + bool orderBySystemField = true, string filter = "") { - int totalChildren; + long totalChildren; IMedia[] children; if (pageNumber > 0 && pageSize > 0) { - children = Services.MediaService.GetPagedChildren(id, (pageNumber - 1), pageSize, out totalChildren, orderBy, orderDirection, filter).ToArray(); + children = Services.MediaService + .GetPagedChildren(id, (pageNumber - 1), pageSize, out totalChildren + , orderBy, orderDirection, orderBySystemField, filter).ToArray(); } else { @@ -260,7 +263,7 @@ namespace Umbraco.Web.Editors var response = Request.CreateResponse(HttpStatusCode.OK); response.Content = new StringContent(toMove.Path, Encoding.UTF8, "application/json"); - return response; + return response; } /// @@ -306,7 +309,7 @@ namespace Umbraco.Web.Editors //return the updated model var display = Mapper.Map(contentItem.PersistedContent); - + //lasty, if it is not valid, add the modelstate to the outgoing object and throw a 403 HandleInvalidModelState(display); @@ -333,8 +336,8 @@ namespace Umbraco.Web.Editors throw new HttpResponseException(Request.CreateValidationErrorResponse(display)); } } - - break; + + break; } return display; @@ -363,7 +366,7 @@ namespace Umbraco.Web.Editors Services.MediaService.EmptyRecycleBin(); return Request.CreateResponse(HttpStatusCode.OK); } - + /// /// Change the sort order for media /// @@ -382,7 +385,7 @@ namespace Umbraco.Web.Editors { return Request.CreateResponse(HttpStatusCode.OK); } - + var mediaService = base.ApplicationContext.Services.MediaService; var sortedMedia = new List(); try @@ -404,7 +407,7 @@ namespace Umbraco.Web.Editors } } - [EnsureUserPermissionForMedia("folder.ParentId")] + [EnsureUserPermissionForMedia("folder.ParentId")] public MediaItemDisplay PostAddFolder(EntityBasic folder) { var mediaService = ApplicationContext.Services.MediaService; @@ -435,7 +438,7 @@ namespace Umbraco.Web.Editors var provider = new MultipartFormDataStreamProvider(root); var result = await Request.Content.ReadAsMultipartAsync(provider); - + //must have a file if (result.FileData.Count == 0) { @@ -448,10 +451,10 @@ namespace Umbraco.Web.Editors { return Request.CreateValidationErrorResponse("The request was not formatted correctly, the currentFolder is not an integer"); } - + //ensure the user has access to this folder by parent id! if (CheckPermissions( - new Dictionary(), + new Dictionary(), Security.CurrentUser, Services.MediaService, parentId) == false) { @@ -462,65 +465,65 @@ namespace Umbraco.Web.Editors Services.TextService.Localize("speechBubbles/invalidUserPermissionsText"), SpeechBubbleIcon.Warning))); } - + var tempFiles = new PostedFiles(); var mediaService = ApplicationContext.Services.MediaService; //in case we pass a path with a folder in it, we will create it and upload media to it. - if (result.FormData.ContainsKey("path")) - { + if (result.FormData.ContainsKey("path")) + { - var folders = result.FormData["path"].Split('/'); + var folders = result.FormData["path"].Split('/'); - for (int i = 0; i < folders.Length - 1; i++) - { - var folderName = folders[i]; - IMedia folderMediaItem; + for (int i = 0; i < folders.Length - 1; i++) + { + var folderName = folders[i]; + IMedia folderMediaItem; - //if uploading directly to media root and not a subfolder - if (parentId == -1) - { - //look for matching folder - folderMediaItem = - mediaService.GetRootMedia().FirstOrDefault(x => x.Name == folderName && x.ContentType.Alias == Constants.Conventions.MediaTypes.Folder); - if (folderMediaItem == null) - { - //if null, create a folder - folderMediaItem = mediaService.CreateMedia(folderName, -1, Constants.Conventions.MediaTypes.Folder); - mediaService.Save(folderMediaItem); - } - } - else - { - //get current parent - var mediaRoot = mediaService.GetById(parentId); + //if uploading directly to media root and not a subfolder + if (parentId == -1) + { + //look for matching folder + folderMediaItem = + mediaService.GetRootMedia().FirstOrDefault(x => x.Name == folderName && x.ContentType.Alias == Constants.Conventions.MediaTypes.Folder); + if (folderMediaItem == null) + { + //if null, create a folder + folderMediaItem = mediaService.CreateMedia(folderName, -1, Constants.Conventions.MediaTypes.Folder); + mediaService.Save(folderMediaItem); + } + } + else + { + //get current parent + var mediaRoot = mediaService.GetById(parentId); - //if the media root is null, something went wrong, we'll abort - if (mediaRoot == null) - return Request.CreateErrorResponse(HttpStatusCode.InternalServerError, - "The folder: " + folderName + " could not be used for storing images, its ID: " + parentId + - " returned null"); + //if the media root is null, something went wrong, we'll abort + if (mediaRoot == null) + return Request.CreateErrorResponse(HttpStatusCode.InternalServerError, + "The folder: " + folderName + " could not be used for storing images, its ID: " + parentId + + " returned null"); - //look for matching folder - folderMediaItem = mediaRoot.Children().FirstOrDefault(x => x.Name == folderName && x.ContentType.Alias == Constants.Conventions.MediaTypes.Folder); - if (folderMediaItem == null) - { - //if null, create a folder - folderMediaItem = mediaService.CreateMedia(folderName, mediaRoot, Constants.Conventions.MediaTypes.Folder); - mediaService.Save(folderMediaItem); - } - } - //set the media root to the folder id so uploaded files will end there. - parentId = folderMediaItem.Id; - } - } + //look for matching folder + folderMediaItem = mediaRoot.Children().FirstOrDefault(x => x.Name == folderName && x.ContentType.Alias == Constants.Conventions.MediaTypes.Folder); + if (folderMediaItem == null) + { + //if null, create a folder + folderMediaItem = mediaService.CreateMedia(folderName, mediaRoot, Constants.Conventions.MediaTypes.Folder); + mediaService.Save(folderMediaItem); + } + } + //set the media root to the folder id so uploaded files will end there. + parentId = folderMediaItem.Id; + } + } - //get the files + //get the files foreach (var file in result.FileData) { var fileName = file.Headers.ContentDisposition.FileName.Trim(new[] { '\"' }); - var ext = fileName.Substring(fileName.LastIndexOf('.')+1).ToLower(); + var ext = fileName.Substring(fileName.LastIndexOf('.') + 1).ToLower(); if (UmbracoConfig.For.UmbracoSettings().Content.DisallowedUploadFiles.Contains(ext) == false) { @@ -570,7 +573,7 @@ namespace Umbraco.Web.Editors { tempFiles.Notifications.Add(new Notification( Services.TextService.Localize("speechBubbles/operationFailedHeader"), - "Cannot upload file " + file.Headers.ContentDisposition.FileName + ", it is not an approved file type", + Services.TextService.Localize("media/disallowedFileType"), SpeechBubbleIcon.Warning)); } } @@ -582,7 +585,7 @@ namespace Umbraco.Web.Editors if (origin.Value == "blueimp") { return Request.CreateResponse(HttpStatusCode.OK, - tempFiles, + tempFiles, //Don't output the angular xsrf stuff, blue imp doesn't like that new JsonMediaTypeFormatter()); } diff --git a/src/Umbraco.Web/Editors/MemberController.cs b/src/Umbraco.Web/Editors/MemberController.cs index 909189b7ad..9d9093486f 100644 --- a/src/Umbraco.Web/Editors/MemberController.cs +++ b/src/Umbraco.Web/Editors/MemberController.cs @@ -73,15 +73,16 @@ namespace Umbraco.Web.Editors get { return Services.MemberService.GetMembershipScenario(); } } - public PagedResult GetPagedResults( + public PagedResult GetPagedResults( int pageNumber = 1, int pageSize = 100, string orderBy = "Name", Direction orderDirection = Direction.Ascending, + bool orderBySystemField = true, string filter = "", string memberTypeAlias = null) { - + if (pageNumber <= 0 || pageSize <= 0) { throw new NotSupportedException("Both pageNumber and pageSize must be greater than zero"); @@ -90,7 +91,9 @@ namespace Umbraco.Web.Editors if (MembershipScenario == MembershipScenario.NativeUmbraco) { long totalRecords; - var members = Services.MemberService.GetAll((pageNumber - 1), pageSize, out totalRecords, orderBy, orderDirection, memberTypeAlias, filter).ToArray(); + var members = Services.MemberService + .GetAll((pageNumber - 1), pageSize, out totalRecords, orderBy, orderDirection, orderBySystemField + , memberTypeAlias, filter).ToArray(); if (totalRecords == 0) { return new PagedResult(0, 0, 0); @@ -103,7 +106,24 @@ namespace Umbraco.Web.Editors else { int totalRecords; - var members = _provider.GetAllUsers((pageNumber - 1), pageSize, out totalRecords); + + MembershipUserCollection members; + if (filter.IsNullOrWhiteSpace()) + { + members = _provider.GetAllUsers((pageNumber - 1), pageSize, out totalRecords); + } + else + { + //we need to search! + + //try by name first + members = _provider.FindUsersByName(filter, (pageNumber - 1), pageSize, out totalRecords); + if (totalRecords == 0) + { + //try by email then + members = _provider.FindUsersByEmail(filter, (pageNumber - 1), pageSize, out totalRecords); + } + } if (totalRecords == 0) { return new PagedResult(0, 0, 0); @@ -114,7 +134,7 @@ namespace Umbraco.Web.Editors .Select(Mapper.Map); return pagedResult; } - + } /// @@ -162,23 +182,23 @@ namespace Umbraco.Web.Editors return Mapper.Map(foundMember); case MembershipScenario.CustomProviderWithUmbracoLink: - //TODO: Support editing custom properties for members with a custom membership provider here. + //TODO: Support editing custom properties for members with a custom membership provider here. - //foundMember = Services.MemberService.GetByKey(key); - //if (foundMember == null) - //{ - // HandleContentNotFound(key); - //} - //foundMembershipMember = Membership.GetUser(key, false); - //if (foundMembershipMember == null) - //{ - // HandleContentNotFound(key); - //} + //foundMember = Services.MemberService.GetByKey(key); + //if (foundMember == null) + //{ + // HandleContentNotFound(key); + //} + //foundMembershipMember = Membership.GetUser(key, false); + //if (foundMembershipMember == null) + //{ + // HandleContentNotFound(key); + //} - //display = Mapper.Map(foundMembershipMember); - ////map the name over - //display.Name = foundMember.Name; - //return display; + //display = Mapper.Map(foundMembershipMember); + ////map the name over + //display.Name = foundMember.Name; + //return display; case MembershipScenario.StandaloneCustomProvider: default: @@ -219,7 +239,7 @@ namespace Umbraco.Web.Editors emptyContent.AdditionalData["NewPassword"] = Membership.GeneratePassword(Membership.MinRequiredPasswordLength, Membership.MinRequiredNonAlphanumericCharacters); return Mapper.Map(emptyContent); case MembershipScenario.CustomProviderWithUmbracoLink: - //TODO: Support editing custom properties for members with a custom membership provider here. + //TODO: Support editing custom properties for members with a custom membership provider here. case MembershipScenario.StandaloneCustomProvider: default: @@ -275,7 +295,7 @@ namespace Umbraco.Web.Editors { throw new NotSupportedException("Currently the member editor does not support providers that have RequiresQuestionAndAnswer specified"); } - + //We're gonna look up the current roles now because the below code can cause // events to be raised and developers could be manually adding roles to members in // their handlers. If we don't look this up now there's a chance we'll just end up @@ -324,7 +344,7 @@ namespace Umbraco.Web.Editors //create/save the IMember Services.MemberService.Save(contentItem.PersistedContent); } - + //Now let's do the role provider stuff - now that we've saved the content item (that is important since // if we are changing the username, it must be persisted before looking up the member roles). if (rolesToRemove.Any()) @@ -504,7 +524,7 @@ namespace Umbraco.Web.Editors private void RefetchMemberData(MemberSave contentItem, LookupType lookup) { var currProps = contentItem.PersistedContent.Properties.ToArray(); - + switch (MembershipScenario) { case MembershipScenario.NativeUmbraco: @@ -512,11 +532,11 @@ namespace Umbraco.Web.Editors { case LookupType.ByKey: //Go and re-fetch the persisted item - contentItem.PersistedContent = Services.MemberService.GetByKey(contentItem.Key); + contentItem.PersistedContent = Services.MemberService.GetByKey(contentItem.Key); break; case LookupType.ByUserName: contentItem.PersistedContent = Services.MemberService.GetByUsername(contentItem.Username.Trim()); - break; + break; } break; case MembershipScenario.CustomProviderWithUmbracoLink: @@ -524,14 +544,14 @@ namespace Umbraco.Web.Editors default: var membershipUser = _provider.GetUser(contentItem.Key, false); //Go and re-fetch the persisted item - contentItem.PersistedContent = Mapper.Map(membershipUser); + contentItem.PersistedContent = Mapper.Map(membershipUser); break; } UpdateName(contentItem); //re-assign the mapped values that are not part of the membership provider properties. - var builtInAliases = Constants.Conventions.Member.GetStandardPropertyTypeStubs().Select(x => x.Key).ToArray(); + var builtInAliases = Constants.Conventions.Member.GetStandardPropertyTypeStubs().Select(x => x.Key).ToArray(); foreach (var p in contentItem.PersistedContent.Properties) { var valueMapped = currProps.SingleOrDefault(x => x.Alias == p.Alias); @@ -542,7 +562,7 @@ namespace Umbraco.Web.Editors p.TagSupport.Enable = valueMapped.TagSupport.Enable; p.TagSupport.Tags = valueMapped.TagSupport.Tags; } - } + } } /// @@ -595,7 +615,7 @@ namespace Umbraco.Web.Editors contentItem.IsApproved, Guid.NewGuid(), //since it's the umbraco provider, the user key here doesn't make any difference out status); - + break; case MembershipScenario.CustomProviderWithUmbracoLink: //We are using a custom membership provider, we'll create an empty IMember first to get the unique id to use @@ -618,7 +638,7 @@ namespace Umbraco.Web.Editors case MembershipScenario.StandaloneCustomProvider: // we don't have a member type to use so we will just create the basic membership user with the provider with no // link back to the umbraco data - + var newKey = Guid.NewGuid(); //TODO: We are not supporting q/a - passing in empty here membershipUser = _provider.CreateUser( @@ -628,9 +648,9 @@ namespace Umbraco.Web.Editors "TEMP", //some membership provider's require something here even if q/a is disabled! "TEMP", //some membership provider's require something here even if q/a is disabled! contentItem.IsApproved, - newKey, + newKey, out status); - + break; default: throw new ArgumentOutOfRangeException(); @@ -685,12 +705,12 @@ namespace Umbraco.Web.Editors break; case MembershipCreateStatus.InvalidProviderUserKey: ModelState.AddPropertyError( - //specify 'default' just so that it shows up as a notification - is not assigned to a property + //specify 'default' just so that it shows up as a notification - is not assigned to a property new ValidationResult("Invalid provider user key"), "default"); break; case MembershipCreateStatus.DuplicateProviderUserKey: ModelState.AddPropertyError( - //specify 'default' just so that it shows up as a notification - is not assigned to a property + //specify 'default' just so that it shows up as a notification - is not assigned to a property new ValidationResult("Duplicate provider user key"), "default"); break; case MembershipCreateStatus.ProviderError: diff --git a/src/Umbraco.Web/HtmlHelperBackOfficeExtensions.cs b/src/Umbraco.Web/HtmlHelperBackOfficeExtensions.cs index 3f38ae35ec..71fc3be8f1 100644 --- a/src/Umbraco.Web/HtmlHelperBackOfficeExtensions.cs +++ b/src/Umbraco.Web/HtmlHelperBackOfficeExtensions.cs @@ -9,9 +9,12 @@ using Newtonsoft.Json; using Umbraco.Core; using Umbraco.Core.Configuration; using Umbraco.Web.Editors; +using Umbraco.Web.Models; namespace Umbraco.Web { + using Umbraco.Core.Configuration; + /// /// HtmlHelper extensions for the back office /// @@ -43,6 +46,9 @@ namespace Umbraco.Web ""serverVarsJs"": """ + uri.GetUrlWithCacheBust("ServerVariables", "BackOffice") + @""", ""externalLoginsUrl"": """ + externalLoginsUrl + @""" }, + ""umbracoSettings"": { + ""allowPasswordReset"": " + (UmbracoConfig.For.UmbracoSettings().Security.AllowPasswordReset ? "true" : "false") + @" + }, ""application"": { ""applicationPath"": """ + html.ViewContext.HttpContext.Request.ApplicationPath + @""", ""version"": """ + version + @""", @@ -56,12 +62,12 @@ namespace Umbraco.Web } /// - /// Used to render the script that will pass in the angular externalLoginInfo service on page load + /// Used to render the script that will pass in the angular "externalLoginInfo" service/value on page load /// /// /// /// - public static IHtmlString AngularExternalLoginInfoValuesScript(this HtmlHelper html, IEnumerable externalLoginErrors) + public static IHtmlString AngularValueExternalLoginInfoScript(this HtmlHelper html, IEnumerable externalLoginErrors) { var loginProviders = html.ViewContext.HttpContext.GetOwinContext().Authentication.GetExternalAuthenticationTypes() .Where(p => p.Properties.ContainsKey("UmbracoBackOffice")) @@ -93,5 +99,38 @@ namespace Umbraco.Web return html.Raw(sb.ToString()); } + + /// + /// Used to render the script that will pass in the angular "resetPasswordCodeInfo" service/value on page load + /// + /// + /// + /// + public static IHtmlString AngularValueResetPasswordCodeInfoScript(this HtmlHelper html, object val) + { + var sb = new StringBuilder(); + sb.AppendLine(); + sb.AppendLine(@"var errors = [];"); + + var errors = val as IEnumerable; + if (errors != null) + { + foreach (var error in errors) + { + sb.AppendFormat(@"errors.push(""{0}"");", error).AppendLine(); + } + } + + var resetCodeModel = val as ValidatePasswordResetCodeModel; + + + sb.AppendLine(@"app.value(""resetPasswordCodeInfo"", {"); + sb.AppendLine(@"errors: errors,"); + sb.Append(@"resetCodeModel: "); + sb.AppendLine(JsonConvert.SerializeObject(resetCodeModel)); + sb.AppendLine(@"});"); + + return html.Raw(sb.ToString()); + } } } \ No newline at end of file diff --git a/src/Umbraco.Web/Install/InstallSteps/MajorVersion7UpgradeReport.cs b/src/Umbraco.Web/Install/InstallSteps/MajorVersion7UpgradeReport.cs index f1903f96a4..74c3c683c4 100644 --- a/src/Umbraco.Web/Install/InstallSteps/MajorVersion7UpgradeReport.cs +++ b/src/Umbraco.Web/Install/InstallSteps/MajorVersion7UpgradeReport.cs @@ -1,6 +1,7 @@ using System; using System.Collections.Generic; using System.Linq; +using NPoco; using Umbraco.Core; using Umbraco.Core.Configuration; using Umbraco.Core.Persistence; diff --git a/src/Umbraco.Web/Models/Mapping/ContentModelMapper.cs b/src/Umbraco.Web/Models/Mapping/ContentModelMapper.cs index cd3df47b16..d9f1f25189 100644 --- a/src/Umbraco.Web/Models/Mapping/ContentModelMapper.cs +++ b/src/Umbraco.Web/Models/Mapping/ContentModelMapper.cs @@ -172,19 +172,23 @@ namespace Umbraco.Web.Models.Mapping Value = localizedText.UmbracoDictionaryTranslate(display.ContentTypeName), View = PropertyEditorResolver.Current.GetByAlias(Constants.PropertyEditors.NoEditAlias).ValueEditor.View }, - new ContentPropertyDisplay + new ContentPropertyDisplay { Alias = string.Format("{0}releasedate", Constants.PropertyEditors.InternalGenericPropertiesPrefix), Label = localizedText.Localize("content/releaseDate"), Value = display.ReleaseDate.HasValue ? display.ReleaseDate.Value.ToIsoString() : null, - View = "datepicker" //TODO: Hard coding this because the templatepicker doesn't necessarily need to be a resolvable (real) property editor - }, + //Not editible for people without publish permission (U4-287) + View = display.AllowedActions.Contains('P') ? "datepicker" : PropertyEditorResolver.Current.GetByAlias(Constants.PropertyEditors.NoEditAlias).ValueEditor.View + //TODO: Fix up hard coded datepicker + } , new ContentPropertyDisplay { Alias = string.Format("{0}expiredate", Constants.PropertyEditors.InternalGenericPropertiesPrefix), Label = localizedText.Localize("content/unpublishDate"), Value = display.ExpireDate.HasValue ? display.ExpireDate.Value.ToIsoString() : null, - View = "datepicker" //TODO: Hard coding this because the templatepicker doesn't necessarily need to be a resolvable (real) property editor + //Not editible for people without publish permission (U4-287) + View = display.AllowedActions.Contains('P') ? "datepicker" : PropertyEditorResolver.Current.GetByAlias(Constants.PropertyEditors.NoEditAlias).ValueEditor.View + //TODO: Fix up hard coded datepicker }, new ContentPropertyDisplay { diff --git a/src/Umbraco.Web/Models/RequestPasswordResetModel.cs b/src/Umbraco.Web/Models/RequestPasswordResetModel.cs new file mode 100644 index 0000000000..0ea173bfd6 --- /dev/null +++ b/src/Umbraco.Web/Models/RequestPasswordResetModel.cs @@ -0,0 +1,14 @@ +using System.ComponentModel.DataAnnotations; +using System.Runtime.Serialization; + +namespace Umbraco.Web.Models +{ + + [DataContract(Name = "requestPasswordReset", Namespace = "")] + public class RequestPasswordResetModel + { + [Required] + [DataMember(Name = "email", IsRequired = true)] + public string Email { get; set; } + } +} diff --git a/src/Umbraco.Web/Models/SetPasswordModel.cs b/src/Umbraco.Web/Models/SetPasswordModel.cs new file mode 100644 index 0000000000..02d0e4f901 --- /dev/null +++ b/src/Umbraco.Web/Models/SetPasswordModel.cs @@ -0,0 +1,21 @@ +using System.ComponentModel.DataAnnotations; +using System.Runtime.Serialization; + +namespace Umbraco.Web.Models +{ + [DataContract(Name = "setPassword", Namespace = "")] + public class SetPasswordModel + { + [Required] + [DataMember(Name = "userId", IsRequired = true)] + public int UserId { get; set; } + + [Required] + [DataMember(Name = "password", IsRequired = true)] + public string Password { get; set; } + + [Required] + [DataMember(Name = "resetCode", IsRequired = true)] + public string ResetCode { get; set; } + } +} diff --git a/src/Umbraco.Web/Models/Trees/DisableUser.cs b/src/Umbraco.Web/Models/Trees/DisableUser.cs new file mode 100644 index 0000000000..b28b2043ab --- /dev/null +++ b/src/Umbraco.Web/Models/Trees/DisableUser.cs @@ -0,0 +1,15 @@ +namespace Umbraco.Web.Models.Trees +{ + /// + /// Represents the disable user menu item + /// + [ActionMenuItem("umbracoMenuActions")] + public sealed class DisableUser : ActionMenuItem + { + public DisableUser() + { + Alias = "disable"; + Icon = "remove"; + } + } +} \ No newline at end of file diff --git a/src/Umbraco.Web/Models/Trees/MenuItem.cs b/src/Umbraco.Web/Models/Trees/MenuItem.cs index 8e0f581e78..e1a656857a 100644 --- a/src/Umbraco.Web/Models/Trees/MenuItem.cs +++ b/src/Umbraco.Web/Models/Trees/MenuItem.cs @@ -191,7 +191,25 @@ namespace Umbraco.Web.Models.Trees view => LaunchDialogView( view, ApplicationContext.Current.Services.TextService.Localize("defaultdialogs/confirmdelete") + " '" + (item == null ? "" : item.Name) + "' ?")); - } + } + + internal void ConvertLegacyFileSystemMenuItem(string path, string nodeType, string currentSection) + { + //First try to get a URL/title from the legacy action, + // if that doesn't work, try to get the legacy confirm view + + //in some edge cases, item can be null so we'll just convert those to "-1" and "" for id and name since these edge cases don't need that. + Attempt + .Try(LegacyTreeDataConverter.GetUrlAndTitleFromLegacyAction(Action, + path, + nodeType, + path, currentSection), + action => LaunchDialogUrl(action.Url, action.DialogTitle)) + .OnFailure(() => LegacyTreeDataConverter.GetLegacyConfirmView(Action, currentSection), + view => LaunchDialogView( + view, + ApplicationContext.Current.Services.TextService.Localize("defaultdialogs/confirmdelete") + " '" + path + "' ?")); + } #endregion } diff --git a/src/Umbraco.Web/Models/ValidatePasswordResetCodeModel.cs b/src/Umbraco.Web/Models/ValidatePasswordResetCodeModel.cs new file mode 100644 index 0000000000..cba92eeff7 --- /dev/null +++ b/src/Umbraco.Web/Models/ValidatePasswordResetCodeModel.cs @@ -0,0 +1,17 @@ +using System.ComponentModel.DataAnnotations; +using System.Runtime.Serialization; + +namespace Umbraco.Web.Models +{ + [DataContract(Name = "validatePasswordReset", Namespace = "")] + public class ValidatePasswordResetCodeModel + { + [Required] + [DataMember(Name = "userId", IsRequired = true)] + public int UserId { get; set; } + + [Required] + [DataMember(Name = "resetCode", IsRequired = true)] + public string ResetCode { get; set; } + } +} diff --git a/src/Umbraco.Web/Mvc/DisableBrowserCacheAttribute.cs b/src/Umbraco.Web/Mvc/DisableBrowserCacheAttribute.cs index c1b5b88643..c1c2186171 100644 --- a/src/Umbraco.Web/Mvc/DisableBrowserCacheAttribute.cs +++ b/src/Umbraco.Web/Mvc/DisableBrowserCacheAttribute.cs @@ -13,6 +13,13 @@ namespace Umbraco.Web.Mvc { base.OnActionExecuted(filterContext); + // could happens if exception (but afaik this wouldn't happen in MVC) + if (filterContext.HttpContext == null || filterContext.HttpContext.Response == null || + filterContext.HttpContext.Response.Cache == null) + { + return; + } + filterContext.HttpContext.Response.Cache.SetCacheability(HttpCacheability.NoCache); filterContext.HttpContext.Response.Cache.SetMaxAge(TimeSpan.Zero); filterContext.HttpContext.Response.Cache.SetRevalidation(HttpCacheRevalidation.AllCaches); diff --git a/src/Umbraco.Web/Mvc/EnsurePartialViewMacroViewContextFilterAttribute.cs b/src/Umbraco.Web/Mvc/EnsurePartialViewMacroViewContextFilterAttribute.cs index afd40330ea..625b67b2b2 100644 --- a/src/Umbraco.Web/Mvc/EnsurePartialViewMacroViewContextFilterAttribute.cs +++ b/src/Umbraco.Web/Mvc/EnsurePartialViewMacroViewContextFilterAttribute.cs @@ -21,20 +21,46 @@ namespace Umbraco.Web.Mvc /// internal class EnsurePartialViewMacroViewContextFilterAttribute : ActionFilterAttribute { + /// + /// Ensures the custom ViewContext datatoken is set before the RenderController action is invoked, + /// this ensures that any calls to GetPropertyValue with regards to RTE or Grid editors can still + /// render any PartialViewMacro with a form and maintain ModelState + /// + /// public override void OnActionExecuting(ActionExecutingContext filterContext) { //ignore anything that is not IRenderController - if ((filterContext.Controller is IRenderController) == false) + if ((filterContext.Controller is IRenderController) == false && filterContext.IsChildAction == false) return; + SetViewContext(filterContext); + } + + /// + /// Ensures that the custom ViewContext datatoken is set after the RenderController action is invoked, + /// this ensures that any custom ModelState that may have been added in the RenderController itself is + /// passed onwards in case it is required when rendering a PartialViewMacro with a form + /// + /// The filter context. + public override void OnResultExecuting(ResultExecutingContext filterContext) + { + //ignore anything that is not IRenderController + if ((filterContext.Controller is IRenderController) == false && filterContext.IsChildAction == false) + return; + + SetViewContext(filterContext); + } + + private void SetViewContext(ControllerContext controllerContext) + { var viewCtx = new ViewContext( - filterContext.Controller.ControllerContext, - new DummyView(), - filterContext.Controller.ViewData, filterContext.Controller.TempData, + controllerContext, + new DummyView(), + controllerContext.Controller.ViewData, controllerContext.Controller.TempData, new StringWriter()); //set the special data token - filterContext.RequestContext.RouteData.DataTokens[Constants.DataTokenCurrentViewContext] = viewCtx; + controllerContext.RequestContext.RouteData.DataTokens[Constants.DataTokenCurrentViewContext] = viewCtx; } private class DummyView : IView diff --git a/src/Umbraco.Web/Mvc/UmbracoViewPageOfTModel.cs b/src/Umbraco.Web/Mvc/UmbracoViewPageOfTModel.cs index 0c45c24c4a..3d1a41d289 100644 --- a/src/Umbraco.Web/Mvc/UmbracoViewPageOfTModel.cs +++ b/src/Umbraco.Web/Mvc/UmbracoViewPageOfTModel.cs @@ -120,9 +120,13 @@ namespace Umbraco.Web.Mvc base.InitializePage(); if (ViewContext.IsChildAction == false) { - //always ensure the special data token is set - this is used purely for partial view macros that contain forms - // and mostly just when rendered within the RTE - ViewContext.RouteData.DataTokens[Constants.DataTokenCurrentViewContext] = ViewContext; + //this is used purely for partial view macros that contain forms + // and mostly just when rendered within the RTE - This should already be set with the + // EnsurePartialViewMacroViewContextFilterAttribute + if (ViewContext.RouteData.DataTokens.ContainsKey(Constants.DataTokenCurrentViewContext) == false) + { + ViewContext.RouteData.DataTokens.Add(Constants.DataTokenCurrentViewContext, ViewContext); + } } } diff --git a/src/Umbraco.Web/OwinMiddlewareConfiguredEventArgs.cs b/src/Umbraco.Web/OwinMiddlewareConfiguredEventArgs.cs new file mode 100644 index 0000000000..03c2dc631d --- /dev/null +++ b/src/Umbraco.Web/OwinMiddlewareConfiguredEventArgs.cs @@ -0,0 +1,15 @@ +using System; +using Owin; + +namespace Umbraco.Web +{ + public class OwinMiddlewareConfiguredEventArgs : EventArgs + { + public OwinMiddlewareConfiguredEventArgs(IAppBuilder appBuilder) + { + AppBuilder = appBuilder; + } + + public IAppBuilder AppBuilder { get; private set; } + } +} \ No newline at end of file diff --git a/src/Umbraco.Web/PropertyEditors/CheckBoxListPropertyEditor.cs b/src/Umbraco.Web/PropertyEditors/CheckBoxListPropertyEditor.cs index 2cebd665cd..e1b72f0ad4 100644 --- a/src/Umbraco.Web/PropertyEditors/CheckBoxListPropertyEditor.cs +++ b/src/Umbraco.Web/PropertyEditors/CheckBoxListPropertyEditor.cs @@ -1,6 +1,7 @@ using Umbraco.Core; using Umbraco.Core.Logging; using Umbraco.Core.PropertyEditors; +using Umbraco.Core.Services; namespace Umbraco.Web.PropertyEditors { @@ -15,11 +16,14 @@ namespace Umbraco.Web.PropertyEditors [PropertyEditor(Constants.PropertyEditors.CheckBoxListAlias, "Checkbox list", "checkboxlist", Icon="icon-bulleted-list", Group="lists")] public class CheckBoxListPropertyEditor : PropertyEditor { + private readonly ILocalizedTextService _textService; + /// /// The constructor will setup the property editor based on the attribute if one is found /// - public CheckBoxListPropertyEditor(ILogger logger) : base(logger) + public CheckBoxListPropertyEditor(ILogger logger, ILocalizedTextService textService) : base(logger) { + _textService = textService; } /// @@ -31,7 +35,7 @@ namespace Umbraco.Web.PropertyEditors /// protected override PreValueEditor CreatePreValueEditor() { - return new ValueListPreValueEditor(); + return new ValueListPreValueEditor(_textService); } /// diff --git a/src/Umbraco.Web/PropertyEditors/ColorListPreValueEditor.cs b/src/Umbraco.Web/PropertyEditors/ColorListPreValueEditor.cs index e7750c4c65..e9e721c108 100644 --- a/src/Umbraco.Web/PropertyEditors/ColorListPreValueEditor.cs +++ b/src/Umbraco.Web/PropertyEditors/ColorListPreValueEditor.cs @@ -6,13 +6,14 @@ using Newtonsoft.Json.Linq; using Umbraco.Core; using Umbraco.Core.Models; using Umbraco.Core.PropertyEditors; +using Umbraco.Core.Services; namespace Umbraco.Web.PropertyEditors { internal class ColorListPreValueEditor : ValueListPreValueEditor { - public ColorListPreValueEditor() + public ColorListPreValueEditor(ILocalizedTextService textService) : base(textService) { var field = Fields.First(); diff --git a/src/Umbraco.Web/PropertyEditors/ColorPickerPropertyEditor.cs b/src/Umbraco.Web/PropertyEditors/ColorPickerPropertyEditor.cs index 95d2c5f07e..3d2beb64fb 100644 --- a/src/Umbraco.Web/PropertyEditors/ColorPickerPropertyEditor.cs +++ b/src/Umbraco.Web/PropertyEditors/ColorPickerPropertyEditor.cs @@ -1,17 +1,21 @@ using Umbraco.Core; using Umbraco.Core.Logging; using Umbraco.Core.PropertyEditors; +using Umbraco.Core.Services; namespace Umbraco.Web.PropertyEditors { [PropertyEditor(Constants.PropertyEditors.ColorPickerAlias, "Color Picker", "colorpicker", Icon="icon-colorpicker", Group="Pickers")] public class ColorPickerPropertyEditor : PropertyEditor { + private readonly ILocalizedTextService _textService; + /// /// The constructor will setup the property editor based on the attribute if one is found /// - public ColorPickerPropertyEditor(ILogger logger) : base(logger) + public ColorPickerPropertyEditor(ILogger logger, ILocalizedTextService textService) : base(logger) { + _textService = textService; } /// @@ -23,7 +27,7 @@ namespace Umbraco.Web.PropertyEditors /// protected override PreValueEditor CreatePreValueEditor() { - return new ColorListPreValueEditor(); + return new ColorListPreValueEditor(_textService); } } diff --git a/src/Umbraco.Web/PropertyEditors/DropDownMultiplePropertyEditor.cs b/src/Umbraco.Web/PropertyEditors/DropDownMultiplePropertyEditor.cs index e7cf1bb87b..2728f5c86b 100644 --- a/src/Umbraco.Web/PropertyEditors/DropDownMultiplePropertyEditor.cs +++ b/src/Umbraco.Web/PropertyEditors/DropDownMultiplePropertyEditor.cs @@ -2,6 +2,7 @@ using Newtonsoft.Json; using Umbraco.Core; using Umbraco.Core.Logging; using Umbraco.Core.PropertyEditors; +using Umbraco.Core.Services; namespace Umbraco.Web.PropertyEditors { @@ -21,7 +22,7 @@ namespace Umbraco.Web.PropertyEditors /// /// The constructor will setup the property editor based on the attribute if one is found /// - public DropDownMultiplePropertyEditor(ILogger logger) : base(logger) + public DropDownMultiplePropertyEditor(ILogger logger, ILocalizedTextService textService) : base(logger, textService) { } diff --git a/src/Umbraco.Web/PropertyEditors/DropDownMultipleWithKeysPropertyEditor.cs b/src/Umbraco.Web/PropertyEditors/DropDownMultipleWithKeysPropertyEditor.cs index 9540c4fdc5..f16d9872ec 100644 --- a/src/Umbraco.Web/PropertyEditors/DropDownMultipleWithKeysPropertyEditor.cs +++ b/src/Umbraco.Web/PropertyEditors/DropDownMultipleWithKeysPropertyEditor.cs @@ -3,6 +3,7 @@ using Umbraco.Core; using Umbraco.Core.Logging; using Umbraco.Core.Models; using Umbraco.Core.PropertyEditors; +using Umbraco.Core.Services; namespace Umbraco.Web.PropertyEditors { @@ -16,11 +17,14 @@ namespace Umbraco.Web.PropertyEditors [PropertyEditor(Constants.PropertyEditors.DropdownlistMultiplePublishKeysAlias, "Dropdown list multiple, publish keys", "dropdown", Group = "lists", Icon = "icon-bulleted-list")] public class DropDownMultipleWithKeysPropertyEditor : DropDownPropertyEditor { + private readonly ILocalizedTextService _textService; + /// /// The constructor will setup the property editor based on the attribute if one is found /// - public DropDownMultipleWithKeysPropertyEditor(ILogger logger) : base(logger) + public DropDownMultipleWithKeysPropertyEditor(ILogger logger, ILocalizedTextService textService) : base(logger, textService) { + _textService = textService; } protected override PropertyValueEditor CreateValueEditor() @@ -30,7 +34,7 @@ namespace Umbraco.Web.PropertyEditors protected override PreValueEditor CreatePreValueEditor() { - return new DropDownMultiplePreValueEditor(); + return new DropDownMultiplePreValueEditor(_textService); } /// @@ -42,7 +46,7 @@ namespace Umbraco.Web.PropertyEditors /// internal class DropDownMultiplePreValueEditor : ValueListPreValueEditor { - public DropDownMultiplePreValueEditor() + public DropDownMultiplePreValueEditor(ILocalizedTextService textService) : base(textService) { //add the multiple field, we'll make it hidden so it is not seen in the pre-value editor Fields.Add(new PreValueField diff --git a/src/Umbraco.Web/PropertyEditors/DropDownPropertyEditor.cs b/src/Umbraco.Web/PropertyEditors/DropDownPropertyEditor.cs index 3607a8b5fa..4981e88412 100644 --- a/src/Umbraco.Web/PropertyEditors/DropDownPropertyEditor.cs +++ b/src/Umbraco.Web/PropertyEditors/DropDownPropertyEditor.cs @@ -5,6 +5,7 @@ using Umbraco.Core.Logging; using Umbraco.Core.PropertyEditors; using umbraco; using ClientDependency.Core; +using Umbraco.Core.Services; using Constants = Umbraco.Core.Constants; namespace Umbraco.Web.PropertyEditors @@ -23,7 +24,7 @@ namespace Umbraco.Web.PropertyEditors /// /// The constructor will setup the property editor based on the attribute if one is found /// - public DropDownPropertyEditor(ILogger logger) : base(logger) + public DropDownPropertyEditor(ILogger logger, ILocalizedTextService textService) : base(logger, textService) { } diff --git a/src/Umbraco.Web/PropertyEditors/DropDownWithKeysPropertyEditor.cs b/src/Umbraco.Web/PropertyEditors/DropDownWithKeysPropertyEditor.cs index b4138d170a..2192af8d4f 100644 --- a/src/Umbraco.Web/PropertyEditors/DropDownWithKeysPropertyEditor.cs +++ b/src/Umbraco.Web/PropertyEditors/DropDownWithKeysPropertyEditor.cs @@ -1,6 +1,7 @@ using Umbraco.Core; using Umbraco.Core.Logging; using Umbraco.Core.PropertyEditors; +using Umbraco.Core.Services; namespace Umbraco.Web.PropertyEditors { @@ -15,11 +16,14 @@ namespace Umbraco.Web.PropertyEditors [PropertyEditor(Constants.PropertyEditors.DropdownlistPublishingKeysAlias, "Dropdown list, publishing keys", "dropdown", ValueType = "INT", Group = "lists", Icon = "icon-indent")] public class DropDownWithKeysPropertyEditor : PropertyEditor { + private readonly ILocalizedTextService _textService; + /// /// The constructor will setup the property editor based on the attribute if one is found /// - public DropDownWithKeysPropertyEditor(ILogger logger) : base(logger) + public DropDownWithKeysPropertyEditor(ILogger logger, ILocalizedTextService textService) : base(logger) { + _textService = textService; } /// @@ -28,7 +32,7 @@ namespace Umbraco.Web.PropertyEditors /// protected override PreValueEditor CreatePreValueEditor() { - return new ValueListPreValueEditor(); + return new ValueListPreValueEditor(_textService); } } } \ No newline at end of file diff --git a/src/Umbraco.Web/PropertyEditors/FileUploadPropertyEditor.cs b/src/Umbraco.Web/PropertyEditors/FileUploadPropertyEditor.cs index 9b4e722b30..809716af62 100644 --- a/src/Umbraco.Web/PropertyEditors/FileUploadPropertyEditor.cs +++ b/src/Umbraco.Web/PropertyEditors/FileUploadPropertyEditor.cs @@ -24,14 +24,17 @@ namespace Umbraco.Web.PropertyEditors { private readonly MediaFileSystem _mediaFileSystem; private readonly IContentSection _contentSettings; + private readonly ILocalizedTextService _textService; - public FileUploadPropertyEditor(ILogger logger, MediaFileSystem mediaFileSystem, IContentSection contentSettings) + public FileUploadPropertyEditor(ILogger logger, MediaFileSystem mediaFileSystem, IContentSection contentSettings, ILocalizedTextService textService) : base(logger) { if (mediaFileSystem == null) throw new ArgumentNullException("mediaFileSystem"); if (contentSettings == null) throw new ArgumentNullException("contentSettings"); + if (textService == null) throw new ArgumentNullException("textService"); _mediaFileSystem = mediaFileSystem; _contentSettings = contentSettings; + _textService = textService; MemberService.Deleted += (sender, args) => args.MediaFilesToDelete.AddRange(ServiceDeleted(args.DeletedEntities.Cast())); } @@ -49,7 +52,7 @@ namespace Umbraco.Web.PropertyEditors protected override PreValueEditor CreatePreValueEditor() { - return new FileUploadPreValueEditor(); + return new FileUploadPreValueEditor(_textService); } /// @@ -172,8 +175,8 @@ namespace Umbraco.Web.PropertyEditors /// internal class FileUploadPreValueEditor : ValueListPreValueEditor { - public FileUploadPreValueEditor() - : base() + public FileUploadPreValueEditor(ILocalizedTextService textService) + : base(textService) { var field = Fields.First(); field.Description = "Enter a max width/height for each thumbnail"; diff --git a/src/Umbraco.Web/PropertyEditors/RadioButtonsPropertyEditor.cs b/src/Umbraco.Web/PropertyEditors/RadioButtonsPropertyEditor.cs index 24c3a275fb..8ac6bff69e 100644 --- a/src/Umbraco.Web/PropertyEditors/RadioButtonsPropertyEditor.cs +++ b/src/Umbraco.Web/PropertyEditors/RadioButtonsPropertyEditor.cs @@ -1,6 +1,7 @@ using Umbraco.Core; using Umbraco.Core.Logging; using Umbraco.Core.PropertyEditors; +using Umbraco.Core.Services; namespace Umbraco.Web.PropertyEditors { @@ -18,7 +19,7 @@ namespace Umbraco.Web.PropertyEditors /// /// The constructor will setup the property editor based on the attribute if one is found /// - public RadioButtonsPropertyEditor(ILogger logger) : base(logger) + public RadioButtonsPropertyEditor(ILogger logger, ILocalizedTextService textService) : base(logger, textService) { } } diff --git a/src/Umbraco.Web/PropertyEditors/RelatedLinksPropertyEditor.cs b/src/Umbraco.Web/PropertyEditors/RelatedLinksPropertyEditor.cs index c45697e912..4dd31f558b 100644 --- a/src/Umbraco.Web/PropertyEditors/RelatedLinksPropertyEditor.cs +++ b/src/Umbraco.Web/PropertyEditors/RelatedLinksPropertyEditor.cs @@ -18,5 +18,15 @@ namespace Umbraco.Web.PropertyEditors public RelatedLinksPropertyEditor(ILogger logger) : base(logger) { } + protected override PreValueEditor CreatePreValueEditor() + { + return new RelatedLinksPreValueEditor(); + } + + internal class RelatedLinksPreValueEditor : PreValueEditor + { + [PreValueField("max", "Maximum number of links", "number", Description = "Enter the maximum amount of links to be added, enter 0 for unlimited")] + public int Maximum { get; set; } + } } } diff --git a/src/Umbraco.Web/PropertyEditors/ValueListPreValueEditor.cs b/src/Umbraco.Web/PropertyEditors/ValueListPreValueEditor.cs index 41c45efb98..e11a969bfe 100644 --- a/src/Umbraco.Web/PropertyEditors/ValueListPreValueEditor.cs +++ b/src/Umbraco.Web/PropertyEditors/ValueListPreValueEditor.cs @@ -22,9 +22,11 @@ namespace Umbraco.Web.PropertyEditors /// internal class ValueListPreValueEditor : PreValueEditor { + private readonly ILocalizedTextService _textService; - public ValueListPreValueEditor() + public ValueListPreValueEditor(ILocalizedTextService textService) { + _textService = textService; Fields.AddRange(CreatePreValueFields()); } @@ -46,7 +48,7 @@ namespace Umbraco.Web.PropertyEditors //It's also important to note that by default the dropdown angular controller is expecting the // config options to come in with a property called 'items' Key = "items", - Name = ApplicationContext.Current.Services.TextService.Localize("editdatatype/addPrevalue"), + Name = _textService.Localize("editdatatype/addPrevalue"), // todo: inject View = "multivalues" } }; diff --git a/src/Umbraco.Web/PublishedContentExtensions.cs b/src/Umbraco.Web/PublishedContentExtensions.cs index 197175366e..578aab2755 100644 --- a/src/Umbraco.Web/PublishedContentExtensions.cs +++ b/src/Umbraco.Web/PublishedContentExtensions.cs @@ -1201,6 +1201,7 @@ namespace Umbraco.Web /// Enumerates bottom-up ie walking up the tree (parent, grand-parent, etc). internal static IEnumerable EnumerateAncestors(this IPublishedContent content, bool orSelf) { + if (content == null) throw new ArgumentNullException("content"); if (orSelf) yield return content; while ((content = content.Parent) != null) yield return content; @@ -1373,6 +1374,7 @@ namespace Umbraco.Web internal static IEnumerable EnumerateDescendants(this IPublishedContent content, bool orSelf) { + if (content == null) throw new ArgumentNullException("content"); if (orSelf) yield return content; foreach (var child in content.Children) @@ -1707,6 +1709,7 @@ namespace Umbraco.Web public static T Parent(this IPublishedContent content) where T : class, IPublishedContent { + if (content == null) throw new ArgumentNullException("content"); return content.Parent as T; } @@ -1724,9 +1727,10 @@ namespace Umbraco.Web /// This method exists for consistency, it is the same as calling content.Children as a property. /// public static IEnumerable Children(this IPublishedContent content) - { - return content.Children; - } + { + if (content == null) throw new ArgumentNullException("content"); + return content.Children; + } /// /// Gets the children of the content, filtered by a predicate. diff --git a/src/Umbraco.Web/Scheduling/KeepAlive.cs b/src/Umbraco.Web/Scheduling/KeepAlive.cs index 0557e56e57..380ae85401 100644 --- a/src/Umbraco.Web/Scheduling/KeepAlive.cs +++ b/src/Umbraco.Web/Scheduling/KeepAlive.cs @@ -32,7 +32,7 @@ namespace Umbraco.Web.Scheduling // ensure we do not run if not main domain, but do NOT lock it if (_appContext.MainDom.IsMainDom == false) { - LogHelper.Debug("Does not run if not MainDom."); + LogHelper.Debug("Does not run if not MainDom."); return false; // do NOT repeat, going down } diff --git a/src/Umbraco.Web/Security/Identity/AppBuilderExtensions.cs b/src/Umbraco.Web/Security/Identity/AppBuilderExtensions.cs index 3097407de3..be4c8923d7 100644 --- a/src/Umbraco.Web/Security/Identity/AppBuilderExtensions.cs +++ b/src/Umbraco.Web/Security/Identity/AppBuilderExtensions.cs @@ -24,10 +24,31 @@ namespace Umbraco.Web.Security.Identity { public static class AppBuilderExtensions { + /// + /// Called at the end of configuring middleware + /// + /// + /// + /// This could be used for something else in the future - maybe to inform Umbraco that middleware is done/ready, but for + /// now this is used to raise the custom event + /// + /// This is an extension method in case developer entirely replace the UmbracoDefaultOwinStartup class, in which case they will + /// need to ensure they call this extension method in their startup class. + /// + /// TODO: Move this method in v8, it doesn't belong in this namespace/extension class + /// + public static void FinalizeMiddlewareConfiguration(this IAppBuilder app) + { + UmbracoDefaultOwinStartup.OnMiddlewareConfigured(new OwinMiddlewareConfiguredEventArgs(app)); + } + /// /// Sets the OWIN logger to use Umbraco's logging system /// /// + /// + /// TODO: Move this method in v8, it doesn't belong in this namespace/extension class + /// public static void SetUmbracoLoggerFactory(this IAppBuilder app) { app.SetLoggerFactory(new OwinLoggerFactory()); diff --git a/src/Umbraco.Web/Strategies/Migrations/ClearCsrfCookiesAfterUpgrade.cs b/src/Umbraco.Web/Strategies/Migrations/ClearCsrfCookiesAfterUpgrade.cs index 24b706aee9..f40490c2d1 100644 --- a/src/Umbraco.Web/Strategies/Migrations/ClearCsrfCookiesAfterUpgrade.cs +++ b/src/Umbraco.Web/Strategies/Migrations/ClearCsrfCookiesAfterUpgrade.cs @@ -10,7 +10,7 @@ namespace Umbraco.Web.Strategies.Migrations /// /// After upgrade we clear out the csrf tokens /// - public class ClearCsrfCookiesAfterUpgrade : MigrationStartupHander + public class ClearCsrfCookiesAfterUpgrade : MigrationStartupHandler { protected override void AfterMigration(MigrationRunner sender, MigrationEventArgs e) { diff --git a/src/Umbraco.Web/Strategies/Migrations/ClearMediaXmlCacheForDeletedItemsAfterUpgrade.cs b/src/Umbraco.Web/Strategies/Migrations/ClearMediaXmlCacheForDeletedItemsAfterUpgrade.cs index 6e0580a2c4..dcf56fd03f 100644 --- a/src/Umbraco.Web/Strategies/Migrations/ClearMediaXmlCacheForDeletedItemsAfterUpgrade.cs +++ b/src/Umbraco.Web/Strategies/Migrations/ClearMediaXmlCacheForDeletedItemsAfterUpgrade.cs @@ -16,7 +16,7 @@ namespace Umbraco.Web.Strategies.Migrations /// /// * If current is less than or equal to 7.0.0 /// - public class ClearMediaXmlCacheForDeletedItemsAfterUpgrade : MigrationStartupHander + public class ClearMediaXmlCacheForDeletedItemsAfterUpgrade : MigrationStartupHandler { private readonly ISqlSyntaxProvider _sqlSyntax; diff --git a/src/Umbraco.Web/Strategies/Migrations/EnsureListViewDataTypeIsCreated.cs b/src/Umbraco.Web/Strategies/Migrations/EnsureListViewDataTypeIsCreated.cs index a03f9e36a6..706ffe181d 100644 --- a/src/Umbraco.Web/Strategies/Migrations/EnsureListViewDataTypeIsCreated.cs +++ b/src/Umbraco.Web/Strategies/Migrations/EnsureListViewDataTypeIsCreated.cs @@ -1,6 +1,7 @@ using System; using System.Collections.Generic; using System.Linq; +using NPoco; using Umbraco.Core; using Umbraco.Core.Events; using Umbraco.Core.Models; @@ -16,7 +17,7 @@ namespace Umbraco.Web.Strategies.Migrations /// /// Creates the built in list view data types /// - public class EnsureDefaultListViewDataTypesCreated : MigrationStartupHander + public class EnsureDefaultListViewDataTypesCreated : MigrationStartupHandler { private readonly ISqlSyntaxProvider _sqlSyntax; diff --git a/src/Umbraco.Web/Strategies/Migrations/MigrationStartupHander.cs b/src/Umbraco.Web/Strategies/Migrations/MigrationStartupHandler.cs similarity index 78% rename from src/Umbraco.Web/Strategies/Migrations/MigrationStartupHander.cs rename to src/Umbraco.Web/Strategies/Migrations/MigrationStartupHandler.cs index a350911580..3b40bbdf5d 100644 --- a/src/Umbraco.Web/Strategies/Migrations/MigrationStartupHander.cs +++ b/src/Umbraco.Web/Strategies/Migrations/MigrationStartupHandler.cs @@ -1,4 +1,5 @@ -using System.Linq; +using System; +using System.Linq; using Umbraco.Core; using Umbraco.Core.Persistence.Migrations; @@ -7,8 +8,10 @@ namespace Umbraco.Web.Strategies.Migrations /// /// Base class that can be used to run code after the migration runner has executed /// - public abstract class MigrationStartupHander : ApplicationEventHandler + public abstract class MigrationStartupHandler : ApplicationEventHandler, IDisposable { + private bool _disposed; + /// /// Ensure this is run when not configured /// @@ -57,5 +60,23 @@ namespace Umbraco.Web.Strategies.Migrations /// Leaving empty will run for all migration products /// public virtual string[] TargetProductNames { get { return new string[] {}; } } + + public void Dispose() + { + Dispose(true); + GC.SuppressFinalize(this); + } + + ~MigrationStartupHandler() + { + Dispose(false); + } + + protected virtual void Dispose(bool disposing) + { + if (_disposed) return; + _disposed = true; + Unsubscribe(); + } } } \ No newline at end of file diff --git a/src/Umbraco.Web/Strategies/Migrations/OverwriteStylesheetFilesFromTempFiles.cs b/src/Umbraco.Web/Strategies/Migrations/OverwriteStylesheetFilesFromTempFiles.cs index 9a8b6a6044..d8e5ded98f 100644 --- a/src/Umbraco.Web/Strategies/Migrations/OverwriteStylesheetFilesFromTempFiles.cs +++ b/src/Umbraco.Web/Strategies/Migrations/OverwriteStylesheetFilesFromTempFiles.cs @@ -19,7 +19,7 @@ namespace Umbraco.Web.Strategies.Migrations /// files during the migration since other parts of the migration might fail. So once the migration is complete, we'll then copy over the temp /// files that this migration created over top of the developer's files. We'll also create a backup of their files. /// - public sealed class OverwriteStylesheetFilesFromTempFiles : MigrationStartupHander + public sealed class OverwriteStylesheetFilesFromTempFiles : MigrationStartupHandler { protected override void AfterMigration(MigrationRunner sender, MigrationEventArgs e) { diff --git a/src/Umbraco.Web/Strategies/Migrations/PublishAfterUpgradeToVersionSixth.cs b/src/Umbraco.Web/Strategies/Migrations/PublishAfterUpgradeToVersionSixth.cs index e51d6d59b8..125b8f7a86 100644 --- a/src/Umbraco.Web/Strategies/Migrations/PublishAfterUpgradeToVersionSixth.cs +++ b/src/Umbraco.Web/Strategies/Migrations/PublishAfterUpgradeToVersionSixth.cs @@ -1,6 +1,7 @@ using System; using System.Collections.Generic; using System.Linq; +using NPoco; using Umbraco.Core.Events; using Umbraco.Core.Models.Rdbms; using Umbraco.Core.Persistence; @@ -16,7 +17,7 @@ namespace Umbraco.Web.Strategies.Migrations /// This event ensures that upgrades from (configured) versions lower then 6.0.0 /// have their publish state updated after the database schema has been migrated. /// - public class PublishAfterUpgradeToVersionSixth : MigrationStartupHander + public class PublishAfterUpgradeToVersionSixth : MigrationStartupHandler { private readonly ISqlSyntaxProvider _sqlSyntax; @@ -32,19 +33,19 @@ namespace Umbraco.Web.Strategies.Migrations var target = new Version(6, 0, 0); if (e.ConfiguredVersion < target) { - var sql = new Sql(); - sql.Select("*") - .From(_sqlSyntax) - .InnerJoin(_sqlSyntax) - .On(_sqlSyntax, left => left.VersionId, right => right.VersionId) - .InnerJoin(_sqlSyntax) - .On(_sqlSyntax, left => left.NodeId, right => right.NodeId) - .InnerJoin(_sqlSyntax) - .On(_sqlSyntax, left => left.NodeId, right => right.NodeId) - .Where(_sqlSyntax, x => x.NodeObjectType == new Guid(Constants.ObjectTypes.Document)) - .Where(_sqlSyntax, x => x.Path.StartsWith("-1")); + var sql = Sql.BuilderFor(new SqlContext(_sqlSyntax, e.MigrationContext.Database)) + .SelectAll() + .From() + .InnerJoin() + .On(left => left.VersionId, right => right.VersionId) + .InnerJoin() + .On(left => left.NodeId, right => right.NodeId) + .InnerJoin() + .On(left => left.NodeId, right => right.NodeId) + .Where(x => x.NodeObjectType == new Guid(Constants.ObjectTypes.Document)) + .Where(x => x.Path.StartsWith("-1")); - var dtos = e.MigrationContext.Database.Fetch(sql); + var dtos = e.MigrationContext.Database.Fetch(sql); var toUpdate = new List(); var versionGroup = dtos.GroupBy(x => x.NodeId); foreach (var grp in versionGroup) diff --git a/src/Umbraco.Web/Strategies/Migrations/RebuildMediaXmlCacheAfterUpgrade.cs b/src/Umbraco.Web/Strategies/Migrations/RebuildMediaXmlCacheAfterUpgrade.cs index 2af3c402aa..63c8d5db16 100644 --- a/src/Umbraco.Web/Strategies/Migrations/RebuildMediaXmlCacheAfterUpgrade.cs +++ b/src/Umbraco.Web/Strategies/Migrations/RebuildMediaXmlCacheAfterUpgrade.cs @@ -17,7 +17,7 @@ namespace Umbraco.Web.Strategies.Migrations /// /// * If current is less than or equal to 7.0.0 /// - public class RebuildMediaXmlCacheAfterUpgrade : MigrationStartupHander + public class RebuildMediaXmlCacheAfterUpgrade : MigrationStartupHandler { protected override void AfterMigration(MigrationRunner sender, MigrationEventArgs e) { diff --git a/src/Umbraco.Web/Trees/DictionaryTreeController.cs b/src/Umbraco.Web/Trees/DictionaryTreeController.cs new file mode 100644 index 0000000000..dec233a61e --- /dev/null +++ b/src/Umbraco.Web/Trees/DictionaryTreeController.cs @@ -0,0 +1,124 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Net.Http.Formatting; +using Umbraco.Core; +using Umbraco.Core.Models; +using Umbraco.Core.Services; +using Umbraco.Web.Models.Trees; +using Umbraco.Web.WebApi.Filters; +using Umbraco.Web._Legacy.Actions; + +namespace Umbraco.Web.Trees +{ + [UmbracoTreeAuthorize(Constants.Trees.Dictionary)] + [Tree(Constants.Applications.Settings, Constants.Trees.Dictionary, null, sortOrder: 3)] + [Mvc.PluginController("UmbracoTrees")] + [CoreTree] + public class DictionaryTreeController : TreeController + { + protected override TreeNode CreateRootNode(FormDataCollection queryStrings) + { + var node = base.CreateRootNode(queryStrings); + + // For now, this is using the legacy webforms view but will need refactoring + // when the dictionary has been converted to Angular. + node.RoutePath = String.Format("{0}/framed/{1}", queryStrings.GetValue("application"), + Uri.EscapeDataString("settings/DictionaryItemList.aspx")); + + return node; + } + + protected override TreeNodeCollection GetTreeNodes(string id, FormDataCollection queryStrings) + { + var intId = ValidateId(id); + + var nodes = new TreeNodeCollection(); + nodes.AddRange(GetDictionaryItems(intId) + .OrderBy(dictionaryItem => dictionaryItem.ItemKey) + .Select(dictionaryItem => CreateTreeNode(id, queryStrings, dictionaryItem))); + + return nodes; + } + + protected override MenuItemCollection GetMenuForNode(string id, FormDataCollection queryStrings) + { + var intId = ValidateId(id); + + var menu = new MenuItemCollection(); + + if (intId == Constants.System.Root) + { + // Again, menu actions will need to use legacy views as this section hasn't been converted to Angular (yet!) + menu.Items.Add(Services.TextService.Localize("actions", ActionNew.Instance.Alias)) + .ConvertLegacyMenuItem(null, "dictionary", queryStrings.GetValue("application")); + + menu.Items.Add( + Services.TextService.Localize("actions", ActionRefresh.Instance.Alias), true); + } + else + { + + var dictionaryItem = Services.LocalizationService.GetDictionaryItemById(intId); + var entity = new UmbracoEntity + { + Id = dictionaryItem.Id, + Level = 1, + ParentId = -1, + Name = dictionaryItem.ItemKey + }; + + menu.Items.Add(Services.TextService.Localize("actions", ActionNew.Instance.Alias)) + .ConvertLegacyMenuItem(entity, "dictionary", queryStrings.GetValue("application")); + + menu.Items.Add(Services.TextService.Localize("actions", ActionDelete.Instance.Alias)) + .ConvertLegacyMenuItem(null, "dictionary", queryStrings.GetValue("application")); + + menu.Items.Add( + Services.TextService.Localize("actions", ActionRefresh.Instance.Alias), true); + } + + return menu; + } + + private IEnumerable GetDictionaryItems(int id) + { + if (id > Constants.System.Root) + { + var dictionaryItem = Services.LocalizationService.GetDictionaryItemById(id); + + if (dictionaryItem != null) + { + return Services.LocalizationService.GetDictionaryItemChildren(dictionaryItem.Key); + } + } + + return Services.LocalizationService.GetRootDictionaryItems(); + } + + private TreeNode CreateTreeNode(string id, FormDataCollection queryStrings, IDictionaryItem dictionaryItem) + { + var hasChildren = Services.LocalizationService.GetDictionaryItemChildren(dictionaryItem.Key).Any(); + + // Again, menu actions will need to use legacy views as this section hasn't been converted to Angular (yet!) + var node = CreateTreeNode(dictionaryItem.Id.ToInvariantString(), id, queryStrings, dictionaryItem.ItemKey, + "icon-book-alt", hasChildren, + String.Format("{0}/framed/{1}", queryStrings.GetValue("application"), + Uri.EscapeDataString("settings/editDictionaryItem.aspx?id=" + + dictionaryItem.Id))); + + return node; + } + + private int ValidateId(string id) + { + var intId = id.TryConvertTo(); + if (intId == false) + { + throw new InvalidOperationException("Id must be an integer"); + } + + return intId.Result; + } + } +} diff --git a/src/Umbraco.Web/Trees/FileSystemTreeController.cs b/src/Umbraco.Web/Trees/FileSystemTreeController.cs index f9ebaaf2d6..3c612281f5 100644 --- a/src/Umbraco.Web/Trees/FileSystemTreeController.cs +++ b/src/Umbraco.Web/Trees/FileSystemTreeController.cs @@ -2,35 +2,50 @@ using System.Collections.Generic; using System.IO; using System.Linq; +using System.Net.Http.Formatting; using System.Text; using System.Threading.Tasks; +using ClientDependency.Core; +using Umbraco.Core; using Umbraco.Core.IO; +using Umbraco.Core.Models; +using Umbraco.Core.Services; using Umbraco.Web.Models.Trees; +using Umbraco.Web._Legacy.Actions; +using Constants = Umbraco.Core.Constants; namespace Umbraco.Web.Trees { public abstract class FileSystemTreeController : TreeController { protected abstract string FilePath { get; } - protected abstract string FileSearchPattern { get; } + protected abstract IEnumerable FileSearchPattern { get; } + protected abstract string EditFormUrl { get; } + protected abstract bool EnableCreateOnFolder { get; } /// /// Inheritors can override this method to modify the file node that is created. /// /// - protected virtual void OnRenderFileNode(ref TreeNode treeNode) { } + protected virtual void OnRenderFileNode(TreeNode treeNode, FileInfo file) + { + } /// /// Inheritors can override this method to modify the folder node that is created. /// /// - protected virtual void OnRenderFolderNode(ref TreeNode treeNode) { } - - protected override Models.Trees.TreeNodeCollection GetTreeNodes(string id, System.Net.Http.Formatting.FormDataCollection queryStrings) + protected virtual void OnRenderFolderNode(TreeNode treeNode) { + } + + protected override TreeNodeCollection GetTreeNodes(string id, FormDataCollection queryStrings) + { + var nodes = new TreeNodeCollection(); + string orgPath = ""; string path = ""; - if (!string.IsNullOrEmpty(id) && id != "-1") + if (!string.IsNullOrEmpty(id) && id != Constants.System.Root.ToInvariantString()) { orgPath = id; path = IOHelper.MapPath(FilePath + "/" + orgPath); @@ -41,54 +56,124 @@ namespace Umbraco.Web.Trees path = IOHelper.MapPath(FilePath); } - DirectoryInfo dirInfo = new DirectoryInfo(path); - DirectoryInfo[] dirInfos = dirInfo.GetDirectories(); + if (!Directory.Exists(path) && !System.IO.File.Exists(path)) + { + return nodes; + } + + if (System.IO.File.Exists(path)) + { + return GetTreeNodesForFile(path, id, queryStrings); + } + + DirectoryInfo dirInfo = new DirectoryInfo(path); + DirectoryInfo[] dirInfos = new DirectoryInfo(path).GetDirectories(); - var nodes = new TreeNodeCollection(); foreach (DirectoryInfo dir in dirInfos) { - if ((dir.Attributes & FileAttributes.Hidden) == 0) + if ((dir.Attributes.HasFlag(FileAttributes.Hidden)) == false) { - var HasChildren = dir.GetFiles().Length > 0 || dir.GetDirectories().Length > 0; - var node = CreateTreeNode(orgPath + dir.Name, orgPath, queryStrings, dir.Name, "icon-folder", HasChildren); + var hasChildren = dir.GetFiles().Length > 0 || dir.GetDirectories().Length > 0; + var node = CreateTreeNode(orgPath + dir.Name, orgPath, queryStrings, dir.Name, "icon-folder", + hasChildren); - OnRenderFolderNode(ref node); - if(node != null) - nodes.Add(node); + //TODO: This isn't the best way to ensure a noop process for clicking a node but it works for now. + node.AdditionalData["jsClickCallback"] = "javascript:void(0);"; + OnRenderFolderNode(node); + + nodes.Add(node); } } - //this is a hack to enable file system tree to support multiple file extension look-up - //so the pattern both support *.* *.xml and xml,js,vb for lookups - string[] allowedExtensions = new string[0]; - bool filterByMultipleExtensions = FileSearchPattern.Contains(","); - FileInfo[] fileInfo; + var files = FileSearchPattern + .SelectMany(p => dirInfo.GetFiles("*." + p)) + .Where(f => !f.Attributes.HasFlag(FileAttributes.Hidden)); - if (filterByMultipleExtensions) + foreach (FileInfo file in files) { - fileInfo = dirInfo.GetFiles(); - allowedExtensions = FileSearchPattern.ToLower().Split(','); - } - else - fileInfo = dirInfo.GetFiles(FileSearchPattern); + var nodeId = orgPath + file.Name; - foreach (FileInfo file in fileInfo) - { - if ((file.Attributes & FileAttributes.Hidden) == 0) - { - if (filterByMultipleExtensions && Array.IndexOf(allowedExtensions, file.Extension.ToLower().Trim('.')) < 0) - continue; + var node = CreateTreeNode( + nodeId, + orgPath, queryStrings, + file.Name.StripFileExtension(), + "icon-file", + false, + "/" + queryStrings.GetValue("application") + "/framed/" + + Uri.EscapeDataString(string.Format(EditFormUrl, nodeId))); - var node = CreateTreeNode(orgPath + file.Name, orgPath, queryStrings, file.Name, "icon-file", false); + OnRenderFileNode(node, file); - OnRenderFileNode(ref node); - - if(node != null) - nodes.Add(node); - } + nodes.Add(node); } return nodes; - } + } + + protected virtual TreeNodeCollection GetTreeNodesForFile(string path, string id, FormDataCollection queryStrings) + { + return new TreeNodeCollection(); + } + + + protected override MenuItemCollection GetMenuForNode(string id, FormDataCollection queryStrings) + { + + var menu = new MenuItemCollection(); + + OnBeforeRenderMenu(menu, id, queryStrings); + + if (id == Constants.System.Root.ToInvariantString()) + { + //Create the normal create action + menu.Items.Add(Services.TextService.Localize("actions", ActionNew.Instance.Alias)) + //Since we haven't implemented anything for file systems in angular, this needs to be converted to + //use the legacy format + .ConvertLegacyFileSystemMenuItem("", "init" + TreeAlias, queryStrings.GetValue("application")); + + //refresh action + menu.Items.Add( + Services.TextService.Localize("actions", ActionRefresh.Instance.Alias), true); + + return menu; + + } + + if (Directory.Exists(IOHelper.MapPath(FilePath + "/" + id))) + { + if (EnableCreateOnFolder) + { + //Create the normal create action + menu.Items.Add(Services.TextService.Localize("actions", ActionNew.Instance.Alias)) + //Since we haven't implemented anything for file systems in angular, this needs to be converted to + //use the legacy format + .ConvertLegacyFileSystemMenuItem(id, TreeAlias + "Folder", + queryStrings.GetValue("application")); + } + + //refresh action + menu.Items.Add( + Services.TextService.Localize("actions", ActionRefresh.Instance.Alias), true); + + } + + //add delete option for all languages + menu.Items.Add(Services.TextService.Localize("actions", ActionDelete.Instance.Alias), true) + .ConvertLegacyFileSystemMenuItem( + id, TreeAlias, queryStrings.GetValue("application")); + + OnAfterRenderMenu(menu, id, queryStrings); + + return menu; + } + + protected virtual void OnBeforeRenderMenu(MenuItemCollection menu, string id, FormDataCollection queryStrings) + { + } + + protected virtual void OnAfterRenderMenu(MenuItemCollection menu, string id, FormDataCollection queryStrings) + { + + } } } diff --git a/src/Umbraco.Web/Trees/MacrosTreeController.cs b/src/Umbraco.Web/Trees/MacrosTreeController.cs new file mode 100644 index 0000000000..3ee054dee5 --- /dev/null +++ b/src/Umbraco.Web/Trees/MacrosTreeController.cs @@ -0,0 +1,88 @@ +using System; +using System.Collections.Generic; +using System.Globalization; +using System.Linq; +using System.Net; +using System.Net.Http.Formatting; +using System.Web.Http; +using Umbraco.Core; +using Umbraco.Core.Models; +using Umbraco.Web.Models.Trees; +using Umbraco.Web.Mvc; +using Umbraco.Web.WebApi.Filters; +using umbraco; +using Umbraco.Core.Models.EntityBase; +using Umbraco.Core.Services; +using Umbraco.Web._Legacy.Actions; +using Constants = Umbraco.Core.Constants; + +namespace Umbraco.Web.Trees +{ + [UmbracoTreeAuthorize(Constants.Trees.Macros)] + [Tree(Constants.Applications.Developer, Constants.Trees.Macros, "Macros", sortOrder: 2)] + [PluginController("UmbracoTrees")] + [CoreTree] + public class MacrosTreeController : TreeController + { + protected override TreeNodeCollection GetTreeNodes(string id, FormDataCollection queryStrings) + { + var nodes = new TreeNodeCollection(); + + if (id == Constants.System.Root.ToInvariantString()) + { + foreach (var macro in Services.MacroService.GetAll()) + { + nodes.Add(CreateTreeNode( + macro.Id.ToString(), + id, + queryStrings, + macro.Name, + "icon-settings-alt", + false, + //TODO: Rebuild the macro editor in angular, then we dont need to have this at all (which is just a path to the legacy editor) + "/" + queryStrings.GetValue("application") + "/framed/" + + Uri.EscapeDataString("/umbraco/developer/macros/editMacro.aspx?macroID=" + macro.Id))); + } + } + + return nodes; + } + + protected override MenuItemCollection GetMenuForNode(string id, FormDataCollection queryStrings) + { + var menu = new MenuItemCollection(); + + if (id == Constants.System.Root.ToInvariantString()) + { + //Create the normal create action + menu.Items.Add(Services.TextService.Localize("actions", ActionNew.Instance.Alias)) + //Since we haven't implemented anything for macros in angular, this needs to be converted to + //use the legacy format + .ConvertLegacyMenuItem(null, "initmacros", queryStrings.GetValue("application")); + + //refresh action + menu.Items.Add(Services.TextService.Localize("actions", ActionRefresh.Instance.Alias), true); + + return menu; + } + + + var macro = Services.MacroService.GetById(int.Parse(id)); + if (macro == null) return new MenuItemCollection(); + + //add delete option for all macros + menu.Items.Add(Services.TextService.Localize("actions", ActionDelete.Instance.Alias)) + //Since we haven't implemented anything for macros in angular, this needs to be converted to + //use the legacy format + .ConvertLegacyMenuItem(new UmbracoEntity + { + Id = macro.Id, + Level = 1, + ParentId = -1, + Name = macro.Name + }, "macros", queryStrings.GetValue("application")); + + return menu; + } + } +} \ No newline at end of file diff --git a/src/Umbraco.Web/Trees/PartialViewMacrosTree.cs b/src/Umbraco.Web/Trees/PartialViewMacrosTree.cs deleted file mode 100644 index fdde9beb4c..0000000000 --- a/src/Umbraco.Web/Trees/PartialViewMacrosTree.cs +++ /dev/null @@ -1,48 +0,0 @@ -using System.Text; -using Umbraco.Core.IO; -using umbraco.cms.presentation.Trees; -using Umbraco.Core; - -namespace Umbraco.Web.Trees -{ - /// - /// Tree for displaying partial view macros in the developer app - /// - [Tree(Constants.Applications.Developer, "partialViewMacros", "Partial View Macro Files", sortOrder: 6)] - public class PartialViewMacrosTree : PartialViewsTree - { - public PartialViewMacrosTree(string application) : base(application) - { - } - - protected override string FilePath - { - get { return SystemDirectories.MvcViews + "/MacroPartials/"; } - } - - public override void RenderJS(ref StringBuilder javascript) - { - javascript.Append( - @" - function openMacroPartialView(id) { - UmbClientMgr.contentFrame('Settings/Views/EditView.aspx?treeType=partialViewMacros&file=' + id); - } - "); - - }/// - /// Ensures that no folders can be added - /// - /// - protected override void OnRenderFolderNode(ref XmlTreeNode xNode) - { - base.OnRenderFolderNode(ref xNode); - - xNode.NodeType = "partialViewMacrosFolder"; - } - - protected override void ChangeNodeAction(XmlTreeNode xNode) - { - xNode.Action = xNode.Action.Replace("openFile", "openMacroPartialView"); - } - } -} \ No newline at end of file diff --git a/src/Umbraco.Web/Trees/PartialViewMacrosTreeController.cs b/src/Umbraco.Web/Trees/PartialViewMacrosTreeController.cs new file mode 100644 index 0000000000..d4213c7996 --- /dev/null +++ b/src/Umbraco.Web/Trees/PartialViewMacrosTreeController.cs @@ -0,0 +1,24 @@ +using System.Text; +using Umbraco.Core.IO; +using umbraco.cms.presentation.Trees; +using Umbraco.Core; + +namespace Umbraco.Web.Trees +{ + /// + /// Tree for displaying partial view macros in the developer app + /// + [Tree(Constants.Applications.Developer, Constants.Trees.PartialViewMacros, "Partial View Macro Files", sortOrder: 6)] + public class PartialViewMacrosTreeController : PartialViewsTreeController + { + protected override string FilePath + { + get { return SystemDirectories.MvcViews + "/MacroPartials/"; } + } + + protected override string EditFormUrl + { + get { return "Settings/Views/EditView.aspx?treeType=partialViewMacros&file={0}"; } + } + } +} \ No newline at end of file diff --git a/src/Umbraco.Web/Trees/PartialViewsTree.cs b/src/Umbraco.Web/Trees/PartialViewsTree.cs deleted file mode 100644 index ff7edd8fb7..0000000000 --- a/src/Umbraco.Web/Trees/PartialViewsTree.cs +++ /dev/null @@ -1,87 +0,0 @@ -using System; -using System.Collections.Generic; -using System.IO; -using System.Linq; -using System.Text; -using System.Web; -using Umbraco.Core; -using Umbraco.Core.Configuration; -using Umbraco.Core.IO; - -using umbraco.cms.businesslogic.template; -using umbraco.cms.presentation.Trees; -using Umbraco.Web._Legacy.Actions; - -namespace Umbraco.Web.Trees -{ - /// - /// Tree for displaying partial views in the settings app - /// - [Tree(Constants.Applications.Settings, "partialViews", "Partial Views", sortOrder: 2)] - public class PartialViewsTree : FileSystemTree - { - public PartialViewsTree(string application) : base(application) { } - - public override void RenderJS(ref StringBuilder javascript) - { - javascript.Append( - @" - function openPartialView(id) { - UmbClientMgr.contentFrame('Settings/Views/EditView.aspx?treeType=partialViews&file=' + id); - } - "); - } - - protected override void CreateRootNode(ref XmlTreeNode rootNode) - { - rootNode.NodeType = TreeAlias; - rootNode.NodeID = "init"; - } - - protected override string FilePath - { - get { return SystemDirectories.MvcViews + "/Partials/"; } - } - - protected override string FileSearchPattern - { - get { return "*.cshtml"; } - } - - /// - /// Ensures that no folders can be added - /// - /// - protected override void OnRenderFolderNode(ref XmlTreeNode xNode) - { - // We should allow folder hierarchy for organization in large sites. - xNode.Action = "javascript:void(0);"; - xNode.NodeType = "partialViewsFolder"; - xNode.Menu = new List(new IAction[] - { - ActionNew.Instance, - ContextMenuSeperator.Instance, - ActionDelete.Instance, - ContextMenuSeperator.Instance, - ActionRefresh.Instance - }); - - } - - protected virtual void ChangeNodeAction(XmlTreeNode xNode) - { - xNode.Action = xNode.Action.Replace("openFile", "openPartialView"); - } - - protected override void OnRenderFileNode(ref XmlTreeNode xNode) - { - ChangeNodeAction(xNode); - xNode.Icon = "icon-article"; - xNode.OpenIcon = "icon-article"; - - xNode.Text = xNode.Text.StripFileExtension(); - } - - - } -} diff --git a/src/Umbraco.Web/Trees/PartialViewsTreeController.cs b/src/Umbraco.Web/Trees/PartialViewsTreeController.cs new file mode 100644 index 0000000000..3255c87e40 --- /dev/null +++ b/src/Umbraco.Web/Trees/PartialViewsTreeController.cs @@ -0,0 +1,49 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Text; +using System.Web; +using Umbraco.Core; +using Umbraco.Core.Configuration; +using Umbraco.Core.IO; + +using umbraco.cms.businesslogic.template; +using umbraco.cms.presentation.Trees; +using Umbraco.Web.Models.Trees; +using Umbraco.Web._Legacy.Actions; + +namespace Umbraco.Web.Trees +{ + /// + /// Tree for displaying partial views in the settings app + /// + [Tree(Constants.Applications.Settings, Constants.Trees.PartialViews, "Partial Views", sortOrder: 2)] + public class PartialViewsTreeController : FileSystemTreeController + { + protected override string FilePath + { + get { return SystemDirectories.MvcViews + "/Partials/"; } + } + + protected override IEnumerable FileSearchPattern + { + get { return new[] {"cshtml"}; } + } + + protected override string EditFormUrl + { + get { return "Settings/Views/EditView.aspx?treeType=partialViews&file={0}"; } + } + + protected override bool EnableCreateOnFolder + { + get { return true; } + } + + protected override void OnRenderFileNode(TreeNode treeNode, FileInfo file) + { + treeNode.Icon = "icon-article"; + } + } +} diff --git a/src/Umbraco.Web/Trees/ScriptsTreeController.cs b/src/Umbraco.Web/Trees/ScriptsTreeController.cs new file mode 100644 index 0000000000..7409230d24 --- /dev/null +++ b/src/Umbraco.Web/Trees/ScriptsTreeController.cs @@ -0,0 +1,48 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Net.Http.Formatting; +using Umbraco.Core; +using Umbraco.Core.Configuration; +using Umbraco.Core.IO; +using Umbraco.Web.Models.Trees; + +namespace Umbraco.Web.Trees +{ + [Tree(Constants.Applications.Settings, Constants.Trees.Scripts, "Scripts", "icon-folder", "icon-folder", sortOrder: 2)] + public class ScriptsTreeController : FileSystemTreeController + { + protected override string FilePath + { + get { return SystemDirectories.Scripts + "/"; } + } + + protected override IEnumerable FileSearchPattern + { + get { return UmbracoConfig.For.UmbracoSettings().Content.ScriptFileTypes; } + } + + protected override string EditFormUrl + { + get { return "settings/scripts/editScript.aspx?file={0}"; } + } + + protected override bool EnableCreateOnFolder + { + get { return true; } + } + + protected override void OnRenderFolderNode(TreeNode treeNode) + { + } + + protected override void OnRenderFileNode(TreeNode treeNode, FileInfo file) + { + treeNode.Icon = + file.Name.EndsWith(".js", StringComparison.OrdinalIgnoreCase) ? + "icon-script" : + "icon-code"; + + } + } +} diff --git a/src/Umbraco.Web/Trees/StylesheetsTreeController.cs b/src/Umbraco.Web/Trees/StylesheetsTreeController.cs new file mode 100644 index 0000000000..786bfe45bc --- /dev/null +++ b/src/Umbraco.Web/Trees/StylesheetsTreeController.cs @@ -0,0 +1,107 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Net.Http.Formatting; +using System.Text; +using System.Threading.Tasks; +using Umbraco.Core; +using Umbraco.Core.IO; +using Umbraco.Core.Models; +using Umbraco.Core.Persistence.Repositories; +using Umbraco.Core.Services; +using Umbraco.Web.Models.Trees; +using Umbraco.Web._Legacy.Actions; +using File = System.IO.File; + +namespace Umbraco.Web.Trees +{ + [Tree(Constants.Applications.Settings, Constants.Trees.Stylesheets, "Stylesheets", "icon-folder", "icon-folder", sortOrder: 3)] + public class StylesheetsTreeController : FileSystemTreeController + { + + protected override string FilePath + { + get { return SystemDirectories.Css + "/"; } + } + + protected override IEnumerable FileSearchPattern + { + get { return new [] {"css"}; } + } + + protected override string EditFormUrl + { + get { return "settings/stylesheet/editStylesheet.aspx?id={0}"; } + } + + protected override bool EnableCreateOnFolder + { + get { return false; } + } + + + protected override void OnBeforeRenderMenu(MenuItemCollection menu, string id, FormDataCollection queryStrings) + { + if (File.Exists((IOHelper.MapPath(FilePath + "/" + id)))) + { + menu.Items.Add(Services.TextService.Localize("actions", ActionNew.Instance.Alias)) + //Since we haven't implemented anything for file systems in angular, this needs to be converted to + //use the legacy format + .ConvertLegacyFileSystemMenuItem(id, "stylesheet", queryStrings.GetValue("application")); + } + } + + protected override void OnAfterRenderMenu(MenuItemCollection menu, string id, FormDataCollection queryStrings) + { + if (File.Exists((IOHelper.MapPath(FilePath + "/" + id)))) + { + menu.Items.Add(Services.TextService.Localize("actions", ActionSort.Instance.Alias), true) + .ConvertLegacyFileSystemMenuItem(id, "stylesheet", queryStrings.GetValue("application")); + + //refresh action + menu.Items.Add( + Services.TextService.Localize("actions", ActionRefresh.Instance.Alias), true); + } + } + + protected override void OnRenderFileNode(TreeNode treeNode, FileInfo file) + { + treeNode.Icon = "icon-brackets"; + treeNode.NodeType = "stylesheet"; + var styleSheet = Services.FileService.GetStylesheetByName(treeNode.Id.ToString().EnsureEndsWith(".css")); + if (styleSheet != null) + { + treeNode.HasChildren = styleSheet.Properties.Any(); + } + + } + + protected override TreeNodeCollection GetTreeNodesForFile(string path, string id, FormDataCollection queryStrings) + { + var nodes = new TreeNodeCollection(); + + var sheet = Services.FileService.GetStylesheetByName(id.EnsureEndsWith(".css")); + + foreach (var prop in sheet.Properties) + { + var node = CreateTreeNode( + id + "_" + prop.Name, + id, queryStrings, + prop.Name, + "icon-brackets", + false, + "/" + queryStrings.GetValue("application") + "/framed/" + + Uri.EscapeDataString("settings/stylesheet/property/editStylesheetProperty.aspx?id=" + + sheet.Path + "&prop=" + prop.Name)); + node.NodeType = "stylesheetProperty"; + nodes.Add(node); + + + + } + + return nodes; + } + } +} diff --git a/src/Umbraco.Web/Trees/UsersTreeController.cs b/src/Umbraco.Web/Trees/UsersTreeController.cs new file mode 100644 index 0000000000..1ac0f25e27 --- /dev/null +++ b/src/Umbraco.Web/Trees/UsersTreeController.cs @@ -0,0 +1,98 @@ +using System; +using System.Collections.Generic; +using System.Globalization; +using System.Linq; +using System.Net.Http.Formatting; +using Umbraco.Core; +using Umbraco.Core.Configuration; +using Umbraco.Core.Models; +using Umbraco.Core.Models.Membership; +using Umbraco.Web.WebApi.Filters; +using Umbraco.Web._Legacy.Actions; +using Umbraco.Core.Services; +using Umbraco.Web.Models.Trees; +using Umbraco.Web.Mvc; +using Constants = Umbraco.Core.Constants; + +namespace Umbraco.Web.Trees +{ + [UmbracoTreeAuthorize(Constants.Trees.Users)] + [Tree(Constants.Applications.Users, Constants.Trees.Users, null)] + [PluginController("UmbracoTrees")] + [CoreTree] + public class UsersTreeController : TreeController + { + protected override TreeNodeCollection GetTreeNodes(string id, FormDataCollection queryStrings) + { + var nodes = new TreeNodeCollection(); + + int totalusers; + var users = new List(Services.UserService.GetAll(0, int.MaxValue, out totalusers)); + + var currentUser = UmbracoContext.Current.Security.CurrentUser; + var currentUserIsAdmin = currentUser.IsAdmin(); + + foreach (var user in users.OrderBy(x => x.IsApproved == false)) + { + if (UmbracoConfig.For.UmbracoSettings().Security.HideDisabledUsersInBackoffice && + (UmbracoConfig.For.UmbracoSettings().Security.HideDisabledUsersInBackoffice == false || + user.IsApproved == false)) + { + continue; + } + + var node = CreateTreeNode( + user.Id.ToString(CultureInfo.InvariantCulture), + "-1", + queryStrings, + user.Name, + "icon-user", + false, + "/" + queryStrings.GetValue("application") + "/framed/" + + Uri.EscapeDataString("users/EditUser.aspx?id=" + user.Id)); + + if (user.Id == 0) + { + if (currentUser.Id != 0) + continue; + } + else if (currentUserIsAdmin == false && user.IsAdmin()) + continue; + + if (user.IsApproved == false) + node.CssClasses.Add("not-published"); + + nodes.Add(node); + } + + return nodes; + } + + protected override MenuItemCollection GetMenuForNode(string id, FormDataCollection queryStrings) + { + var menu = new MenuItemCollection(); + + if (id == Constants.System.Root.ToInvariantString()) + { + // Root actions + menu.Items.Add(Services.TextService.Localize("actions", ActionNew.Instance.Alias)) + .ConvertLegacyMenuItem(null, "users", queryStrings.GetValue("application")); + + menu.Items.Add( + Services.TextService.Localize("actions", ActionRefresh.Instance.Alias), true); + return menu; + } + + // If administator, don't create a menu + if (id == "0") + return menu; + + menu.Items.Add(new DisableUser() + { + Name = Services.TextService.Localize("actions", "disable") + }); + + return menu; + } + } +} \ No newline at end of file diff --git a/src/Umbraco.Web/Trees/XsltTreeController.cs b/src/Umbraco.Web/Trees/XsltTreeController.cs new file mode 100644 index 0000000000..0c0bb8f637 --- /dev/null +++ b/src/Umbraco.Web/Trees/XsltTreeController.cs @@ -0,0 +1,41 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Umbraco.Core; +using Umbraco.Core.IO; +using Umbraco.Web.Models.Trees; + +namespace Umbraco.Web.Trees +{ + [Tree(Constants.Applications.Settings, Constants.Trees.Xslt, "XSLT Files", "icon-folder", "icon-folder", sortOrder: 2)] + public class XsltTreeController : FileSystemTreeController + { + protected override string FilePath + { + get { return SystemDirectories.Xslt + "/"; } + } + + protected override IEnumerable FileSearchPattern + { + get { return new [] {"xslt"}; } + } + + protected override string EditFormUrl + { + get { return "developer/xslt/editXslt.aspx?file={0}"; } + } + + protected override bool EnableCreateOnFolder + { + get { return false; } + } + + protected override void OnRenderFileNode(TreeNode treeNode, FileInfo file) + { + treeNode.Icon = "icon-code"; + } + } +} diff --git a/src/Umbraco.Web/UI/Controls/InsertMacroSplitButton.cs b/src/Umbraco.Web/UI/Controls/InsertMacroSplitButton.cs index 5c6db74513..4a97eac6d1 100644 --- a/src/Umbraco.Web/UI/Controls/InsertMacroSplitButton.cs +++ b/src/Umbraco.Web/UI/Controls/InsertMacroSplitButton.cs @@ -71,7 +71,8 @@ namespace Umbraco.Web.UI.Controls var divMacroItemContainer = new TagBuilder("div"); divMacroItemContainer.Attributes.Add("style", "width: 285px;display:none;"); divMacroItemContainer.Attributes.Add("class", "sbMenu"); - var macros = ApplicationContext.DatabaseContext.Database.Fetch("select id, macroAlias, macroName from cmsMacro order by macroName"); + + var macros = Services.MacroService.GetAll().OrderBy(x => x.Name); foreach (var macro in macros) { var divMacro = new TagBuilder("div"); diff --git a/src/Umbraco.Web/Umbraco.Web.csproj b/src/Umbraco.Web/Umbraco.Web.csproj index 77ab3ba929..8834ea4609 100644 --- a/src/Umbraco.Web/Umbraco.Web.csproj +++ b/src/Umbraco.Web/Umbraco.Web.csproj @@ -236,6 +236,10 @@ ..\packages\Newtonsoft.Json.8.0.3\lib\net45\Newtonsoft.Json.dll True + + ..\packages\NPoco.3.1.0-u005\lib\net45\NPoco.dll + True + False ..\packages\Owin.1.0\lib\net40\Owin.dll @@ -264,6 +268,7 @@ False ..\packages\Microsoft.AspNet.WebApi.Client.5.2.3\lib\net45\System.Net.Http.Formatting.dll + @@ -365,7 +370,14 @@ + + + + + + + @@ -373,7 +385,6 @@ - @@ -426,7 +437,10 @@ + + + @@ -434,6 +448,7 @@ + @@ -721,7 +736,7 @@ - + @@ -1085,8 +1100,8 @@ - - + + @@ -1130,6 +1145,9 @@ ASPXCodeBehind + + ASPXCodeBehind + @@ -1328,13 +1346,6 @@ Preview.aspx - - MemberSearch.ascx - ASPXCodeBehind - - - MemberSearch.ascx - xsltVisualize.aspx @@ -1499,20 +1510,6 @@ EditMemberGroup.aspx - - search.aspx - ASPXCodeBehind - - - search.aspx - - - ViewMembers.aspx - ASPXCodeBehind - - - ViewMembers.aspx - DictionaryItemList.aspx ASPXCodeBehind @@ -1584,17 +1581,9 @@ xml.aspx - - - - - - - - @@ -1691,7 +1680,6 @@ - Mvc\web.config @@ -1715,9 +1703,6 @@ ASPXCodeBehind - - ASPXCodeBehind - ASPXCodeBehind @@ -1741,7 +1726,6 @@ - @@ -1767,7 +1751,6 @@ ASPXCodeBehind - Designer @@ -1798,7 +1781,9 @@ ASPXCodeBehind - + + ASPXCodeBehind + diff --git a/src/Umbraco.Web/UmbracoDefaultOwinStartup.cs b/src/Umbraco.Web/UmbracoDefaultOwinStartup.cs index 5b3fadd0f3..046b2167d5 100644 --- a/src/Umbraco.Web/UmbracoDefaultOwinStartup.cs +++ b/src/Umbraco.Web/UmbracoDefaultOwinStartup.cs @@ -1,4 +1,5 @@ -using System.Web; +using System; +using System.Web; using Microsoft.Owin; using Microsoft.Owin.Extensions; using Microsoft.Owin.Logging; @@ -59,12 +60,24 @@ namespace Umbraco.Web app .UseUmbracoBackOfficeCookieAuthentication(ApplicationContext, PipelineStage.Authenticate) .UseUmbracoBackOfficeExternalCookieAuthentication(ApplicationContext, PipelineStage.Authenticate) - .UseUmbracoPreviewAuthentication(ApplicationContext, PipelineStage.Authorize); + .UseUmbracoPreviewAuthentication(ApplicationContext, PipelineStage.Authorize) + .FinalizeMiddlewareConfiguration(); } + /// + /// Raised when the middelware has been configured + /// + public static event EventHandler MiddlewareConfigured; + protected virtual ApplicationContext ApplicationContext { get { return ApplicationContext.Current; } } + + internal static void OnMiddlewareConfigured(OwinMiddlewareConfiguredEventArgs args) + { + var handler = MiddlewareConfigured; + if (handler != null) handler(null, args); + } } } diff --git a/src/Umbraco.Web/WebApi/Filters/DisableBrowserCacheAttribute.cs b/src/Umbraco.Web/WebApi/Filters/DisableBrowserCacheAttribute.cs index e1890326fb..99e08a4597 100644 --- a/src/Umbraco.Web/WebApi/Filters/DisableBrowserCacheAttribute.cs +++ b/src/Umbraco.Web/WebApi/Filters/DisableBrowserCacheAttribute.cs @@ -1,15 +1,6 @@ using System; -using System.Collections.Generic; -using System.Linq; -using System.Net.Http; using System.Net.Http.Headers; -using System.Text; -using System.Threading; -using System.Threading.Tasks; -using System.Web; -using System.Web.Http.Controllers; using System.Web.Http.Filters; -using Umbraco.Core; namespace Umbraco.Web.WebApi.Filters { @@ -23,7 +14,11 @@ namespace Umbraco.Web.WebApi.Filters //See: http://stackoverflow.com/questions/17755239/how-to-stop-chrome-from-caching-rest-response-from-webapi base.OnActionExecuted(actionExecutedContext); - + if (actionExecutedContext == null || actionExecutedContext.Response == null || + actionExecutedContext.Response.Headers == null) + { + return; + } //NOTE: Until we upgraded to WebApi 2, this didn't work correctly and we had to revert to using // HttpContext.Current responses. I've changed this back to what it should be now since it works // and now with WebApi2, the HttpContext.Current responses dont! Anyways, all good now. @@ -39,12 +34,9 @@ namespace Umbraco.Web.WebApi.Filters if (actionExecutedContext.Response.Content != null) { actionExecutedContext.Response.Content.Headers.Expires = - //Mon, 01 Jan 1990 00:00:00 GMT - new DateTimeOffset(1990, 1, 1, 0, 0, 0, TimeSpan.Zero); + //Mon, 01 Jan 1990 00:00:00 GMT + new DateTimeOffset(1990, 1, 1, 0, 0, 0, TimeSpan.Zero); } - - - } } } diff --git a/src/Umbraco.Web/WebServices/XmlDataIntegrityController.cs b/src/Umbraco.Web/WebServices/XmlDataIntegrityController.cs index 3e95c9ee22..589801a829 100644 --- a/src/Umbraco.Web/WebServices/XmlDataIntegrityController.cs +++ b/src/Umbraco.Web/WebServices/XmlDataIntegrityController.cs @@ -1,5 +1,6 @@ using System; using System.Web.Http; +using NPoco; using Umbraco.Core; using Umbraco.Core.Models.Rdbms; using Umbraco.Core.Persistence; @@ -37,13 +38,13 @@ namespace Umbraco.Web.WebServices { var totalPublished = Services.ContentService.CountPublished(); - var subQuery = new Sql() + var subQuery = DatabaseContext.Sql() .Select("DISTINCT cmsContentXml.nodeId") - .From(DatabaseContext.SqlSyntax) - .InnerJoin(DatabaseContext.SqlSyntax) - .On(DatabaseContext.SqlSyntax, left => left.NodeId, right => right.NodeId); + .From() + .InnerJoin() + .On(left => left.NodeId, right => right.NodeId); - var totalXml = ApplicationContext.DatabaseContext.Database.ExecuteScalar("SELECT COUNT(*) FROM (" + subQuery.SQL + ") as tmp"); + var totalXml = DatabaseContext.Database.ExecuteScalar("SELECT COUNT(*) FROM (" + subQuery.SQL + ") as tmp"); return totalXml == totalPublished; } @@ -53,13 +54,13 @@ namespace Umbraco.Web.WebServices { var total = Services.MediaService.Count(); var mediaObjectType = Guid.Parse(Constants.ObjectTypes.Media); - var subQuery = new Sql() - .Select("Count(*)") - .From(DatabaseContext.SqlSyntax) - .InnerJoin(DatabaseContext.SqlSyntax) - .On(DatabaseContext.SqlSyntax, left => left.NodeId, right => right.NodeId) - .Where(DatabaseContext.SqlSyntax, dto => dto.NodeObjectType == mediaObjectType); - var totalXml = ApplicationContext.DatabaseContext.Database.ExecuteScalar(subQuery); + var subQuery = DatabaseContext.Sql() + .SelectCount() + .From() + .InnerJoin() + .On(left => left.NodeId, right => right.NodeId) + .Where(dto => dto.NodeObjectType == mediaObjectType); + var totalXml = DatabaseContext.Database.ExecuteScalar(subQuery); return totalXml == total; } @@ -69,13 +70,13 @@ namespace Umbraco.Web.WebServices { var total = Services.MemberService.Count(); var memberObjectType = Guid.Parse(Constants.ObjectTypes.Member); - var subQuery = new Sql() - .Select("Count(*)") - .From(DatabaseContext.SqlSyntax) - .InnerJoin(DatabaseContext.SqlSyntax) - .On(DatabaseContext.SqlSyntax, left => left.NodeId, right => right.NodeId) - .Where(DatabaseContext.SqlSyntax, dto => dto.NodeObjectType == memberObjectType); - var totalXml = ApplicationContext.DatabaseContext.Database.ExecuteScalar(subQuery); + var subQuery = DatabaseContext.Sql() + .SelectCount() + .From() + .InnerJoin() + .On(left => left.NodeId, right => right.NodeId) + .Where(dto => dto.NodeObjectType == memberObjectType); + var totalXml = DatabaseContext.Database.ExecuteScalar(subQuery); return totalXml == total; } diff --git a/src/Umbraco.Web/_Legacy/Actions/ActionDisable.cs b/src/Umbraco.Web/_Legacy/Actions/ActionDisable.cs deleted file mode 100644 index 0e72694fe2..0000000000 --- a/src/Umbraco.Web/_Legacy/Actions/ActionDisable.cs +++ /dev/null @@ -1,91 +0,0 @@ -using System; -using Umbraco.Web.UI.Pages; - -namespace Umbraco.Web._Legacy.Actions -{ - /// - /// This action is invoked when a document is disabled. - /// - public class ActionDisable : IAction - { - //create singleton -#pragma warning disable 612,618 - private static readonly ActionDisable m_instance = new ActionDisable(); -#pragma warning restore 612,618 - - /// - /// A public constructor exists ONLY for backwards compatibility in regards to 3rd party add-ons. - /// All Umbraco assemblies should use the singleton instantiation (this.Instance) - /// When this applicatio is refactored, this constuctor should be made private. - /// - [Obsolete("Use the singleton instantiation instead of a constructor")] - public ActionDisable() { } - - public static ActionDisable Instance - { - get { return m_instance; } - } - - #region IAction Members - - public char Letter - { - get - { - return 'E'; - } - } - - public string JsFunctionName - { - get - { - return string.Format("{0}.actionDisable()", ClientTools.Scripts.GetAppActions); - } - } - - public string JsSource - { - get - { - return null; - } - } - - public string Alias - { - get - { - - return "disable"; - } - } - - public string Icon - { - get - { - - return "remove"; - } - } - - public bool ShowInNotifier - { - get - { - - return false; - } - } - public bool CanBePermissionAssigned - { - get - { - - return false; - } - } - #endregion - } -} diff --git a/src/Umbraco.Web/_Legacy/Utils/JSONSerializer.cs b/src/Umbraco.Web/_Legacy/Utils/JSONSerializer.cs deleted file mode 100644 index f5eaf708a0..0000000000 --- a/src/Umbraco.Web/_Legacy/Utils/JSONSerializer.cs +++ /dev/null @@ -1,66 +0,0 @@ -using System; -using System.Text.RegularExpressions; -using System.Web.Script.Serialization; - -namespace Umbraco.Web._Legacy.Utils -{ - /// - /// The built in JavaScriptSerializer does not allow you to export real JavaScript - /// objects, functions, etc... only string values which isn't always what you want. - /// See - /// - /// Override the JavaScriptSerializer serialization process and look for any - /// custom "tags" strings such as a @ symbol which depicts that the string value - /// should really be a JSON value, therefore the output removes the double quotes. - /// - /// - /// - /// If you want to output: - /// {"myFunction": function() {alert('hello');}} - /// The JavaScriptSerializer will not let you do this, it will render: - /// {"myFunction": "function() {alert('hello');}"} - /// which means that JavaScript will interpret it as a string. - /// This class allows you to output JavaScript objects, amongst other things. - /// - [Obsolete("Remove this for v8")] - internal class JSONSerializer : JavaScriptSerializer - { - - public new string Serialize(object obj) - { - string output = base.Serialize(obj); - - //replaces all strings beginning with this prefix to have no double quotes - Regex regex1 = new Regex(string.Format("(\"{0}(.*?)\")+", PrefixJavaScriptObject), - RegexOptions.Multiline - | RegexOptions.CultureInvariant - | RegexOptions.Compiled - ); - string result = regex1.Replace(output, "$2"); - - return result; - } - - private const string PrefixJavaScriptObject = "@@@@"; - - /// - /// method for a string to be converted to a json object. - /// - /// - /// A string formatted with a special prefix - /// - /// This essentially just prefixes the string with a special key that we will use - /// to parse with later during serialization. - /// - public static string ToJSONObject(string s) - { - return PrefixJavaScriptObject + s; - } - - - } - - - -} - diff --git a/src/Umbraco.Web/packages.config b/src/Umbraco.Web/packages.config index 0b93a154a4..a267cb99ce 100644 --- a/src/Umbraco.Web/packages.config +++ b/src/Umbraco.Web/packages.config @@ -30,6 +30,7 @@ + diff --git a/src/Umbraco.Web/umbraco.presentation/macro.cs b/src/Umbraco.Web/umbraco.presentation/macro.cs index e4234587d5..3d3f505844 100644 --- a/src/Umbraco.Web/umbraco.presentation/macro.cs +++ b/src/Umbraco.Web/umbraco.presentation/macro.cs @@ -1399,7 +1399,7 @@ namespace umbraco //Trace out to profiling... doesn't actually profile, just for informational output. if (excludeProfiling == false) { - using (ApplicationContext.Current.ProfilingLogger.TraceDuration(string.Format("{0}", message))) + using (ApplicationContext.Current.ProfilingLogger.DebugDuration(string.Format("{0}", message))) { } } diff --git a/src/Umbraco.Web/umbraco.presentation/umbraco/Trees/FileSystemTree.cs b/src/Umbraco.Web/umbraco.presentation/umbraco/Trees/FileSystemTree.cs deleted file mode 100644 index aed6009d86..0000000000 --- a/src/Umbraco.Web/umbraco.presentation/umbraco/Trees/FileSystemTree.cs +++ /dev/null @@ -1,134 +0,0 @@ -using System; -using System.Data; -using System.Configuration; -using System.Web; -using System.Web.Security; -using System.Web.UI; -using System.Web.UI.WebControls; -using System.Web.UI.WebControls.WebParts; -using System.Web.UI.HtmlControls; -using System.IO; -using Umbraco.Core.IO; - -namespace umbraco.cms.presentation.Trees -{ - public abstract class FileSystemTree : BaseTree - { - - public FileSystemTree(string application) : base(application) { } - - public override abstract void RenderJS(ref System.Text.StringBuilder Javascript); - protected override abstract void CreateRootNode(ref XmlTreeNode rootNode); - - protected abstract string FilePath { get; } - protected abstract string FileSearchPattern { get; } - - /// - /// Inheritors can override this method to modify the file node that is created. - /// - /// - protected virtual void OnRenderFileNode(ref XmlTreeNode xNode) { } - - /// - /// Inheritors can override this method to modify the folder node that is created. - /// - /// - protected virtual void OnRenderFolderNode(ref XmlTreeNode xNode) { } - - public override void Render(ref XmlTree tree) - { - string orgPath = ""; - string path = ""; - if (!string.IsNullOrEmpty(this.NodeKey)) - { - orgPath = this.NodeKey; - path = IOHelper.MapPath(FilePath + orgPath); - orgPath += "/"; - } - else - { - path = IOHelper.MapPath(FilePath); - } - - DirectoryInfo dirInfo = new DirectoryInfo(path); - - - DirectoryInfo[] dirInfos = dirInfo.Exists ? dirInfo.GetDirectories() : new DirectoryInfo[] { }; - - var args = new TreeEventArgs(tree); - OnBeforeTreeRender(dirInfo, args); - - foreach (DirectoryInfo dir in dirInfos) - { - if ((dir.Attributes & FileAttributes.Hidden) == 0) - { - XmlTreeNode xDirNode = XmlTreeNode.Create(this); - xDirNode.NodeID = orgPath + dir.Name; - xDirNode.Menu.Clear(); - xDirNode.Text = dir.Name; - xDirNode.Action = string.Empty; - xDirNode.Source = GetTreeServiceUrl(orgPath + dir.Name); - xDirNode.Icon = FolderIcon; - xDirNode.OpenIcon = FolderIconOpen; - xDirNode.HasChildren = dir.GetFiles().Length > 0 || dir.GetDirectories().Length > 0; - - OnRenderFolderNode(ref xDirNode); - OnBeforeNodeRender(ref tree, ref xDirNode, EventArgs.Empty); - if (xDirNode != null) - { - tree.Add(xDirNode); - OnAfterNodeRender(ref tree, ref xDirNode, EventArgs.Empty); - } - - - } - } - - //this is a hack to enable file system tree to support multiple file extension look-up - //so the pattern both support *.* *.xml and xml,js,vb for lookups - string[] allowedExtensions = new string[0]; - bool filterByMultipleExtensions = FileSearchPattern.Contains(","); - FileInfo[] fileInfo; - - if (filterByMultipleExtensions) - { - fileInfo = dirInfo.Exists ? dirInfo.GetFiles() : new FileInfo[] {}; - allowedExtensions = FileSearchPattern.ToLower().Split(','); - } - else - { - fileInfo = dirInfo.Exists ? dirInfo.GetFiles(FileSearchPattern) : new FileInfo[] { }; - } - - foreach (FileInfo file in fileInfo) - { - if ((file.Attributes & FileAttributes.Hidden) == 0) - { - if (filterByMultipleExtensions && Array.IndexOf(allowedExtensions, file.Extension.ToLower().Trim('.')) < 0) - continue; - - XmlTreeNode xFileNode = XmlTreeNode.Create(this); - xFileNode.NodeID = orgPath + file.Name; - xFileNode.Text = file.Name; - if (!((orgPath == ""))) - xFileNode.Action = "javascript:openFile('" + orgPath + file.Name + "');"; - else - xFileNode.Action = "javascript:openFile('" + file.Name + "');"; - xFileNode.Icon = "doc.gif"; - xFileNode.OpenIcon = "doc.gif"; - - OnRenderFileNode(ref xFileNode); - OnBeforeNodeRender(ref tree, ref xFileNode, EventArgs.Empty); - if (xFileNode != null) - { - tree.Add(xFileNode); - OnAfterNodeRender(ref tree, ref xFileNode, EventArgs.Empty); - } - - - } - } - OnAfterTreeRender(dirInfo, args); - } - } -} diff --git a/src/Umbraco.Web/umbraco.presentation/umbraco/Trees/XmlTree.cs b/src/Umbraco.Web/umbraco.presentation/umbraco/Trees/XmlTree.cs index def2bbb9b0..9b62e5ea1f 100644 --- a/src/Umbraco.Web/umbraco.presentation/umbraco/Trees/XmlTree.cs +++ b/src/Umbraco.Web/umbraco.presentation/umbraco/Trees/XmlTree.cs @@ -7,18 +7,10 @@ using System.Web.Script.Serialization; using Umbraco.Core.IO; using Umbraco.Web.UI.Pages; using Umbraco.Web._Legacy.Actions; -using Umbraco.Web._Legacy.Utils; using Action = Umbraco.Web._Legacy.Actions.Action; namespace umbraco.cms.presentation.Trees { - - public enum SerializedTreeType - { - JSONTree, - JsTree - } - /// /// Used for serializing data to XML as the data structure for the JavaScript tree /// @@ -28,73 +20,13 @@ namespace umbraco.cms.presentation.Trees public XmlTree() { - //set to the XTree provider by default. - //m_TreeType = SerializedTreeType.XmlTree; - //m_TreeType = SerializedTreeType.JSONTree; - m_TreeType = SerializedTreeType.JsTree; - Init(); } - - /// - /// Use this constructor to force a tree provider to be used - /// - /// - public XmlTree(SerializedTreeType treeType) - { - m_TreeType = treeType; - Init(); - } - + private void Init() { - m_JSSerializer = new JSONSerializer { MaxJsonLength = int.MaxValue }; - - switch (m_TreeType) - { - case SerializedTreeType.JSONTree: - m_JSSerializer.RegisterConverters(new List() - { - new JSONTreeConverter(), - new JSONTreeNodeConverter() - }); - break; - case SerializedTreeType.JsTree: - m_JSSerializer.RegisterConverters(new List() - { - new JsTreeNodeConverter() - }); - break; - } - - } - - private JSONSerializer m_JSSerializer; - private SerializedTreeType m_TreeType; - - /// - /// Returns the string representation of the tree structure depending on the SerializedTreeType - /// specified. - /// - /// - public override string ToString() - { - return ToString(m_TreeType); - } - - public string ToString(SerializedTreeType type) - { - switch (type) - { - case SerializedTreeType.JsTree: - return m_JSSerializer.Serialize(this.treeCollection); - case SerializedTreeType.JSONTree: - return m_JSSerializer.Serialize(this); - } - return ""; - } - + public void Add(XmlTreeNode obj) { treeCollection.Add(obj); @@ -533,231 +465,4 @@ namespace umbraco.cms.presentation.Trees } - /// - /// Used to serialize an XmlTree object to JSON for supporting a JSON Tree View control. - /// - internal class JSONTreeConverter : JavaScriptConverter - { - /// - /// Not implemented as we never need to Deserialize - /// - /// - /// - /// - /// - public override object Deserialize(IDictionary dictionary, Type type, JavaScriptSerializer serializer) - { - throw new NotImplementedException(); - } - - /// - /// Serializes an XmlTree object with the relevant values. - /// - /// - /// - /// - public override IDictionary Serialize(object obj, JavaScriptSerializer serializer) - { - XmlTree tree = obj as XmlTree; - - Dictionary resultSet = new Dictionary(); - Dictionary resultTree = new Dictionary(); - - if (tree != null) - { - //add a count property for the count of total nodes - resultTree.Add("Count", tree.Count); - - List nodes = new List(); - foreach (XmlTreeNode node in tree.treeCollection) - nodes.Add(node); - - resultTree.Add("Nodes", nodes); - } - - resultSet.Add("Tree", resultTree); - - return resultSet; - } - - public override IEnumerable SupportedTypes - { - get { return new Type[] { typeof(XmlTree) }; } - } - } - - /// - /// Used to serialize an XmlTreeNode object to JSON for supporting a JS Tree View control. - /// - internal class JSONTreeNodeConverter : JavaScriptConverter - { - - /// - /// Not implemented as we never need to Deserialize - /// - /// - /// - /// - /// - public override object Deserialize(IDictionary dictionary, Type type, JavaScriptSerializer serializer) - { - throw new NotImplementedException(); - } - - /// - /// Serializes an XmlTreeNode object with the relevant values. - /// - /// - /// - /// - public override IDictionary Serialize(object obj, JavaScriptSerializer serializer) - { - XmlTreeNode node = obj as XmlTreeNode; - - Dictionary result = new Dictionary(); - - if (node != null) - { - //add the properties - result.Add(XmlTreeNode.TreeAttributes.notPublished.ToString(), node.NotPublished); - result.Add(XmlTreeNode.TreeAttributes.isProtected.ToString(), node.IsProtected); - result.Add(XmlTreeNode.TreeAttributes.text.ToString(), node.Text); - result.Add(XmlTreeNode.TreeAttributes.action.ToString(), node.Action); - result.Add(XmlTreeNode.TreeAttributes.src.ToString(), node.Source); - result.Add(XmlTreeNode.TreeAttributes.iconClass.ToString(), node.IconClass); - result.Add(XmlTreeNode.TreeAttributes.icon.ToString(), node.Icon); - result.Add(XmlTreeNode.TreeAttributes.openIcon.ToString(), node.OpenIcon); - result.Add(XmlTreeNode.TreeAttributes.nodeType.ToString(), node.NodeType); - result.Add(XmlTreeNode.TreeAttributes.nodeID.ToString(), node.NodeID); - - //Add the menu as letters. - result.Add(XmlTreeNode.TreeAttributes.menu.ToString(), node.Menu != null && node.Menu.Count > 0 ? Action.ToString(node.Menu) : ""); - - return result; - } - - return new Dictionary(); - - } - - public override IEnumerable SupportedTypes - { - get { return new Type[] { typeof(XmlTreeNode) }; } - } - } - - /// - /// Used to serialize an XmlTreeNode object to JSON for supporting a JS Tree View control. - /// - internal class JsTreeNodeConverter : JavaScriptConverter - { - - /// - /// A reference path to where the icons are actually stored as compared to where the tree themes folder is - /// - private static string IconPath = IOHelper.ResolveUrl(SystemDirectories.Umbraco) + "/images/umbraco/"; - - /// - /// Not implemented as we never need to Deserialize - /// - /// - /// - /// - /// - public override object Deserialize(IDictionary dictionary, Type type, JavaScriptSerializer serializer) - { - throw new NotImplementedException(); - } - - /// - /// Serializes an XmlTreeNode object with the relevant values. - /// - /// - /// - /// - public override IDictionary Serialize(object obj, JavaScriptSerializer serializer) - { - XmlTreeNode node = obj as XmlTreeNode; - - Dictionary result = new Dictionary(); - - if (node != null) - { - //the data object to build the node - Dictionary data = new Dictionary(); - - data.Add("title", node.Text); - - - - //the attributes object fot the tree node link (a) object created - Dictionary dataAttributes = new Dictionary(); - string cssClass = ""; - if (node.Icon.StartsWith(".spr")) - cssClass = "sprTree " + node.Icon.TrimStart('.'); - else - { - //there is no sprite so add the noSpr class - cssClass = "sprTree noSpr"; - data.Add("icon", IconPath + node.Icon); - } - dataAttributes.Add("class", cssClass + (string.IsNullOrEmpty(node.IconClass) ? "" : " " + node.IconClass)); - dataAttributes.Add("href", node.Action); - - //add a metadata dictionary object, we can store whatever we want in this! - //in this case we're going to store permissions & the tree type & the child node source url - //For whatever reason jsTree requires this JSON output to be quoted!?! - //This also needs to be stored in the attributes object with the class above. - Dictionary metadata = new Dictionary(); - //the menu: - metadata.Add("menu", node.Menu == null ? "" : Action.ToString(node.Menu)); - //the tree type: - metadata.Add("nodeType", node.NodeType); - //the data url for child nodes: - metadata.Add("source", node.Source); - - //the metadata/jsTree requires this property to be in a quoted JSON syntax - JSONSerializer jsSerializer = new JSONSerializer(); - string strMetaData = jsSerializer.Serialize(metadata).Replace("\"", "'"); - dataAttributes.Add("umb:nodedata", strMetaData); - - data.Add("attributes", dataAttributes); - - //add the data structure - result.Add("data", data); - - //state is nothing if no children - if ((node.HasChildren || node.IsRoot) && !string.IsNullOrEmpty(node.Source)) - result.Add("state", "closed"); - - //the attributes object for the tree node (li) object created - Dictionary attributes = new Dictionary(); - attributes.Add("id", node.NodeID); - attributes.Add("class", string.Join(" ", node.Style.AppliedClasses.ToArray())); - - if (node.IsRoot) - attributes.Add("rel", "rootNode"); - else - attributes.Add("rel", "dataNode"); - - //the tree type should always be set, however if some developers have serialized their tree into an XmlTree - //then there is no gaurantees that this will be set if they didn't use the create methods of XmlTreeNode. - //So, we'll set the treetype to the nodetype if it is null, this means that the tree on the front end may - //not function as expected when reloding a node. - attributes.Add("umb:type", string.IsNullOrEmpty(node.TreeType) ? node.NodeType : node.TreeType); - - result.Add("attributes", attributes); - - return result; - } - - return null; - - } - - public override IEnumerable SupportedTypes - { - get { return new Type[] { typeof(XmlTreeNode) }; } - } - } } diff --git a/src/Umbraco.Web/umbraco.presentation/umbraco/Trees/loadDictionary.cs b/src/Umbraco.Web/umbraco.presentation/umbraco/Trees/loadDictionary.cs deleted file mode 100644 index 03ae754f5c..0000000000 --- a/src/Umbraco.Web/umbraco.presentation/umbraco/Trees/loadDictionary.cs +++ /dev/null @@ -1,82 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; - -using umbraco.cms.businesslogic; -using umbraco.cms.presentation.Trees; -using Umbraco.Core; -using Umbraco.Web.Trees; -using Umbraco.Web._Legacy.Actions; - - -namespace umbraco -{ - - [Tree(Constants.Applications.Translation, Constants.Trees.Dictionary, "Dictionary", sortOrder: 0)] - public class loadDictionary : BaseTree - { - public loadDictionary(string application) : base(application) { } - - protected override void CreateRootNode(ref XmlTreeNode rootNode) - { - rootNode.NodeType = "init" + TreeAlias; - rootNode.NodeID = "init"; - rootNode.Action = "javascript:openDictionary()"; - } - - protected override void CreateAllowedActions(ref List actions) - { - actions.Clear(); - actions.Add(ActionNew.Instance); - actions.Add(ActionDelete.Instance); - actions.Add(ContextMenuSeperator.Instance); - actions.Add(ActionRefresh.Instance); - } - - public override void RenderJS(ref StringBuilder Javascript) - { - Javascript.Append( - @" - function openDictionary() { - UmbClientMgr.contentFrame('settings/DictionaryItemList.aspx'); - } - function openDictionaryItem(id) { - UmbClientMgr.contentFrame('settings/editDictionaryItem.aspx?id=' + id); - }"); - } - - public override void Render(ref XmlTree tree) - { - - Dictionary.DictionaryItem[] tmp; - if (this.id == this.StartNodeID) - tmp = Dictionary.getTopMostItems; - else - tmp = new Dictionary.DictionaryItem(this.id).Children; - - foreach (Dictionary.DictionaryItem di in tmp.OrderBy(a => a.key)) - { - XmlTreeNode xNode = XmlTreeNode.Create(this); - xNode.NodeID = di.id.ToString(); //dictionary_ + id.. - xNode.Text = di.key; - xNode.Action = string.Format("javascript:openDictionaryItem({0});", di.id); - xNode.Icon = "icon-book-alt"; - xNode.NodeType = "DictionaryItem"; //this shouldn't be like this, it should be this.TreeAlias but the ui.config file points to this name. - xNode.Source = this.GetTreeServiceUrl(di.id); - xNode.HasChildren = di.hasChildren; - - OnBeforeNodeRender(ref tree, ref xNode, EventArgs.Empty); - if (xNode != null) - { - tree.Add(xNode); - OnAfterNodeRender(ref tree, ref xNode, EventArgs.Empty); - } - - } - } - - - } - -} diff --git a/src/Umbraco.Web/umbraco.presentation/umbraco/Trees/loadMacros.cs b/src/Umbraco.Web/umbraco.presentation/umbraco/Trees/loadMacros.cs deleted file mode 100644 index 6a689878fa..0000000000 --- a/src/Umbraco.Web/umbraco.presentation/umbraco/Trees/loadMacros.cs +++ /dev/null @@ -1,66 +0,0 @@ -using System; -using System.Text; - -using umbraco.DataLayer; -using umbraco.cms.presentation.Trees; -using Umbraco.Core; -using Umbraco.Web.Trees; - - -namespace umbraco -{ - /// - /// Handles loading of the cache application into the developer application tree - /// - [Tree(Constants.Applications.Developer, "macros", "Macros", sortOrder: 2)] - public class loadMacros : BaseTree - { - - public loadMacros(string application) : base(application) { } - - protected override void CreateRootNode(ref XmlTreeNode rootNode) - { - rootNode.NodeType = "init" + TreeAlias; - rootNode.NodeID = "init"; - } - - /// - /// Renders the JS. - /// - /// The javascript. - public override void RenderJS(ref StringBuilder Javascript) - { - Javascript.Append( - @" -function openMacro(id) { - UmbClientMgr.contentFrame('developer/macros/editMacro.aspx?macroID=' + id); -} -"); - } - - /// - /// This will call the normal Render method by passing the converted XmlTree to an XmlDocument. - /// TODO: need to update this render method to do everything that the obsolete render method does and remove the obsolete method - /// - /// - public override void Render(ref XmlTree tree) - { - foreach(var macros in ApplicationContext.Current.DatabaseContext.Database.Query("select id, macroName from cmsMacro order by macroName")) - { - XmlTreeNode xNode = XmlTreeNode.Create(this); - xNode.NodeID = macros.id.ToString(); - xNode.Text = macros.macroName; - xNode.Action = "javascript:openMacro(" + macros.id + ");"; - xNode.Icon = " icon-settings-alt"; - xNode.OpenIcon = "icon-settings-alt"; - OnBeforeNodeRender(ref tree, ref xNode, EventArgs.Empty); - if (xNode != null) - { - tree.Add(xNode); - } - OnAfterNodeRender(ref tree, ref xNode, EventArgs.Empty); - } - } - - } -} diff --git a/src/Umbraco.Web/umbraco.presentation/umbraco/Trees/loadScripts.cs b/src/Umbraco.Web/umbraco.presentation/umbraco/Trees/loadScripts.cs deleted file mode 100644 index 296d7b1db4..0000000000 --- a/src/Umbraco.Web/umbraco.presentation/umbraco/Trees/loadScripts.cs +++ /dev/null @@ -1,92 +0,0 @@ - -using Umbraco.Core.Services; -using System.Collections.Generic; -using System.Text; -using Umbraco.Core; - -using Umbraco.Core.Configuration; -using umbraco.cms.presentation.Trees; -using Umbraco.Core.IO; -using Umbraco.Web.Trees; -using Umbraco.Web._Legacy.Actions; - - -namespace umbraco -{ - [Tree(Constants.Applications.Settings, "scripts", "Scripts", "icon-folder", "icon-folder", sortOrder: 2)] - public class loadScripts : FileSystemTree - { - public loadScripts(string application) : base(application) { } - protected override void CreateRootNode(ref XmlTreeNode rootNode) - { - rootNode.NodeType = "init" + TreeAlias; - rootNode.NodeID = "init"; - rootNode.Text = Services.TextService.Localize("treeHeaders/scripts"); - } - - public override void RenderJS(ref StringBuilder Javascript) - { - Javascript.Append( - @" - function openScriptEditor(id) { - UmbClientMgr.contentFrame('settings/scripts/editScript.aspx?file=' + id); - } - function openScriptFolder(id) { - return false; - } - "); - } - - protected override string FilePath - { - get - { - return SystemDirectories.Scripts + "/"; - } - } - - protected override string FileSearchPattern - { - - get { return string.Join(",", UmbracoConfig.For.UmbracoSettings().Content.ScriptFileTypes); } - } - - protected override void OnRenderFolderNode(ref XmlTreeNode xNode) - { - - xNode.Menu = new List(new IAction[] - { - ActionNew.Instance, - ContextMenuSeperator.Instance, - ActionDelete.Instance, - ContextMenuSeperator.Instance, - ActionRefresh.Instance - }); - xNode.Action = "javascript:void(0)"; - xNode.NodeType = "scriptsFolder"; - xNode.Action = "javascript:void(0);"; - } - - protected override void OnRenderFileNode(ref XmlTreeNode xNode) - { - xNode.Action = xNode.Action.Replace("openFile", "openScriptEditor"); - - // add special icons for javascript files - if (xNode.Text.Contains(".js")) - { - xNode.Icon = "icon-script"; - xNode.OpenIcon = "icon-script"; - } - else - { - xNode.Icon = "icon-code"; - xNode.OpenIcon = "icon-code"; - } - - xNode.Text = xNode.Text.StripFileExtension(); - } - - - } - -} diff --git a/src/Umbraco.Web/umbraco.presentation/umbraco/Trees/loadStylesheetProperty.cs b/src/Umbraco.Web/umbraco.presentation/umbraco/Trees/loadStylesheetProperty.cs deleted file mode 100644 index 372b490e9a..0000000000 --- a/src/Umbraco.Web/umbraco.presentation/umbraco/Trees/loadStylesheetProperty.cs +++ /dev/null @@ -1,64 +0,0 @@ -using System; -using System.Globalization; -using System.Text; -using System.Web; - -using umbraco.cms.businesslogic.web; -using umbraco.cms.presentation.Trees; -using Umbraco.Core; -using Umbraco.Web.Trees; - - -namespace umbraco -{ - [Tree(Constants.Applications.Settings, "stylesheetProperty", "Stylesheet Property", "", "", initialize: false)] - public class loadStylesheetProperty : BaseTree - { - public loadStylesheetProperty(string application) : base(application) { } - - protected override void CreateRootNode(ref XmlTreeNode rootNode) - { - rootNode.NodeType = "init" + TreeAlias; - rootNode.NodeID = "init"; - } - - public override void RenderJS(ref StringBuilder Javascript) - { - Javascript.Append( - @" - function openStylesheetProperty(name, prop) { - UmbClientMgr.contentFrame('settings/stylesheet/property/editStylesheetProperty.aspx?id=' + name + '&prop=' + prop); - } - "); - } - - public override void Render(ref XmlTree tree) - { - var sheet = Services.FileService.GetStylesheetByName(NodeKey.EnsureEndsWith(".css")); - - foreach (var prop in sheet.Properties) - { - var sheetId = sheet.Path.TrimEnd(".css"); - var xNode = XmlTreeNode.Create(this); - xNode.NodeID = sheetId + "_" + prop.Name; - xNode.Text = prop.Name; - xNode.Action = "javascript:openStylesheetProperty('" + - //Needs to be escaped for JS - HttpUtility.UrlEncode(sheet.Path) + - "','" + prop.Name + "');"; - xNode.Icon = "icon-brackets"; - xNode.OpenIcon = "icon-brackets"; - - OnBeforeNodeRender(ref tree, ref xNode, EventArgs.Empty); - if (xNode != null) - { - tree.Add(xNode); - OnAfterNodeRender(ref tree, ref xNode, EventArgs.Empty); - } - - } - } - - } - -} diff --git a/src/Umbraco.Web/umbraco.presentation/umbraco/Trees/loadStylesheets.cs b/src/Umbraco.Web/umbraco.presentation/umbraco/Trees/loadStylesheets.cs deleted file mode 100644 index 649212315e..0000000000 --- a/src/Umbraco.Web/umbraco.presentation/umbraco/Trees/loadStylesheets.cs +++ /dev/null @@ -1,74 +0,0 @@ -using Umbraco.Core.Services; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Web; -using umbraco.cms.presentation.Trees; -using Umbraco.Core; -using Umbraco.Web.Trees; -using Umbraco.Web._Legacy.Actions; - - -namespace umbraco -{ - [Tree(Constants.Applications.Settings, Constants.Trees.Stylesheets, "Stylesheets")] - public class loadStylesheets : BaseTree - { - public loadStylesheets(string application) : base(application) { } - - protected override void CreateRootNode(ref XmlTreeNode rootNode) - { - rootNode.NodeType = "init" + TreeAlias; - rootNode.NodeID = "init"; - rootNode.Text = Services.TextService.Localize("treeHeaders/stylesheets"); - } - - public override void RenderJS(ref StringBuilder Javascript) - { - Javascript.Append( - @" - function openStylesheet(name) { - UmbClientMgr.contentFrame('settings/stylesheet/editStylesheet.aspx?id=' + name); - } - "); - } - - protected override void CreateAllowedActions(ref List actions) - { - actions.Clear(); - actions.AddRange(new IAction[] { ActionNew.Instance, ActionDelete.Instance, - ActionSort.Instance, ContextMenuSeperator.Instance, ActionRefresh.Instance }); - } - - public override void Render(ref XmlTree tree) - { - foreach (var sheet in Services.FileService.GetStylesheets()) - { - var nodeId = sheet.Path.TrimEnd(".css"); - var xNode = XmlTreeNode.Create(this); - xNode.NodeID = nodeId; - xNode.Text = nodeId; - xNode.Action = "javascript:openStylesheet('" + - //Needs to be escaped for JS - HttpUtility.UrlEncode(sheet.Path) + "');"; - var styleSheetPropertyTree = new loadStylesheetProperty(this.app); - xNode.Source = styleSheetPropertyTree.GetTreeServiceUrl(nodeId); - xNode.HasChildren = sheet.Properties.Any(); - xNode.Icon = " icon-brackets"; - xNode.OpenIcon = "icon-brackets"; - xNode.NodeType = "stylesheet"; //this shouldn't be like this, it should be this.TreeAlias but the ui.config file points to this name. - - OnBeforeNodeRender(ref tree, ref xNode, EventArgs.Empty); - if (xNode != null) - { - tree.Add(xNode); - OnAfterNodeRender(ref tree, ref xNode, EventArgs.Empty); - } - - } - } - - } - -} diff --git a/src/Umbraco.Web/umbraco.presentation/umbraco/Trees/loadUsers.cs b/src/Umbraco.Web/umbraco.presentation/umbraco/Trees/loadUsers.cs deleted file mode 100644 index e5418c37be..0000000000 --- a/src/Umbraco.Web/umbraco.presentation/umbraco/Trees/loadUsers.cs +++ /dev/null @@ -1,112 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Text; -using Umbraco.Core.Configuration; -using umbraco.cms.presentation.Trees; -using System.Linq; -using Umbraco.Core; -using Umbraco.Core.Models; -using Umbraco.Core.Models.Membership; -using Umbraco.Web; -using Umbraco.Web.Trees; -using Umbraco.Web._Legacy.Actions; - - -namespace umbraco -{ - /// - /// Handles loading of all umbraco users into the users application tree - /// - [Tree(Constants.Applications.Users, "users", "Users")] - public class loadUsers : BaseTree - { - public loadUsers(string application) : base(application) { } - - protected override void CreateRootNode(ref XmlTreeNode rootNode) - { - } - - /// - /// Renders the Javascript. - /// - /// The javascript. - public override void RenderJS(ref StringBuilder Javascript) - { - Javascript.Append( - @" -function openUser(id) { - UmbClientMgr.contentFrame('users/editUser.aspx?id=' + id); -} -"); - } - - protected override void CreateAllowedActions(ref List actions) - { - actions.Clear(); - actions.Add(ActionDisable.Instance); - } - - public override void Render(ref XmlTree tree) - { - int totalusers; - var users = new List(Services.UserService.GetAll(0, int.MaxValue, out totalusers)); - - var currUser = UmbracoContext.Current.Security.CurrentUser; - - bool currUserIsAdmin = currUser.IsAdmin(); - foreach (var u in users.OrderBy(x => x.IsApproved == false)) - { - if (UmbracoConfig.For.UmbracoSettings().Security.HideDisabledUsersInBackoffice == false - || (UmbracoConfig.For.UmbracoSettings().Security.HideDisabledUsersInBackoffice && u.IsApproved)) - { - - XmlTreeNode xNode = XmlTreeNode.Create(this); - - // special check for ROOT user - if (u.Id == 0) - { - //if its the administrator, don't create a menu - xNode.Menu = null; - //if the current user is not the administrator, then don't add this node. - if (currUser.Id != 0) - continue; - } - // Special check for admins in general (only show admins to admins) - else if (!currUserIsAdmin && u.IsAdmin()) - { - continue; - } - - - - - - //xNode.IconClass = "umbraco-tree-icon-grey"; - - xNode.NodeID = u.Id.ToString(); - xNode.Text = u.Name; - xNode.Action = "javascript:openUser(" + u.Id + ");"; - xNode.Icon = "icon-user"; - xNode.OpenIcon = "icon-user"; - - if (u.IsApproved == false) { - xNode.Style.DimNode(); - } - - OnBeforeNodeRender(ref tree, ref xNode, EventArgs.Empty); - if (xNode != null) - { - tree.Add(xNode); - OnAfterNodeRender(ref tree, ref xNode, EventArgs.Empty); - } - - - } - - - } - } - - } - -} diff --git a/src/Umbraco.Web/umbraco.presentation/umbraco/Trees/loadXslt.cs b/src/Umbraco.Web/umbraco.presentation/umbraco/Trees/loadXslt.cs deleted file mode 100644 index 46fbb8c2cd..0000000000 --- a/src/Umbraco.Web/umbraco.presentation/umbraco/Trees/loadXslt.cs +++ /dev/null @@ -1,66 +0,0 @@ -using System.Collections.Generic; -using System.Text; -using umbraco.cms.presentation.Trees; -using Umbraco.Core.IO; -using Umbraco.Core; -using Umbraco.Web.Trees; -using Umbraco.Web._Legacy.Actions; - -namespace umbraco -{ - /// - /// Handles loading of the xslt files into the application tree - /// - [Tree(Constants.Applications.Developer, "xslt", "XSLT Files", sortOrder: 5)] - public class loadXslt : FileSystemTree - { - - public loadXslt(string application) : base(application) { } - - protected override void CreateRootNode(ref XmlTreeNode rootNode) - { - rootNode.NodeType = "init" + TreeAlias; - rootNode.NodeID = "init"; - } - - /// - /// Renders the Javascript - /// - /// The javascript. - public override void RenderJS(ref StringBuilder Javascript) - { - Javascript.Append( - @" -function openXslt(id) { - UmbClientMgr.contentFrame('developer/xslt/editXslt.aspx?file=' + id); -} -"); - } - - protected override string FilePath - { - get { return SystemDirectories.Xslt + "/"; } - } - - protected override string FileSearchPattern - { - get { return "*.xslt"; } - } - - protected override void OnRenderFileNode(ref XmlTreeNode xNode) - { - xNode.Action = xNode.Action.Replace("openFile", "openXslt"); - xNode.Icon = "icon-code"; - xNode.OpenIcon = "icon-code"; - - xNode.Text = xNode.Text.StripFileExtension(); - } - - protected override void OnRenderFolderNode(ref XmlTreeNode xNode) - { - xNode.Menu = new List(new IAction[] { ActionDelete.Instance, ContextMenuSeperator.Instance, ActionRefresh.Instance }); - xNode.NodeType = "xsltFolder"; - } - } - -} diff --git a/src/Umbraco.Web/umbraco.presentation/umbraco/controls/Tree/JTreeContextMenu.cs b/src/Umbraco.Web/umbraco.presentation/umbraco/controls/Tree/JTreeContextMenu.cs index 8935aa9bdf..cfaf6bb2cd 100644 --- a/src/Umbraco.Web/umbraco.presentation/umbraco/controls/Tree/JTreeContextMenu.cs +++ b/src/Umbraco.Web/umbraco.presentation/umbraco/controls/Tree/JTreeContextMenu.cs @@ -4,7 +4,6 @@ using System.Web.Script.Serialization; using Umbraco.Core.Logging; using Umbraco.Core; using Umbraco.Web._Legacy.Actions; -using Umbraco.Web._Legacy.Utils; using Action = Umbraco.Web._Legacy.Actions.Action; namespace umbraco.controls.Tree @@ -14,7 +13,7 @@ namespace umbraco.controls.Tree public string RenderJSONMenu() { - JSONSerializer jSSerializer = new JSONSerializer(); + JavaScriptSerializer jSSerializer = new JavaScriptSerializer(); jSSerializer.RegisterConverters(new List() { diff --git a/src/Umbraco.Web/umbraco.presentation/umbraco/controls/Tree/JTreeContextMenuItem.cs b/src/Umbraco.Web/umbraco.presentation/umbraco/controls/Tree/JTreeContextMenuItem.cs index f49bc75a50..c624c429c2 100644 --- a/src/Umbraco.Web/umbraco.presentation/umbraco/controls/Tree/JTreeContextMenuItem.cs +++ b/src/Umbraco.Web/umbraco.presentation/umbraco/controls/Tree/JTreeContextMenuItem.cs @@ -5,7 +5,6 @@ using System.Text; using Umbraco.Core; using Umbraco.Core.Services; using Umbraco.Web._Legacy.Actions; -using Umbraco.Web._Legacy.Utils; namespace umbraco.controls.Tree { @@ -56,12 +55,6 @@ namespace umbraco.controls.Tree data.Add("icon", a.Icon); } - //required by jsTree - data.Add("visible", JSONSerializer.ToJSONObject("function() {return true;}")); - - //The action handler is what is assigned to the IAction, but for flexibility, we'll call our onContextMenuSelect method which will need to return true if the function is to execute. - data.Add("action", JSONSerializer.ToJSONObject("function(N,T){" + a.JsFunctionName + ";}")); - return data; } diff --git a/src/Umbraco.Web/umbraco.presentation/umbraco/developer/Macros/editMacro.aspx.cs b/src/Umbraco.Web/umbraco.presentation/umbraco/developer/Macros/editMacro.aspx.cs index 9e9d3b1522..08d28617e2 100644 --- a/src/Umbraco.Web/umbraco.presentation/umbraco/developer/Macros/editMacro.aspx.cs +++ b/src/Umbraco.Web/umbraco.presentation/umbraco/developer/Macros/editMacro.aspx.cs @@ -44,7 +44,7 @@ namespace umbraco.cms.presentation.developer if (IsPostBack == false) { ClientTools - .SetActiveTreeType(TreeDefinitionCollection.Instance.FindTree().Tree.Alias) + .SetActiveTreeType(Constants.Trees.Macros) .SyncTree("-1,init," + _macro.Id, false); string tempMacroAssembly = _macro.ControlAssembly ?? ""; @@ -292,7 +292,7 @@ namespace umbraco.cms.presentation.developer Page.Validate(); ClientTools - .SetActiveTreeType(TreeDefinitionCollection.Instance.FindTree().Tree.Alias) + .SetActiveTreeType(Constants.Trees.Macros) .SyncTree("-1,init," + _macro.Id.ToInvariantString(), true); //true forces the reload var tempMacroAssembly = macroAssembly.Text; diff --git a/src/Umbraco.Web/umbraco.presentation/umbraco/developer/Xslt/editXslt.aspx.cs b/src/Umbraco.Web/umbraco.presentation/umbraco/developer/Xslt/editXslt.aspx.cs index 32aee74725..f1ad0e705d 100644 --- a/src/Umbraco.Web/umbraco.presentation/umbraco/developer/Xslt/editXslt.aspx.cs +++ b/src/Umbraco.Web/umbraco.presentation/umbraco/developer/Xslt/editXslt.aspx.cs @@ -30,7 +30,7 @@ namespace umbraco.cms.presentation.developer string file = Request.QueryString["file"]; string path = BaseTree.GetTreePathFromFilePath(file); ClientTools - .SetActiveTreeType(TreeDefinitionCollection.Instance.FindTree().Tree.Alias) + .SetActiveTreeType(Constants.Trees.Xslt) .SyncTree(path, false); } diff --git a/src/Umbraco.Web/umbraco.presentation/umbraco/members/MemberSearch.ascx b/src/Umbraco.Web/umbraco.presentation/umbraco/members/MemberSearch.ascx deleted file mode 100644 index e1c6f6e664..0000000000 --- a/src/Umbraco.Web/umbraco.presentation/umbraco/members/MemberSearch.ascx +++ /dev/null @@ -1,40 +0,0 @@ -<%@ Control Language="C#" AutoEventWireup="True" CodeBehind="MemberSearch.ascx.cs" Inherits="umbraco.presentation.umbraco.members.MemberSearch" %> -<%@ Register TagPrefix="cc1" Namespace="umbraco.uicontrols" Assembly="controls" %> -
-

Member Search

- " alt="Member Search" class="dashboardIcon" /> -

- -

- - - - - - - - - - - - - - - - - - - - - - - - - - - -
<%= Services.TextService.Localize("name") %><%= Services.TextService.Localize("email") %><%= Services.TextService.Localize("login") %>
<%# Eval("Name") %><%# Eval("Email") %><%# Eval("LoginName") %>
<%# Eval("Name") %><%# Eval("Email") %><%# Eval("LoginName") %>
- -
-
-
diff --git a/src/Umbraco.Web/umbraco.presentation/umbraco/members/MemberSearch.ascx.cs b/src/Umbraco.Web/umbraco.presentation/umbraco/members/MemberSearch.ascx.cs deleted file mode 100644 index 167311b944..0000000000 --- a/src/Umbraco.Web/umbraco.presentation/umbraco/members/MemberSearch.ascx.cs +++ /dev/null @@ -1,100 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Web.UI; -using Examine; -using Examine.LuceneEngine.SearchCriteria; -using Examine.SearchCriteria; -using umbraco.cms.businesslogic.member; -using System.Web.Security; -using Umbraco.Core.Security; -using Umbraco.Core.Services; -using Umbraco.Web.UI.Controls; - -namespace umbraco.presentation.umbraco.members -{ - public partial class MemberSearch : UmbracoUserControl - { - protected void Page_Load(object sender, EventArgs e) - { - var provider = MembershipProviderExtensions.GetMembersMembershipProvider(); - - if (provider.IsUmbracoMembershipProvider()) - - ButtonSearch.Text = Services.TextService.Localize("search"); - } - - protected void ButtonSearch_Click(object sender, EventArgs e) - { - resultsPane.Visible = true; - var provider = MembershipProviderExtensions.GetMembersMembershipProvider(); - if (provider.IsUmbracoMembershipProvider()) - { - var query = searchQuery.Text.ToLower(); - var internalSearcher = ExamineManager.Instance.SearchProviderCollection["InternalMemberSearcher"]; - - if (String.IsNullOrEmpty(query) == false) - { - var criteria = internalSearcher.CreateSearchCriteria("member", BooleanOperation.Or); - var fields = new[] {"id", "__nodeName", "email"}; - var term = new[] {query.ToLower().Escape()}; - var operation = criteria.GroupedOr(fields, term).Compile(); - - var results = internalSearcher.Search(operation) - .Select(x => new MemberSearchResult - { - Id = x["id"], - Name = x["nodeName"], - Email = x["email"], - LoginName = x["loginName"] - }); - rp_members.DataSource = results; - rp_members.DataBind(); - } - else - { - resultsPane.Visible = false; - } - } - else - { - IEnumerable results; - if (searchQuery.Text.Contains("@")) - { - results = from MembershipUser x in provider.FindUsersByEmail(searchQuery.Text) - select - new MemberSearchResult() - { - Id = x.UserName, - Email = x.Email, - LoginName = x.UserName, - Name = x.UserName - }; - } - else - { - results = from MembershipUser x in provider.FindUsersByName(searchQuery.Text + "%") - select - new MemberSearchResult() - { - Id = x.UserName, - Email = x.Email, - LoginName = x.UserName, - Name = x.UserName - }; - } - - rp_members.DataSource = results; - rp_members.DataBind(); - } - } - - public class MemberSearchResult - { - public string Id { get; set; } - public string LoginName { get; set; } - public string Name { get; set; } - public string Email { get; set; } - } - } -} \ No newline at end of file diff --git a/src/Umbraco.Web/umbraco.presentation/umbraco/members/MemberSearch.ascx.designer.cs b/src/Umbraco.Web/umbraco.presentation/umbraco/members/MemberSearch.ascx.designer.cs deleted file mode 100644 index 5a80e4c929..0000000000 --- a/src/Umbraco.Web/umbraco.presentation/umbraco/members/MemberSearch.ascx.designer.cs +++ /dev/null @@ -1,51 +0,0 @@ -//------------------------------------------------------------------------------ -// -// This code was generated by a tool. -// -// Changes to this file may cause incorrect behavior and will be lost if -// the code is regenerated. -// -//------------------------------------------------------------------------------ - -namespace umbraco.presentation.umbraco.members { - - - public partial class MemberSearch { - - /// - /// searchQuery control. - /// - /// - /// Auto-generated field. - /// To modify move field declaration from designer file to code-behind file. - /// - protected global::System.Web.UI.WebControls.TextBox searchQuery; - - /// - /// ButtonSearch control. - /// - /// - /// Auto-generated field. - /// To modify move field declaration from designer file to code-behind file. - /// - protected global::System.Web.UI.WebControls.Button ButtonSearch; - - /// - /// resultsPane control. - /// - /// - /// Auto-generated field. - /// To modify move field declaration from designer file to code-behind file. - /// - protected global::umbraco.uicontrols.Pane resultsPane; - - /// - /// rp_members control. - /// - /// - /// Auto-generated field. - /// To modify move field declaration from designer file to code-behind file. - /// - protected global::System.Web.UI.WebControls.Repeater rp_members; - } -} diff --git a/src/Umbraco.Web/umbraco.presentation/umbraco/members/ViewMembers.aspx b/src/Umbraco.Web/umbraco.presentation/umbraco/members/ViewMembers.aspx deleted file mode 100644 index 3dd8012118..0000000000 --- a/src/Umbraco.Web/umbraco.presentation/umbraco/members/ViewMembers.aspx +++ /dev/null @@ -1,41 +0,0 @@ -<%@ Page Title="" Language="C#" MasterPageFile="../masterpages/umbracoPage.Master" AutoEventWireup="true" CodeBehind="ViewMembers.aspx.cs" Inherits="umbraco.presentation.members.ViewMembers" %> - -<%@ Register TagPrefix="cc1" Namespace="umbraco.uicontrols" Assembly="controls" %> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
<%= Services.TextService.Localize("name") %><%= Services.TextService.Localize("email") %><%= Services.TextService.Localize("login") %>
- -
-
-
-
- - diff --git a/src/Umbraco.Web/umbraco.presentation/umbraco/members/ViewMembers.aspx.cs b/src/Umbraco.Web/umbraco.presentation/umbraco/members/ViewMembers.aspx.cs deleted file mode 100644 index a147c12295..0000000000 --- a/src/Umbraco.Web/umbraco.presentation/umbraco/members/ViewMembers.aspx.cs +++ /dev/null @@ -1,103 +0,0 @@ -using Umbraco.Core.Services; -using System; -using System.Web.Security; -using System.Web.UI.WebControls; -using Umbraco.Core; -using Umbraco.Core.Security; - -namespace umbraco.presentation.members -{ - public partial class ViewMembers : Umbraco.Web.UI.Pages.UmbracoEnsuredPage - { - - public ViewMembers() - { - CurrentApp = Constants.Applications.Members.ToString(); - } - - protected void Page_Load(object sender, EventArgs e) - { - panel1.Text = Services.TextService.Localize("member"); - BindRp(); - } - - private void BindRp() - { - var provider = MembershipProviderExtensions.GetMembersMembershipProvider(); - string letter = Request.QueryString["letter"]; - if (string.IsNullOrEmpty(letter) == false) - { - if (provider.IsUmbracoMembershipProvider()) - { - if (letter == "#") - { - rp_members.DataSource = cms.businesslogic.member.Member.getAllOtherMembers(); - } - else - { - rp_members.DataSource = cms.businesslogic.member.Member.getMemberFromFirstLetter(letter.ToCharArray()[0]); - } - } - else - { - rp_members.DataSource = provider.FindUsersByName(letter + "%"); - } - rp_members.DataBind(); - } - } - - public void bindMember(object sender, RepeaterItemEventArgs e) - { - var provider = MembershipProviderExtensions.GetMembersMembershipProvider(); - if (e.Item.ItemType == ListItemType.Item || e.Item.ItemType == ListItemType.AlternatingItem) - { - if (provider.IsUmbracoMembershipProvider()) - { - cms.businesslogic.member.Member mem = (cms.businesslogic.member.Member)e.Item.DataItem; - Literal _name = (Literal)e.Item.FindControl("lt_name"); - Literal _email = (Literal)e.Item.FindControl("lt_email"); - Literal _login = (Literal)e.Item.FindControl("lt_login"); - Button _button = (Button)e.Item.FindControl("bt_delete"); - - _name.Text = "" + mem.Text + ""; - _login.Text = mem.LoginName; - _email.Text = mem.Email; - - _button.CommandArgument = mem.Id.ToString(); - _button.OnClientClick = "return confirm(\"" + Services.TextService.Localize("confirmdelete") + "'" + mem.Text + "' ?\")"; - _button.Text = Services.TextService.Localize("delete"); - } - else - { - var mem = (MembershipUser)e.Item.DataItem; - Literal _name = (Literal)e.Item.FindControl("lt_name"); - Literal _email = (Literal)e.Item.FindControl("lt_email"); - Literal _login = (Literal)e.Item.FindControl("lt_login"); - Button _button = (Button)e.Item.FindControl("bt_delete"); - - _name.Text = "" + mem.UserName + ""; - _login.Text = mem.UserName; - _email.Text = mem.Email; - _button.Visible = false; - - } - } - } - - public void deleteMember(object sender, CommandEventArgs e) - { - int memid = 0; - - if (int.TryParse(e.CommandArgument.ToString(), out memid)) - { - cms.businesslogic.member.Member mem = new global::umbraco.cms.businesslogic.member.Member(memid); - - if (mem != null) - mem.delete(); - - - BindRp(); - } - } - } -} diff --git a/src/Umbraco.Web/umbraco.presentation/umbraco/members/ViewMembers.aspx.designer.cs b/src/Umbraco.Web/umbraco.presentation/umbraco/members/ViewMembers.aspx.designer.cs deleted file mode 100644 index 568431385a..0000000000 --- a/src/Umbraco.Web/umbraco.presentation/umbraco/members/ViewMembers.aspx.designer.cs +++ /dev/null @@ -1,42 +0,0 @@ -//------------------------------------------------------------------------------ -// -// This code was generated by a tool. -// -// Changes to this file may cause incorrect behavior and will be lost if -// the code is regenerated. -// -//------------------------------------------------------------------------------ - -namespace umbraco.presentation.members { - - - public partial class ViewMembers { - - /// - /// panel1 control. - /// - /// - /// Auto-generated field. - /// To modify move field declaration from designer file to code-behind file. - /// - protected global::umbraco.uicontrols.UmbracoPanel panel1; - - /// - /// pane1 control. - /// - /// - /// Auto-generated field. - /// To modify move field declaration from designer file to code-behind file. - /// - protected global::umbraco.uicontrols.Pane pane1; - - /// - /// rp_members control. - /// - /// - /// Auto-generated field. - /// To modify move field declaration from designer file to code-behind file. - /// - protected global::System.Web.UI.WebControls.Repeater rp_members; - } -} diff --git a/src/Umbraco.Web/umbraco.presentation/umbraco/members/search.aspx b/src/Umbraco.Web/umbraco.presentation/umbraco/members/search.aspx deleted file mode 100644 index 2bb21660f0..0000000000 --- a/src/Umbraco.Web/umbraco.presentation/umbraco/members/search.aspx +++ /dev/null @@ -1,13 +0,0 @@ -<%@ Page Language="C#" AutoEventWireup="true" MasterPageFile="../masterpages/umbracoPage.Master" CodeBehind="search.aspx.cs" Inherits="umbraco.presentation.members.search" %> -<%@ Register TagPrefix="cc1" Namespace="umbraco.uicontrols" Assembly="controls" %> -<%@ Register Src="~/umbraco/members/MemberSearch.ascx" TagName="MemberSearch" TagPrefix="umb" %> - - - - - - - - - - diff --git a/src/Umbraco.Web/umbraco.presentation/umbraco/members/search.aspx.cs b/src/Umbraco.Web/umbraco.presentation/umbraco/members/search.aspx.cs deleted file mode 100644 index ccd096aea3..0000000000 --- a/src/Umbraco.Web/umbraco.presentation/umbraco/members/search.aspx.cs +++ /dev/null @@ -1,25 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Web; -using System.Web.UI; -using System.Web.UI.WebControls; -using System.Linq; -using System.Web.Security; -using umbraco.cms.businesslogic.member; -using umbraco.DataLayer.SqlHelpers; -using umbraco.BusinessLogic; -using Examine; -using Umbraco.Core; - -namespace umbraco.presentation.members -{ - - - public partial class search : Umbraco.Web.UI.Pages.UmbracoEnsuredPage - { - public search() - { - CurrentApp = Constants.Applications.Members.ToString(); - } - } -} diff --git a/src/Umbraco.Web/umbraco.presentation/umbraco/members/search.aspx.designer.cs b/src/Umbraco.Web/umbraco.presentation/umbraco/members/search.aspx.designer.cs deleted file mode 100644 index 115302af0d..0000000000 --- a/src/Umbraco.Web/umbraco.presentation/umbraco/members/search.aspx.designer.cs +++ /dev/null @@ -1,24 +0,0 @@ -//------------------------------------------------------------------------------ -// -// This code was generated by a tool. -// -// Changes to this file may cause incorrect behavior and will be lost if -// the code is regenerated. -// -//------------------------------------------------------------------------------ - -namespace umbraco.presentation.members { - - - public partial class search { - - /// - /// Panel2 control. - /// - /// - /// Auto-generated field. - /// To modify move field declaration from designer file to code-behind file. - /// - protected global::umbraco.uicontrols.UmbracoPanel Panel2; - } -} diff --git a/src/Umbraco.Web/umbraco.presentation/umbraco/ping.aspx.cs b/src/Umbraco.Web/umbraco.presentation/umbraco/ping.aspx.cs new file mode 100644 index 0000000000..410ada9f4d --- /dev/null +++ b/src/Umbraco.Web/umbraco.presentation/umbraco/ping.aspx.cs @@ -0,0 +1,38 @@ +using System; +using System.Collections; +using System.ComponentModel; +using System.Data; +using System.Drawing; +using System.Web; +using System.Web.SessionState; +using System.Web.UI; +using System.Web.UI.WebControls; +using System.Web.UI.HtmlControls; + +namespace umbraco.presentation +{ + + [Obsolete("This class will be removed in future versions.")] + [EditorBrowsable(EditorBrowsableState.Never)] + public partial class ping : System.Web.UI.Page + { + #region Web Form Designer generated code + override protected void OnInit(EventArgs e) + { + // + // CODEGEN: This call is required by the ASP.NET Web Form Designer. + // + InitializeComponent(); + base.OnInit(e); + } + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + } + #endregion + } +} diff --git a/src/Umbraco.Web/umbraco.presentation/umbraco/settings/EditDictionaryItem.aspx.cs b/src/Umbraco.Web/umbraco.presentation/umbraco/settings/EditDictionaryItem.aspx.cs index b5bed0d759..2d63a6593b 100644 --- a/src/Umbraco.Web/umbraco.presentation/umbraco/settings/EditDictionaryItem.aspx.cs +++ b/src/Umbraco.Web/umbraco.presentation/umbraco/settings/EditDictionaryItem.aspx.cs @@ -4,6 +4,7 @@ using System.Web.UI.WebControls; using umbraco.cms.presentation.Trees; using Umbraco.Core; using Umbraco.Core.Services; +using Umbraco.Web; using Umbraco.Web.UI; namespace umbraco.settings @@ -61,8 +62,8 @@ namespace umbraco.settings { var path = BuildPath(currentItem); ClientTools - .SetActiveTreeType(TreeDefinitionCollection.Instance.FindTree().Tree.Alias) - .SyncTree(path, false); + .SetActiveTreeType(Constants.Trees.Dictionary) + .SyncTree(path, false); } diff --git a/src/Umbraco.Web/umbraco.presentation/umbraco/settings/editTemplate.aspx.cs b/src/Umbraco.Web/umbraco.presentation/umbraco/settings/editTemplate.aspx.cs index 77883c7312..9e0ed6d4bc 100644 --- a/src/Umbraco.Web/umbraco.presentation/umbraco/settings/editTemplate.aspx.cs +++ b/src/Umbraco.Web/umbraco.presentation/umbraco/settings/editTemplate.aspx.cs @@ -1,6 +1,7 @@ using System; using System.Collections.Generic; using System.IO; +using System.Linq; using System.Web.UI; using System.Web.UI.WebControls; using Umbraco.Core; @@ -194,8 +195,15 @@ namespace umbraco.cms.presentation.settings private void LoadMacros() { - var macroRenderings = - DatabaseContext.Database.Fetch("select id, macroAlias, macroName from cmsMacro order by macroName"); + ; + var macroRenderings = + Services.MacroService.GetAll() + .Select(x => new TempMacroClass() + { + id = x.Id, + macroAlias = x.Alias, + macroName = x.Name + }); rpt_macros.DataSource = macroRenderings; rpt_macros.DataBind(); diff --git a/src/Umbraco.Web/umbraco.presentation/umbraco/settings/scripts/editScript.aspx.cs b/src/Umbraco.Web/umbraco.presentation/umbraco/settings/scripts/editScript.aspx.cs index b6db5cdf8c..cd6d7159aa 100644 --- a/src/Umbraco.Web/umbraco.presentation/umbraco/settings/scripts/editScript.aspx.cs +++ b/src/Umbraco.Web/umbraco.presentation/umbraco/settings/scripts/editScript.aspx.cs @@ -65,7 +65,7 @@ namespace umbraco.cms.presentation.settings.scripts if (IsPostBack == false) { ClientTools - .SetActiveTreeType(TreeDefinitionCollection.Instance.FindTree().Tree.Alias) + .SetActiveTreeType(Constants.Trees.Scripts) .SyncTree(ScriptTreeSyncPath, false); } } diff --git a/src/Umbraco.Web/umbraco.presentation/umbraco/settings/stylesheet/editstylesheet.aspx.cs b/src/Umbraco.Web/umbraco.presentation/umbraco/settings/stylesheet/editstylesheet.aspx.cs index 5d24cef82a..9b2a5590ce 100644 --- a/src/Umbraco.Web/umbraco.presentation/umbraco/settings/stylesheet/editstylesheet.aspx.cs +++ b/src/Umbraco.Web/umbraco.presentation/umbraco/settings/stylesheet/editstylesheet.aspx.cs @@ -60,7 +60,7 @@ namespace umbraco.cms.presentation.settings.stylesheet lttPath.Text = "" + stylesheet.VirtualPath + ""; editorSource.Text = stylesheet.Content; - TreeSyncPath = BaseTree.GetTreePathFromFilePath(filename).TrimEnd(".css"); + TreeSyncPath = BaseTree.GetTreePathFromFilePath(filename); // name derives from path, without the .css extension, clean for xss NameTxt.Text = stylesheet.Path.TrimEnd(".css").CleanForXss('\\', '/'); diff --git a/src/Umbraco.Web/umbraco.presentation/umbraco/settings/stylesheet/property/EditStyleSheetProperty.aspx.cs b/src/Umbraco.Web/umbraco.presentation/umbraco/settings/stylesheet/property/EditStyleSheetProperty.aspx.cs index eb284c5ea5..780f63e469 100644 --- a/src/Umbraco.Web/umbraco.presentation/umbraco/settings/stylesheet/property/EditStyleSheetProperty.aspx.cs +++ b/src/Umbraco.Web/umbraco.presentation/umbraco/settings/stylesheet/property/EditStyleSheetProperty.aspx.cs @@ -41,7 +41,7 @@ namespace umbraco.cms.presentation.settings.stylesheet protected override void OnLoad(EventArgs e) { base.OnLoad(e); - + _sheet = Services.FileService.GetStylesheetByName(Request.QueryString["id"]); if (_sheet == null) throw new InvalidOperationException("No stylesheet found with name: " + Request.QueryString["id"]); @@ -70,9 +70,9 @@ namespace umbraco.cms.presentation.settings.stylesheet prStyles.Attributes["style"] = _stylesheetproperty.Value; - var nodePath = string.Format("-1,init,{0},{0}_{1}", _sheet.Path - //needs a double escape to work with JS - .Replace("\\", "\\\\").TrimEnd(".css"), _stylesheetproperty.Name); + var path = _sheet.Path.Replace('\\', '/'); + var nodePath = string.Format(BaseTree.GetTreePathFromFilePath(path) + + ",{0}_{1}", path, _stylesheetproperty.Name); ClientTools .SetActiveTreeType(Constants.Trees.Stylesheets) diff --git a/src/Umbraco.Web/umbraco.presentation/umbraco/users/EditUser.aspx.cs b/src/Umbraco.Web/umbraco.presentation/umbraco/users/EditUser.aspx.cs index bbae68379c..7ec80470a7 100644 --- a/src/Umbraco.Web/umbraco.presentation/umbraco/users/EditUser.aspx.cs +++ b/src/Umbraco.Web/umbraco.presentation/umbraco/users/EditUser.aspx.cs @@ -214,8 +214,8 @@ namespace umbraco.cms.presentation.user SetupForm(); ClientTools - .SetActiveTreeType(TreeDefinitionCollection.Instance.FindTree().Tree.Alias) - .SyncTree(UID.ToString(), IsPostBack); + .SetActiveTreeType(Constants.Trees.Users) + .SyncTree(UID.ToString(), false); } diff --git a/src/Umbraco.Web/umbraco.presentation/umbraco/webservices/CacheRefresher.asmx.cs b/src/Umbraco.Web/umbraco.presentation/umbraco/webservices/CacheRefresher.asmx.cs index fdd4a71f5d..254c9bbcbd 100644 --- a/src/Umbraco.Web/umbraco.presentation/umbraco/webservices/CacheRefresher.asmx.cs +++ b/src/Umbraco.Web/umbraco.presentation/umbraco/webservices/CacheRefresher.asmx.cs @@ -59,7 +59,7 @@ namespace umbraco.presentation.webservices return jsonRefresher; } - private bool NotAutorized(string login, string rawPassword) + private bool Authorized(string login, string rawPassword) { //TODO: This technique of passing the raw password in is a legacy idea and isn't really // a very happy way to secure this webservice. To prevent brute force attacks, we need @@ -91,7 +91,7 @@ namespace umbraco.presentation.webservices [WebMethod] public void BulkRefresh(RefreshInstruction[] instructions, string appId, string login, string password) { - if (NotAutorized(login, password)) return; + if (Authorized(login, password) == false) return; if (SelfMessage(appId)) return; // do not process self-messages // only execute distinct instructions - no sense in running the same one more than once @@ -130,29 +130,29 @@ namespace umbraco.presentation.webservices [WebMethod] public void RefreshAll(Guid uniqueIdentifier, string Login, string Password) { - if (NotAutorized(Login, Password)) return; + if (Authorized(Login, Password) == false) return; GetRefresher(uniqueIdentifier).RefreshAll(); } [WebMethod] public void RefreshByGuid(Guid uniqueIdentifier, Guid Id, string Login, string Password) { - if (NotAutorized(Login, Password)) return; + if (Authorized(Login, Password) == false) return; GetRefresher(uniqueIdentifier).Refresh(Id); } [WebMethod] public void RefreshById(Guid uniqueIdentifier, int Id, string Login, string Password) { - if (NotAutorized(Login, Password)) return; + if (Authorized(Login, Password) == false) return; GetRefresher(uniqueIdentifier).Refresh(Id); } [WebMethod] public void RefreshByIds(Guid uniqueIdentifier, string jsonIds, string Login, string Password) { - if (NotAutorized(Login, Password)) return; - var refresher = GetRefresher(uniqueIdentifier); + if (Authorized(Login, Password) == false) return; + var refresher = GetRefresher(uniqueIdentifier); foreach (var id in JsonConvert.DeserializeObject(jsonIds)) refresher.Refresh(id); } @@ -160,21 +160,21 @@ namespace umbraco.presentation.webservices [WebMethod] public void RefreshByJson(Guid uniqueIdentifier, string jsonPayload, string Login, string Password) { - if (NotAutorized(Login, Password)) return; + if (Authorized(Login, Password) == false) return; GetJsonRefresher(uniqueIdentifier).Refresh(jsonPayload); } [WebMethod] public void RemoveById(Guid uniqueIdentifier, int Id, string Login, string Password) { - if (NotAutorized(Login, Password)) return; + if (Authorized(Login, Password) == false) return; GetRefresher(uniqueIdentifier).Remove(Id); } [WebMethod] public XmlDocument GetRefreshers(string Login, string Password) { - if (NotAutorized(Login, Password)) return null; + if (Authorized(Login, Password) == false) return null; var xd = new XmlDocument(); xd.LoadXml(""); diff --git a/src/UmbracoExamine/UmbracoExamine.csproj b/src/UmbracoExamine/UmbracoExamine.csproj index d231ee4d6c..7fa5c1952b 100644 --- a/src/UmbracoExamine/UmbracoExamine.csproj +++ b/src/UmbracoExamine/UmbracoExamine.csproj @@ -135,12 +135,21 @@ True + + ..\packages\Newtonsoft.Json.7.0.1\lib\net45\Newtonsoft.Json.dll + True + + + ..\packages\NPoco.3.1.0-u005\lib\net45\NPoco.dll + True + 3.5 + diff --git a/src/UmbracoExamine/UmbracoMemberIndexer.cs b/src/UmbracoExamine/UmbracoMemberIndexer.cs index 40a91c5630..eb76d0253b 100644 --- a/src/UmbracoExamine/UmbracoMemberIndexer.cs +++ b/src/UmbracoExamine/UmbracoMemberIndexer.cs @@ -20,7 +20,7 @@ using IMediaService = Umbraco.Core.Services.IMediaService; namespace UmbracoExamine { - + /// /// Custom indexer for members /// @@ -83,7 +83,7 @@ namespace UmbracoExamine if (indexerData.UserFields.Any(x => x.Name == "_searchEmail") == false) { - var field = new IndexField {Name = "_searchEmail"}; + var field = new IndexField { Name = "_searchEmail" }; var policy = IndexFieldPolicies.FirstOrDefault(x => x.Name == "_searchEmail"); if (policy != null) { @@ -93,7 +93,7 @@ namespace UmbracoExamine return new IndexCriteria( indexerData.StandardFields, - indexerData.UserFields.Concat(new[] {field}), + indexerData.UserFields.Concat(new[] { field }), indexerData.IncludeNodeTypes, indexerData.ExcludeNodeTypes, indexerData.ParentNodeId @@ -101,7 +101,7 @@ namespace UmbracoExamine } } - return indexerData; + return indexerData; } /// @@ -124,7 +124,7 @@ namespace UmbracoExamine //This only supports members if (SupportedTypes.Contains(type) == false) return; - + const int pageSize = 1000; var pageIndex = 0; @@ -138,7 +138,7 @@ namespace UmbracoExamine do { long total; - members = _memberService.GetAll(pageIndex, pageSize, out total, "LoginName", Direction.Ascending, nodeType).ToArray(); + members = _memberService.GetAll(pageIndex, pageSize, out total, "LoginName", Direction.Ascending, true, null, nodeType).ToArray(); AddNodesToIndex(GetSerializedMembers(members), type); @@ -158,8 +158,8 @@ namespace UmbracoExamine pageIndex++; } while (members.Length == pageSize); - } - } + } + } private IEnumerable GetSerializedMembers(IEnumerable members) { @@ -195,7 +195,7 @@ namespace UmbracoExamine if (e.Fields.ContainsKey("_searchEmail") == false) e.Fields.Add("_searchEmail", e.Node.Attribute("email").Value.Replace(".", " ").Replace("@", " ")); } - + if (e.Fields.ContainsKey(IconFieldName) == false) e.Fields.Add(IconFieldName, (string)e.Node.Attribute("icon")); } diff --git a/src/UmbracoExamine/packages.config b/src/UmbracoExamine/packages.config index 37c785fb96..dde0147e85 100644 --- a/src/UmbracoExamine/packages.config +++ b/src/UmbracoExamine/packages.config @@ -3,5 +3,7 @@ + + \ No newline at end of file diff --git a/src/umbraco.cms/packages.config b/src/umbraco.cms/packages.config index c00e2f0c3d..12c1341ac8 100644 --- a/src/umbraco.cms/packages.config +++ b/src/umbraco.cms/packages.config @@ -3,5 +3,6 @@ + \ No newline at end of file diff --git a/src/umbraco.cms/umbraco.cms.csproj b/src/umbraco.cms/umbraco.cms.csproj index 492272eb1d..c261253c33 100644 --- a/src/umbraco.cms/umbraco.cms.csproj +++ b/src/umbraco.cms/umbraco.cms.csproj @@ -123,6 +123,10 @@ ..\packages\Newtonsoft.Json.8.0.3\lib\net45\Newtonsoft.Json.dll True + + ..\packages\NPoco.3.1.0-u005\lib\net45\NPoco.dll + True + System @@ -134,6 +138,7 @@ System.Data + System.Security