diff --git a/src/Umbraco.Core/ActionsResolver.cs b/src/Umbraco.Core/ActionsResolver.cs index 50c9fbe9a1..ff34f62c60 100644 --- a/src/Umbraco.Core/ActionsResolver.cs +++ b/src/Umbraco.Core/ActionsResolver.cs @@ -2,6 +2,7 @@ using System; using System.Collections.Generic; using System.Linq; using System.Reflection; +using Umbraco.Core.Logging; using Umbraco.Core.ObjectResolution; using umbraco.interfaces; @@ -12,13 +13,14 @@ namespace Umbraco.Core /// internal sealed class ActionsResolver : LazyManyObjectsResolverBase { - - /// - /// Constructor - /// - /// - internal ActionsResolver(Func> packageActions) - : base(packageActions) + /// + /// Constructor + /// + /// + /// + /// + internal ActionsResolver(IServiceProvider serviceProvider, ILogger logger, Func> packageActions) + : base(serviceProvider, logger, packageActions) { } @@ -55,7 +57,7 @@ namespace Umbraco.Core var instance = type.GetProperty("Instance", BindingFlags.Public | BindingFlags.Static); //if the singletone initializer is not found, try simply creating an instance of the IAction if it supports public constructors if (instance == null) - typeInstance = PluginManager.Current.CreateInstance(type); + typeInstance = ServiceProvider.GetService(type) as IAction; else typeInstance = instance.GetValue(null, null) as IAction; diff --git a/src/Umbraco.Core/ActivatorHelper.cs b/src/Umbraco.Core/ActivatorHelper.cs index 88ec01ae35..90a21f7386 100644 --- a/src/Umbraco.Core/ActivatorHelper.cs +++ b/src/Umbraco.Core/ActivatorHelper.cs @@ -1,8 +1,6 @@ -using System; - namespace Umbraco.Core { - /// + /// /// Helper methods for Activation /// internal static class ActivatorHelper @@ -14,7 +12,9 @@ namespace Umbraco.Core /// public static T CreateInstance() where T : class, new() { - return Activator.CreateInstance(typeof(T)) as T; + return new ActivatorServiceProvider().GetService(typeof (T)) as T; } + + } } \ No newline at end of file diff --git a/src/Umbraco.Core/ActivatorServiceProvider.cs b/src/Umbraco.Core/ActivatorServiceProvider.cs new file mode 100644 index 0000000000..550a4a3ca8 --- /dev/null +++ b/src/Umbraco.Core/ActivatorServiceProvider.cs @@ -0,0 +1,12 @@ +using System; + +namespace Umbraco.Core +{ + internal class ActivatorServiceProvider : IServiceProvider + { + public object GetService(Type serviceType) + { + return Activator.CreateInstance(serviceType); + } + } +} \ No newline at end of file diff --git a/src/Umbraco.Core/ApplicationContext.cs b/src/Umbraco.Core/ApplicationContext.cs index 1ff21615bc..8dfc2536e9 100644 --- a/src/Umbraco.Core/ApplicationContext.cs +++ b/src/Umbraco.Core/ApplicationContext.cs @@ -8,6 +8,7 @@ using Umbraco.Core.Configuration; using Umbraco.Core.Configuration.UmbracoSettings; using Umbraco.Core.Logging; using Umbraco.Core.ObjectResolution; +using Umbraco.Core.Profiling; using Umbraco.Core.Services; @@ -21,21 +22,35 @@ namespace Umbraco.Core /// public class ApplicationContext : IDisposable { - /// /// Constructor /// /// /// /// - public ApplicationContext(DatabaseContext dbContext, ServiceContext serviceContext, CacheHelper cache) - { + /// + public ApplicationContext(DatabaseContext dbContext, ServiceContext serviceContext, CacheHelper cache, ProfilingLogger logger) + { if (dbContext == null) throw new ArgumentNullException("dbContext"); if (serviceContext == null) throw new ArgumentNullException("serviceContext"); if (cache == null) throw new ArgumentNullException("cache"); _databaseContext = dbContext; _services = serviceContext; ApplicationCache = cache; + ProfilingLogger = logger; + } + + /// + /// Constructor + /// + /// + /// + /// + [Obsolete("Use the other constructor specifying an ILogger instead")] + public ApplicationContext(DatabaseContext dbContext, ServiceContext serviceContext, CacheHelper cache) + : this(dbContext, serviceContext, cache, + new ProfilingLogger(LoggerResolver.Current.Logger, ProfilerResolver.Current.Profiler)) + { } /// @@ -83,6 +98,7 @@ namespace Umbraco.Core /// /// This is NOT thread safe /// + [Obsolete("Use the other method specifying an ProfilingLogger instead")] public static ApplicationContext EnsureContext(DatabaseContext dbContext, ServiceContext serviceContext, CacheHelper cache, bool replaceContext) { if (ApplicationContext.Current != null) @@ -95,6 +111,33 @@ namespace Umbraco.Core return ApplicationContext.Current; } + /// + /// A method used to create and ensure that a global ApplicationContext singleton is created. + /// + /// + /// + /// + /// If set to true will replace the current singleton instance - This should only be used for unit tests or on app + /// startup if for some reason the boot manager is not the umbraco boot manager. + /// + /// + /// + /// + /// + /// This is NOT thread safe + /// + public static ApplicationContext EnsureContext(DatabaseContext dbContext, ServiceContext serviceContext, CacheHelper cache, ProfilingLogger logger, bool replaceContext) + { + if (ApplicationContext.Current != null) + { + if (!replaceContext) + return ApplicationContext.Current; + } + var ctx = new ApplicationContext(dbContext, serviceContext, cache, logger); + ApplicationContext.Current = ctx; + return ApplicationContext.Current; + } + /// /// Singleton accessor /// @@ -108,7 +151,13 @@ namespace Umbraco.Core /// public CacheHelper ApplicationCache { get; private set; } - // IsReady is set to true by the boot manager once it has successfully booted + /// + /// Exposes the global ProfilingLogger - this should generally not be accessed via the UmbracoContext and should normally just be exposed + /// on most base classes or injected with IoC + /// + public ProfilingLogger ProfilingLogger { get; private set; } + + // IsReady is set to true by the boot manager once it has successfully booted // note - the original umbraco module checks on content.Instance in umbraco.dll // now, the boot task that setup the content store ensures that it is ready bool _isReady = false; @@ -180,7 +229,7 @@ namespace Umbraco.Core if (currentVersion != configStatus) { - LogHelper.Info("CurrentVersion different from configStatus: '" + currentVersion + "','" + configStatus + "'"); + ProfilingLogger.Logger.Info("CurrentVersion different from configStatus: '" + currentVersion + "','" + configStatus + "'"); } diff --git a/src/Umbraco.Core/Cache/CacheKeys.cs b/src/Umbraco.Core/Cache/CacheKeys.cs index c1f82b0d89..c370b13303 100644 --- a/src/Umbraco.Core/Cache/CacheKeys.cs +++ b/src/Umbraco.Core/Cache/CacheKeys.cs @@ -45,11 +45,14 @@ namespace Umbraco.Core.Cache public const string PropertyTypeCacheKey = "UmbracoPropertyTypeCache"; + [Obsolete("This is no longer used and will be removed from the codebase in the future")] public const string LanguageCacheKey = "UmbracoLanguageCache"; public const string DomainCacheKey = "UmbracoDomainList"; + [Obsolete("This is no longer used and will be removed from the codebase in the future")] public const string StylesheetCacheKey = "UmbracoStylesheet"; + [Obsolete("This is no longer used and will be removed from the codebase in the future")] public const string StylesheetPropertyCacheKey = "UmbracoStylesheetProperty"; public const string DataTypeCacheKey = "UmbracoDataTypeDefinition"; diff --git a/src/Umbraco.Core/CacheRefreshersResolver.cs b/src/Umbraco.Core/CacheRefreshersResolver.cs index e8df98fc1b..4047a06b62 100644 --- a/src/Umbraco.Core/CacheRefreshersResolver.cs +++ b/src/Umbraco.Core/CacheRefreshersResolver.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using Umbraco.Core.Logging; using Umbraco.Core.ObjectResolution; using umbraco.interfaces; @@ -12,13 +13,14 @@ namespace Umbraco.Core /// internal sealed class CacheRefreshersResolver : LegacyTransientObjectsResolver { - - /// - /// Constructor - /// - /// - internal CacheRefreshersResolver(Func> refreshers) - : base(refreshers) + /// + /// Constructor + /// + /// + /// + /// + internal CacheRefreshersResolver(IServiceProvider serviceProvider, ILogger logger, Func> refreshers) + : base(serviceProvider, logger, refreshers) { } diff --git a/src/Umbraco.Core/Configuration/ClientDependencyConfiguration.cs b/src/Umbraco.Core/Configuration/ClientDependencyConfiguration.cs index acd691308a..6fbdec6901 100644 --- a/src/Umbraco.Core/Configuration/ClientDependencyConfiguration.cs +++ b/src/Umbraco.Core/Configuration/ClientDependencyConfiguration.cs @@ -8,10 +8,13 @@ namespace Umbraco.Core.Configuration { internal class ClientDependencyConfiguration { + private readonly ILogger _logger; private readonly string _fileName; - public ClientDependencyConfiguration() + public ClientDependencyConfiguration(ILogger logger) { + if (logger == null) throw new ArgumentNullException("logger"); + _logger = logger; _fileName = IOHelper.MapPath(string.Format("{0}/ClientDependency.config", SystemDirectories.Config)); } @@ -35,13 +38,13 @@ namespace Umbraco.Core.Configuration versionAttribute.SetValue(newVersion); clientDependencyConfigXml.Save(_fileName, SaveOptions.DisableFormatting); - LogHelper.Info(string.Format("Updated version number from {0} to {1}", oldVersion, newVersion)); + _logger.Info(string.Format("Updated version number from {0} to {1}", oldVersion, newVersion)); return true; } } catch (Exception ex) { - LogHelper.Error("Couldn't update ClientDependency version number", ex); + _logger.Error("Couldn't update ClientDependency version number", ex); } return false; diff --git a/src/Umbraco.Core/Configuration/UmbracoSettings/ITemplatesSection.cs b/src/Umbraco.Core/Configuration/UmbracoSettings/ITemplatesSection.cs index f6d104d291..a80fc6d2c7 100644 --- a/src/Umbraco.Core/Configuration/UmbracoSettings/ITemplatesSection.cs +++ b/src/Umbraco.Core/Configuration/UmbracoSettings/ITemplatesSection.cs @@ -1,4 +1,6 @@ -namespace Umbraco.Core.Configuration.UmbracoSettings +using System; + +namespace Umbraco.Core.Configuration.UmbracoSettings { public interface ITemplatesSection : IUmbracoConfigurationSection { @@ -8,6 +10,7 @@ RenderingEngine DefaultRenderingEngine { get; } + [Obsolete("This has no affect and will be removed in future versions")] bool EnableTemplateFolders { get; } } } \ No newline at end of file diff --git a/src/Umbraco.Core/Configuration/UmbracoSettings/TemplatesElement.cs b/src/Umbraco.Core/Configuration/UmbracoSettings/TemplatesElement.cs index 31c374ce6c..c7eb659766 100644 --- a/src/Umbraco.Core/Configuration/UmbracoSettings/TemplatesElement.cs +++ b/src/Umbraco.Core/Configuration/UmbracoSettings/TemplatesElement.cs @@ -1,4 +1,5 @@ -using System.Configuration; +using System; +using System.Configuration; namespace Umbraco.Core.Configuration.UmbracoSettings { @@ -40,6 +41,7 @@ namespace Umbraco.Core.Configuration.UmbracoSettings } } + [Obsolete("This has no affect and will be removed in future versions")] [ConfigurationProperty("enableTemplateFolders")] internal InnerTextConfigurationElement EnableTemplateFolders { @@ -67,6 +69,7 @@ namespace Umbraco.Core.Configuration.UmbracoSettings get { return DefaultRenderingEngine; } } + [Obsolete("This has no affect and will be removed in future versions")] bool ITemplatesSection.EnableTemplateFolders { get { return EnableTemplateFolders; } diff --git a/src/Umbraco.Core/Constants-Applications.cs b/src/Umbraco.Core/Constants-Applications.cs index c32dba0ca3..f03108f4ac 100644 --- a/src/Umbraco.Core/Constants-Applications.cs +++ b/src/Umbraco.Core/Constants-Applications.cs @@ -78,12 +78,12 @@ /// public const string Dictionary = "dictionary"; - //TODO: Fill in the rest! + public const string Stylesheets = "stylesheets"; /// - /// alias for the media tree. + /// alias for the template tree. /// - public const string Templates = "template"; + public const string Templates = "templates"; public const string RelationTypes = "relationTypes"; @@ -91,6 +91,7 @@ public const string Languages = "languages"; + //TODO: Fill in the rest! } } diff --git a/src/Umbraco.Core/Constants-Conventions.cs b/src/Umbraco.Core/Constants-Conventions.cs index 59cec787f6..bcf012e42f 100644 --- a/src/Umbraco.Core/Constants-Conventions.cs +++ b/src/Umbraco.Core/Constants-Conventions.cs @@ -11,6 +11,14 @@ namespace Umbraco.Core /// public static class Conventions { + public static class Localization + { + /// + /// The root id for all top level dictionary items + /// + public const string DictionaryItemRootId = "41c7638d-f529-4bff-853e-59a0c2fb1bde"; + } + public static class DataTypes { public const string ListViewPrefix = "List View - "; @@ -293,7 +301,7 @@ namespace Umbraco.Core } /// - /// Defines the alias identifiers for Umbraco relation types. + /// Defines the alias identifiers for built-in Umbraco relation types. /// public static class RelationTypes { @@ -306,6 +314,16 @@ namespace Umbraco.Core /// ContentType alias for default relation type "Relate Document On Copy". /// public const string RelateDocumentOnCopyAlias = "relateDocumentOnCopy"; + + /// + /// ContentType name for default relation type "Relate Parent Document On Delete". + /// + public const string RelateParentDocumentOnDeleteName = "Relate Parent Document On Delete"; + + /// + /// ContentType alias for default relation type "Relate Parent Document On Delete". + /// + public const string RelateParentDocumentOnDeleteAlias = "relateParentDocumentOnDelete"; } } } diff --git a/src/Umbraco.Core/Constants-ObjectTypes.cs b/src/Umbraco.Core/Constants-ObjectTypes.cs index e11ba8d7ad..81bd66928d 100644 --- a/src/Umbraco.Core/Constants-ObjectTypes.cs +++ b/src/Umbraco.Core/Constants-ObjectTypes.cs @@ -1,4 +1,6 @@ -namespace Umbraco.Core +using System; + +namespace Umbraco.Core { public static partial class Constants { @@ -70,7 +72,11 @@ /// /// Guid for a Stylesheet object. /// - public const string Stylesheet = "9F68DA4F-A3A8-44C2-8226-DCBD125E4840"; + [Obsolete("This no longer exists in the database")] + public const string Stylesheet = "9F68DA4F-A3A8-44C2-8226-DCBD125E4840"; + + [Obsolete("This no longer exists in the database")] + internal const string StylesheetProperty = "5555da4f-a123-42b2-4488-dcdfb25e4111"; /// /// Guid for the System Root. diff --git a/src/Umbraco.Core/CoreBootManager.cs b/src/Umbraco.Core/CoreBootManager.cs index aeb13dd814..4e55bb86a9 100644 --- a/src/Umbraco.Core/CoreBootManager.cs +++ b/src/Umbraco.Core/CoreBootManager.cs @@ -29,66 +29,90 @@ using MigrationsVersionFourNineZero = Umbraco.Core.Persistence.Migrations.Upgrad namespace Umbraco.Core { /// - /// 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 DisposableTimer _timer; - private bool _isInitialized = false; - private bool _isStarted = false; - private bool _isComplete = false; + /// 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 ProfilingLogger _profilingLogger; + private DisposableTimer _timer; + private bool _isInitialized = false; + private bool _isStarted = false; + private bool _isComplete = false; + private readonly IServiceProvider _serviceProvider = new ActivatorServiceProvider(); private readonly UmbracoApplicationBase _umbracoApplication; - protected ApplicationContext ApplicationContext { get; set; } + protected ApplicationContext ApplicationContext { get; set; } protected CacheHelper ApplicationCache { get; set; } + protected PluginManager PluginManager { get; private set; } - protected UmbracoApplicationBase UmbracoApplication - { - get { return _umbracoApplication; } - } + protected UmbracoApplicationBase UmbracoApplication + { + get { return _umbracoApplication; } + } - public CoreBootManager(UmbracoApplicationBase umbracoApplication) - { + protected IServiceProvider ServiceProvider + { + get { return _serviceProvider; } + } + + public CoreBootManager(UmbracoApplicationBase umbracoApplication) + { if (umbracoApplication == null) throw new ArgumentNullException("umbracoApplication"); _umbracoApplication = umbracoApplication; } - public virtual IBootManager Initialize() - { - if (_isInitialized) - throw new InvalidOperationException("The boot manager has already been initialized"); + public virtual IBootManager Initialize() + { + if (_isInitialized) + throw new InvalidOperationException("The boot manager has already been initialized"); - InitializeProfilerResolver(); + InitializeLoggerResolver(); + InitializeProfilerResolver(); - _timer = DisposableTimer.DebugDuration("Umbraco application starting", "Umbraco application startup complete"); - - CreateApplicationCache(); + _profilingLogger = new ProfilingLogger(LoggerResolver.Current.Logger, ProfilerResolver.Current.Profiler); + + _timer = _profilingLogger.DebugDuration("Umbraco application starting", "Umbraco application startup complete"); + + CreateApplicationCache(); + + //create and set the plugin manager (I'd much prefer to not use this singleton anymore but many things are using it unfortunately and + // the way that it is setup, there must only ever be one per app so without IoC it would be hard to make this not a singleton) + PluginManager = new PluginManager(ServiceProvider, ApplicationCache.RuntimeCache, _profilingLogger); + PluginManager.Current = PluginManager; //Create the legacy prop-eds mapping LegacyPropertyEditorIdToAliasConverter.CreateMappingsForCoreEditors(); LegacyParameterEditorAliasConverter.CreateMappingsForCoreEditors(); - //create database and service contexts for the app context - var dbFactory = new DefaultDatabaseFactory(GlobalSettings.UmbracoConnectionName); - Database.Mapper = new PetaPocoMapper(); - var dbContext = new DatabaseContext(dbFactory); - var serviceContext = new ServiceContext( - new PetaPocoUnitOfWorkProvider(dbFactory), - new FileUnitOfWorkProvider(), - new PublishingStrategy(), - ApplicationCache); + //create database and service contexts for the app context + var dbFactory = new DefaultDatabaseFactory(GlobalSettings.UmbracoConnectionName, LoggerResolver.Current.Logger); + Database.Mapper = new PetaPocoMapper(); + + var dbContext = new DatabaseContext( + dbFactory, + LoggerResolver.Current.Logger, + SqlSyntaxProviders.CreateDefault(LoggerResolver.Current.Logger)); + + //initialize the DatabaseContext + dbContext.Initialize(); + + var serviceContext = new ServiceContext( + new RepositoryFactory(ApplicationCache, LoggerResolver.Current.Logger, dbContext.SqlSyntax, UmbracoConfig.For.UmbracoSettings()), + new PetaPocoUnitOfWorkProvider(dbFactory), + new FileUnitOfWorkProvider(), + new PublishingStrategy(), + ApplicationCache, + LoggerResolver.Current.Logger); CreateApplicationContext(dbContext, serviceContext); InitializeApplicationEventsResolver(); - InitializeResolvers(); + InitializeResolvers(); - //initialize the DatabaseContext - dbContext.Initialize(); + InitializeModelMappers(); @@ -96,10 +120,10 @@ namespace Umbraco.Core ApplicationEventsResolver.Current.ApplicationEventHandlers .ForEach(x => x.OnApplicationInitialized(UmbracoApplication, ApplicationContext)); - _isInitialized = true; + _isInitialized = true; - return this; - } + return this; + } /// /// Creates and assigns the application context singleton @@ -109,7 +133,7 @@ namespace Umbraco.Core protected virtual void CreateApplicationContext(DatabaseContext dbContext, ServiceContext serviceContext) { //create the ApplicationContext - ApplicationContext = ApplicationContext.Current = new ApplicationContext(dbContext, serviceContext, ApplicationCache); + ApplicationContext = ApplicationContext.Current = new ApplicationContext(dbContext, serviceContext, ApplicationCache, _profilingLogger); } /// @@ -120,7 +144,7 @@ namespace Umbraco.Core var cacheHelper = new CacheHelper( new ObjectCacheRuntimeCacheProvider(), new StaticCacheProvider(), - //we have no request based cache when not running in web-based context + //we have no request based cache when not running in web-based context new NullCacheProvider()); ApplicationCache = cacheHelper; @@ -144,18 +168,31 @@ namespace Umbraco.Core }); } + /// + /// Special method to initialize the LoggerResolver + /// + protected virtual void InitializeLoggerResolver() + { + LoggerResolver.Current = new LoggerResolver(Logger.CreateWithDefaultLog4NetConfiguration()) + { + //This is another special resolver that needs to be resolvable before resolution is frozen + //since it is used for profiling the application startup + CanResolveBeforeFrozen = true + }; + } + /// /// Special method to initialize the ProfilerResolver /// protected virtual void InitializeProfilerResolver() { //By default we'll initialize the Log profiler (in the web project, we'll override with the web profiler) - ProfilerResolver.Current = new ProfilerResolver(new LogProfiler()) - { - //This is another special resolver that needs to be resolvable before resolution is frozen - //since it is used for profiling the application startup - CanResolveBeforeFrozen = true - }; + ProfilerResolver.Current = new ProfilerResolver(new LogProfiler(LoggerResolver.Current.Logger)) + { + //This is another special resolver that needs to be resolvable before resolution is frozen + //since it is used for profiling the application startup + CanResolveBeforeFrozen = true + }; } /// @@ -170,7 +207,9 @@ namespace Umbraco.Core //ApplicationStartupHandler.RegisterHandlers(); //... and set the special flag to let us resolve before frozen resolution ApplicationEventsResolver.Current = new ApplicationEventsResolver( - PluginManager.Current.ResolveApplicationStartupHandlers()) + ServiceProvider, + LoggerResolver.Current.Logger, + PluginManager.ResolveApplicationStartupHandlers()) { CanResolveBeforeFrozen = true }; @@ -187,16 +226,16 @@ namespace Umbraco.Core Umbraco.Core.IO.IOHelper.SetRootDirectory(rootPath); } - /// - /// 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 - /// - /// - /// - public virtual IBootManager Startup(Action afterStartup) - { - if (_isStarted) - throw new InvalidOperationException("The boot manager has already been initialized"); + /// + /// + /// + public virtual IBootManager Startup(Action afterStartup) + { + if (_isStarted) + throw new InvalidOperationException("The boot manager has already been initialized"); //call OnApplicationStarting of each application events handler ApplicationEventsResolver.Current.ApplicationEventHandlers @@ -207,23 +246,23 @@ namespace Umbraco.Core afterStartup(ApplicationContext.Current); } - _isStarted = true; + _isStarted = true; - return this; - } + return this; + } - /// - /// Fires after startup and calls the callback once customizations are locked - /// - /// - /// - public virtual IBootManager Complete(Action afterComplete) - { - if (_isComplete) - throw new InvalidOperationException("The boot manager has already been completed"); + /// + /// Fires after startup and calls the callback once customizations are locked + /// + /// + /// + public virtual IBootManager Complete(Action afterComplete) + { + if (_isComplete) + throw new InvalidOperationException("The boot manager has already been completed"); + + FreezeResolution(); - FreezeResolution(); - //call OnApplicationStarting of each application events handler ApplicationEventsResolver.Current.ApplicationEventHandlers .ForEach(x => x.OnApplicationStarted(UmbracoApplication, ApplicationContext)); @@ -236,15 +275,15 @@ namespace Umbraco.Core afterComplete(ApplicationContext.Current); } - _isComplete = true; + _isComplete = true; // we're ready to serve content! ApplicationContext.IsReady = true; //stop the timer and log the output _timer.Dispose(); - return this; - } + return this; + } /// /// Freeze resolution to not allow Resolvers to be modified @@ -253,17 +292,18 @@ namespace Umbraco.Core { Resolution.Freeze(); } - - /// - /// Create the resolvers - /// - protected virtual void InitializeResolvers() - { - PropertyEditorResolver.Current = new PropertyEditorResolver(() => PluginManager.Current.ResolvePropertyEditors()); - ParameterEditorResolver.Current = new ParameterEditorResolver(() => PluginManager.Current.ResolveParameterEditors()); + + /// + /// Create the resolvers + /// + protected virtual void InitializeResolvers() + { + PropertyEditorResolver.Current = new PropertyEditorResolver(ServiceProvider, LoggerResolver.Current.Logger, () => PluginManager.ResolvePropertyEditors()); + ParameterEditorResolver.Current = new ParameterEditorResolver(ServiceProvider, LoggerResolver.Current.Logger, () => PluginManager.ResolveParameterEditors()); //setup the validators resolver with our predefined validators - ValidatorsResolver.Current = new ValidatorsResolver(new[] + ValidatorsResolver.Current = new ValidatorsResolver( + ServiceProvider, LoggerResolver.Current.Logger, new[] { new Lazy(() => typeof (RequiredManifestValueValidator)), new Lazy(() => typeof (RegexValidator)), @@ -274,7 +314,7 @@ namespace Umbraco.Core //by default we'll use the standard configuration based sync ServerRegistrarResolver.Current = new ServerRegistrarResolver( - new ConfigServerRegistrar()); + new ConfigServerRegistrar()); //by default (outside of the web) we'll use the default server messenger without //supplying a username/password, this will automatically disable distributed calls @@ -283,48 +323,52 @@ namespace Umbraco.Core new DefaultServerMessenger()); MappingResolver.Current = new MappingResolver( - () => PluginManager.Current.ResolveAssignedMapperTypes()); + ServiceProvider, LoggerResolver.Current.Logger, + () => PluginManager.ResolveAssignedMapperTypes()); - RepositoryResolver.Current = new RepositoryResolver( - new RepositoryFactory(ApplicationCache)); + - SqlSyntaxProvidersResolver.Current = new SqlSyntaxProvidersResolver( - new[] { typeof(MySqlSyntaxProvider), typeof(SqlCeSyntaxProvider), typeof(SqlServerSyntaxProvider) }) - { - CanResolveBeforeFrozen = true - }; + //RepositoryResolver.Current = new RepositoryResolver( + // new RepositoryFactory(ApplicationCache)); - CacheRefreshersResolver.Current = new CacheRefreshersResolver( - () => PluginManager.Current.ResolveCacheRefreshers()); + CacheRefreshersResolver.Current = new CacheRefreshersResolver( + ServiceProvider, LoggerResolver.Current.Logger, + () => PluginManager.ResolveCacheRefreshers()); - MacroFieldEditorsResolver.Current = new MacroFieldEditorsResolver( - () => PluginManager.Current.ResolveMacroRenderings()); + MacroFieldEditorsResolver.Current = new MacroFieldEditorsResolver( + ServiceProvider, LoggerResolver.Current.Logger, + () => PluginManager.ResolveMacroRenderings()); - PackageActionsResolver.Current = new PackageActionsResolver( - () => PluginManager.Current.ResolvePackageActions()); + PackageActionsResolver.Current = new PackageActionsResolver( + ServiceProvider, LoggerResolver.Current.Logger, + () => PluginManager.ResolvePackageActions()); - ActionsResolver.Current = new ActionsResolver( - () => PluginManager.Current.ResolveActions()); + ActionsResolver.Current = new ActionsResolver( + ServiceProvider, LoggerResolver.Current.Logger, + () => PluginManager.ResolveActions()); //the database migration objects MigrationResolver.Current = new MigrationResolver( - () => PluginManager.Current.ResolveTypes()); + ServiceProvider, LoggerResolver.Current.Logger, + () => PluginManager.ResolveTypes()); - // need to filter out the ones we dont want!! - PropertyValueConvertersResolver.Current = new PropertyValueConvertersResolver( - PluginManager.Current.ResolveTypes()); + // need to filter out the ones we dont want!! + PropertyValueConvertersResolver.Current = new PropertyValueConvertersResolver( + ServiceProvider, LoggerResolver.Current.Logger, + PluginManager.ResolveTypes()); // use the new DefaultShortStringHelper ShortStringHelperResolver.Current = new ShortStringHelperResolver( //new LegacyShortStringHelper()); new DefaultShortStringHelper().WithDefaultConfig()); - UrlSegmentProviderResolver.Current = new UrlSegmentProviderResolver( - typeof (DefaultUrlSegmentProvider)); + UrlSegmentProviderResolver.Current = new UrlSegmentProviderResolver( + ServiceProvider, LoggerResolver.Current.Logger, + typeof(DefaultUrlSegmentProvider)); // by default, no factory is activated - PublishedContentModelFactoryResolver.Current = new PublishedContentModelFactoryResolver(); - } - } + PublishedContentModelFactoryResolver.Current = new PublishedContentModelFactoryResolver(); + } + } } diff --git a/src/Umbraco.Core/DatabaseContext.cs b/src/Umbraco.Core/DatabaseContext.cs index fad96b849d..414c68bab0 100644 --- a/src/Umbraco.Core/DatabaseContext.cs +++ b/src/Umbraco.Core/DatabaseContext.cs @@ -25,6 +25,8 @@ namespace Umbraco.Core public class DatabaseContext { private readonly IDatabaseFactory _factory; + private readonly ILogger _logger; + private readonly SqlSyntaxProviders _syntaxProviders; private bool _configured; private bool _canConnect; private volatile bool _connectCheck = false; @@ -33,11 +35,53 @@ namespace Umbraco.Core private string _providerName; private DatabaseSchemaResult _result; + [Obsolete("Use the constructor specifying all dependencies instead")] public DatabaseContext(IDatabaseFactory factory) + : this(factory, LoggerResolver.Current.Logger, new SqlSyntaxProviders(new ISqlSyntaxProvider[] + { + new MySqlSyntaxProvider(LoggerResolver.Current.Logger), + new SqlCeSyntaxProvider(), + new SqlServerSyntaxProvider() + })) { - _factory = factory; } + /// + /// Default constructor + /// + /// + /// + /// + public DatabaseContext(IDatabaseFactory factory, ILogger logger, SqlSyntaxProviders syntaxProviders) + { + if (factory == null) throw new ArgumentNullException("factory"); + if (logger == null) throw new ArgumentNullException("logger"); + if (syntaxProviders == null) throw new ArgumentNullException("syntaxProviders"); + + _factory = factory; + _logger = logger; + _syntaxProviders = syntaxProviders; + } + + /// + /// Create a configured DatabaseContext + /// + /// + /// + /// + /// + public DatabaseContext(IDatabaseFactory factory, ILogger logger, ISqlSyntaxProvider sqlSyntax, string providerName) + { + _providerName = providerName; + SqlSyntax = sqlSyntax; + SqlSyntaxContext.SqlSyntaxProvider = SqlSyntax; + _factory = factory; + _logger = logger; + _configured = true; + } + + public ISqlSyntaxProvider SqlSyntax { get; private set; } + /// /// Gets the object for doing CRUD operations /// against custom tables that resides in the Umbraco database. @@ -324,7 +368,7 @@ namespace Umbraco.Core xml.Save(fileName, SaveOptions.DisableFormatting); - LogHelper.Info("Configured a new ConnectionString using the '" + providerName + "' provider."); + _logger.Info("Configured a new ConnectionString using the '" + providerName + "' provider."); } /// @@ -398,12 +442,23 @@ namespace Umbraco.Core internal void Initialize(string providerName) { + //only configure once! + if (_configured == true) return; + _providerName = providerName; try { - SqlSyntaxContext.SqlSyntaxProvider = - SqlSyntaxProvidersResolver.Current.GetByProviderNameOrDefault(providerName); + if (_syntaxProviders != null) + { + SqlSyntax = _syntaxProviders.GetByProviderNameOrDefault(providerName); + } + else if (SqlSyntax == null) + { + throw new InvalidOperationException("No " + typeof(ISqlSyntaxProvider) + " specified or no " + typeof(SqlSyntaxProviders) + " instance specified"); + } + + SqlSyntaxContext.SqlSyntaxProvider = SqlSyntax; _configured = true; } @@ -411,8 +466,8 @@ namespace Umbraco.Core { _configured = false; - LogHelper.Info("Initialization of the DatabaseContext failed with following error: " + e.Message); - LogHelper.Info(e.StackTrace); + _logger.Info("Initialization of the DatabaseContext failed with following error: " + e.Message); + _logger.Info(e.StackTrace); } } @@ -427,8 +482,8 @@ namespace Umbraco.Core /// private void DetermineSqlServerVersion() { - - var sqlServerSyntax = SqlSyntaxContext.SqlSyntaxProvider as SqlServerSyntaxProvider; + + var sqlServerSyntax = SqlSyntax as SqlServerSyntaxProvider; if (sqlServerSyntax != null) { //this will not execute now, it is lazy so will only execute when we need to actually know @@ -479,8 +534,8 @@ namespace Umbraco.Core throw new InvalidOperationException("Cannot use MySql in Medium Trust configuration"); } - var database = new UmbracoDatabase(_connectionString, ProviderName); - var dbSchema = new DatabaseSchemaCreation(database); + var database = new UmbracoDatabase(_connectionString, ProviderName, _logger); + var dbSchema = new DatabaseSchemaCreation(database, _logger, SqlSyntax); _result = dbSchema.ValidateSchema(); } return _result; @@ -496,17 +551,17 @@ namespace Umbraco.Core return readyForInstall.Result; } - LogHelper.Info("Database configuration status: Started"); + _logger.Info("Database configuration status: Started"); string message; - var database = new UmbracoDatabase(_connectionString, ProviderName); + var database = new UmbracoDatabase(_connectionString, ProviderName, _logger); // If MySQL, we're going to ensure that database calls are maintaining proper casing as to remove the necessity for checks // for case insensitive queries. In an ideal situation (which is what we're striving for), all calls would be case sensitive. /* - var supportsCaseInsensitiveQueries = SqlSyntaxContext.SqlSyntaxProvider.SupportsCaseInsensitiveQueries(database); + var supportsCaseInsensitiveQueries = SqlSyntax.SupportsCaseInsensitiveQueries(database); if (supportsCaseInsensitiveQueries == false) { message = "

 

The database you're trying to use does not support case insensitive queries.
We currently do not support these types of databases.

" + @@ -532,12 +587,12 @@ namespace Umbraco.Core message = message + "

Installation completed!

"; //now that everything is done, we need to determine the version of SQL server that is executing - LogHelper.Info("Database configuration status: " + message); + _logger.Info("Database configuration status: " + message); return new Result { Message = message, Success = true, Percentage = "100" }; } //we need to do an upgrade so return a new status message and it will need to be done during the next step - LogHelper.Info("Database requires upgrade"); + _logger.Info("Database requires upgrade"); message = "

Upgrading database, this may take some time...

"; return new Result { @@ -568,10 +623,10 @@ namespace Umbraco.Core return readyForInstall.Result; } - LogHelper.Info("Database upgrade started"); + _logger.Info("Database upgrade started"); - var database = new UmbracoDatabase(_connectionString, ProviderName); - //var supportsCaseInsensitiveQueries = SqlSyntaxContext.SqlSyntaxProvider.SupportsCaseInsensitiveQueries(database); + var database = new UmbracoDatabase(_connectionString, ProviderName, _logger); + //var supportsCaseInsensitiveQueries = SqlSyntax.SupportsCaseInsensitiveQueries(database); var message = GetResultMessageForMySql(); @@ -584,13 +639,13 @@ namespace Umbraco.Core ? installedVersion : new Version(GlobalSettings.ConfigurationStatus); var targetVersion = UmbracoVersion.Current; - var runner = new MigrationRunner(currentVersion, targetVersion, GlobalSettings.UmbracoMigrationName); + var runner = new MigrationRunner(_logger, currentVersion, targetVersion, GlobalSettings.UmbracoMigrationName); var upgraded = runner.Execute(database, true); message = message + "

Upgrade completed!

"; //now that everything is done, we need to determine the version of SQL server that is executing - LogHelper.Info("Database configuration status: " + message); + _logger.Info("Database configuration status: " + message); return new Result { Message = message, Success = true, Percentage = "100" }; } @@ -602,7 +657,7 @@ namespace Umbraco.Core private string GetResultMessageForMySql() { - if (SqlSyntaxContext.SqlSyntaxProvider.GetType() == typeof(MySqlSyntaxProvider)) + if (SqlSyntax.GetType() == typeof(MySqlSyntaxProvider)) { return "

 

Congratulations, the database step ran successfully!

" + "

Note: You're using MySQL and the database instance you're connecting to seems to support case insensitive queries.

" + @@ -628,7 +683,7 @@ namespace Umbraco.Core "

For more technical information on case sensitivity in MySQL, have a look at " + "the documentation on the subject

"; } - if (SqlSyntaxContext.SqlSyntaxProvider.GetType() == typeof(MySqlSyntaxProvider)) + if (SqlSyntax.GetType() == typeof(MySqlSyntaxProvider)) { return "

 

Congratulations, the database step ran successfully!

" + "

Note: You're using MySQL and the database instance you're connecting to seems to support case insensitive queries.

" + @@ -665,11 +720,11 @@ namespace Umbraco.Core private Result HandleInstallException(Exception ex) { - LogHelper.Error("Database configuration failed", ex); + _logger.Error("Database configuration failed", ex); if (_result != null) { - LogHelper.Info("The database schema validation produced the following summary: \n" + _result.GetSummary()); + _logger.Info("The database schema validation produced the following summary: \n" + _result.GetSummary()); } return new Result diff --git a/src/Umbraco.Core/DisposableTimer.cs b/src/Umbraco.Core/DisposableTimer.cs index f0df0be23e..816256360a 100644 --- a/src/Umbraco.Core/DisposableTimer.cs +++ b/src/Umbraco.Core/DisposableTimer.cs @@ -1,4 +1,5 @@ using System; +using System.ComponentModel; using System.Diagnostics; using System.Web; using Umbraco.Core.Logging; @@ -9,32 +10,65 @@ namespace Umbraco.Core /// /// Starts the timer and invokes a callback upon disposal. Provides a simple way of timing an operation by wrapping it in a using (C#) statement. /// - /// - /// - /// - /// using (DisposableTimer.TraceDuration{MyType}("starting", "finished")) - /// { - /// Thread.Sleep(567); - /// } - /// - /// Console.WriteLine("Testing Stopwatchdisposable, should be 567:"); - /// using (var timer = new DisposableTimer(result => Console.WriteLine("Took {0}ms", result))) - /// { - /// Thread.Sleep(567); - /// } - /// - /// public class DisposableTimer : DisposableObject { - private readonly Stopwatch _stopwatch = Stopwatch.StartNew(); + private readonly Stopwatch _stopwatch = Stopwatch.StartNew(); private readonly Action _callback; - protected DisposableTimer(Action callback) - { - _callback = callback; - } + internal enum LogType + { + Debug, Info + } - public Stopwatch Stopwatch + internal DisposableTimer(ILogger logger, LogType logType, IProfiler profiler, Type loggerType, string startMessage, string endMessage) + { + if (logger == null) throw new ArgumentNullException("logger"); + if (loggerType == null) throw new ArgumentNullException("loggerType"); + + _callback = x => + { + if (profiler != null) + { + profiler.DisposeIfDisposable(); + } + switch (logType) + { + case LogType.Debug: + logger.Debug(loggerType, () => endMessage + " (took " + x + "ms)"); + break; + case LogType.Info: + logger.Info(loggerType, () => endMessage + " (took " + x + "ms)"); + break; + default: + throw new ArgumentOutOfRangeException("logType"); + } + + }; + switch (logType) + { + case LogType.Debug: + logger.Debug(loggerType, startMessage); + break; + case LogType.Info: + logger.Info(loggerType, startMessage); + break; + default: + throw new ArgumentOutOfRangeException("logType"); + } + + if (profiler != null) + { + profiler.Step(loggerType, startMessage); + } + } + + protected internal DisposableTimer(Action callback) + { + if (callback == null) throw new ArgumentNullException("callback"); + _callback = callback; + } + + public Stopwatch Stopwatch { get { return _stopwatch; } } @@ -51,25 +85,25 @@ namespace Umbraco.Core } #region TraceDuration + + [EditorBrowsable(EditorBrowsableState.Never)] + [Obsolete("Use the other methods that specify strings instead of Func")] public static DisposableTimer TraceDuration(Func startMessage, Func completeMessage) { return TraceDuration(typeof(T), startMessage, completeMessage); } + [EditorBrowsable(EditorBrowsableState.Never)] + [Obsolete("Use the other methods that specify strings instead of Func")] public static DisposableTimer TraceDuration(Type loggerType, Func startMessage, Func completeMessage) { - var startMsg = startMessage(); - LogHelper.Info(loggerType, startMsg); - if (HttpContext.Current != null) - HttpContext.Current.Trace.Write("Start: " + startMsg); - var profiler = ActivateProfiler(loggerType, startMsg); - return new DisposableTimer(x => - { - profiler.DisposeIfDisposable(); - LogHelper.Info(loggerType, () => completeMessage() + " (took " + x + "ms)"); - if (HttpContext.Current != null) - HttpContext.Current.Trace.Write("End: " + startMsg); - }); + return new DisposableTimer( + LoggerResolver.Current.Logger, + LogType.Info, + ProfilerResolver.HasCurrent ? ProfilerResolver.Current.Profiler : null, + loggerType, + startMessage(), + completeMessage()); } /// @@ -79,11 +113,19 @@ namespace Umbraco.Core /// /// /// + [Obsolete("Use the Umbraco.Core.Logging.ProfilingLogger to create instances of DisposableTimer")] public static DisposableTimer TraceDuration(string startMessage, string completeMessage) { return TraceDuration(typeof(T), startMessage, completeMessage); } + /// + /// Adds a start and end log entry as Info and tracks how long it takes until disposed. + /// + /// + /// + /// + [Obsolete("Use the Umbraco.Core.Logging.ProfilingLogger to create instances of DisposableTimer")] public static DisposableTimer TraceDuration(string startMessage) { return TraceDuration(typeof(T), startMessage, "Complete"); @@ -96,20 +138,18 @@ namespace Umbraco.Core /// /// /// + [Obsolete("Use the Umbraco.Core.Logging.ProfilingLogger to create instances of DisposableTimer")] public static DisposableTimer TraceDuration(Type loggerType, string startMessage, string completeMessage) { - LogHelper.Info(loggerType, startMessage); - if (HttpContext.Current != null) - HttpContext.Current.Trace.Write("Start: " + startMessage); - var profiler = ActivateProfiler(loggerType, startMessage); - return new DisposableTimer(x => - { - profiler.DisposeIfDisposable(); - LogHelper.Info(loggerType, () => completeMessage + " (took " + x + "ms)"); - if (HttpContext.Current != null) - HttpContext.Current.Trace.Write("End: " + startMessage); - }); - } + return new DisposableTimer( + LoggerResolver.Current.Logger, + LogType.Info, + ProfilerResolver.HasCurrent ? ProfilerResolver.Current.Profiler : null, + loggerType, + startMessage, + completeMessage); + } + #endregion #region DebugDuration @@ -120,23 +160,26 @@ namespace Umbraco.Core /// /// /// + [Obsolete("Use the Umbraco.Core.Logging.ProfilingLogger to create instances of DisposableTimer")] public static DisposableTimer DebugDuration(string startMessage, string completeMessage) { return DebugDuration(typeof(T), startMessage, completeMessage); } - public static DisposableTimer DebugDuration(string startMessage) - { - return DebugDuration(typeof(T), startMessage, "Complete"); - } - /// /// Adds a start and end log entry as Debug and tracks how long it takes until disposed. /// /// /// - /// /// + [Obsolete("Use the Umbraco.Core.Logging.ProfilingLogger to create instances of DisposableTimer")] + public static DisposableTimer DebugDuration(string startMessage) + { + return DebugDuration(typeof(T), startMessage, "Complete"); + } + + [EditorBrowsable(EditorBrowsableState.Never)] + [Obsolete("Use the other methods that specify strings instead of Func")] public static DisposableTimer DebugDuration(Func startMessage, Func completeMessage) { return DebugDuration(typeof(T), startMessage, completeMessage); @@ -149,42 +192,29 @@ namespace Umbraco.Core /// /// /// + [Obsolete("Use the Umbraco.Core.Logging.ProfilingLogger to create instances of DisposableTimer")] public static DisposableTimer DebugDuration(Type loggerType, string startMessage, string completeMessage) { - LogHelper.Debug(loggerType, startMessage); - if (HttpContext.Current != null) - HttpContext.Current.Trace.Write("Start: " + startMessage); - var profiler = ActivateProfiler(loggerType, startMessage); - return new DisposableTimer(x => - { - profiler.DisposeIfDisposable(); - LogHelper.Debug(loggerType, () => completeMessage + " (took " + x + "ms)"); - if (HttpContext.Current != null) - HttpContext.Current.Trace.Write("End: " + startMessage); - }); + return new DisposableTimer( + LoggerResolver.Current.Logger, + LogType.Debug, + ProfilerResolver.HasCurrent ? ProfilerResolver.Current.Profiler : null, + loggerType, + startMessage, + completeMessage); } - /// - /// Adds a start and end log entry as Debug and tracks how long it takes until disposed. - /// - /// - /// - /// - /// + [EditorBrowsable(EditorBrowsableState.Never)] + [Obsolete("Use the other methods that specify strings instead of Func")] public static DisposableTimer DebugDuration(Type loggerType, Func startMessage, Func completeMessage) { - var msg = startMessage(); - LogHelper.Debug(loggerType, msg); - if (HttpContext.Current != null) - HttpContext.Current.Trace.Write("Start: " + startMessage); - var profiler = ActivateProfiler(loggerType, msg); - return new DisposableTimer(x => - { - profiler.DisposeIfDisposable(); - LogHelper.Debug(loggerType, () => completeMessage() + " (took " + x + "ms)"); - if (HttpContext.Current != null) - HttpContext.Current.Trace.Write("End: " + startMessage); - }); + return new DisposableTimer( + LoggerResolver.Current.Logger, + LogType.Debug, + ProfilerResolver.HasCurrent ? ProfilerResolver.Current.Profiler : null, + loggerType, + startMessage(), + completeMessage()); } #endregion @@ -196,18 +226,5 @@ namespace Umbraco.Core _callback.Invoke(Stopwatch.ElapsedMilliseconds); } - private static IDisposable ActivateProfiler(Type loggerType, string profileName) - { - try - { - return ProfilerResolver.Current.Profiler.Step(loggerType, profileName); - } - catch (InvalidOperationException) - { - //swallow this exception, it will occur if the ProfilerResolver is not initialized... generally only in - // unit tests. - } - return null; - } } } \ No newline at end of file diff --git a/src/Umbraco.Core/IO/IOHelper.cs b/src/Umbraco.Core/IO/IOHelper.cs index 0fbd795878..dc5e278970 100644 --- a/src/Umbraco.Core/IO/IOHelper.cs +++ b/src/Umbraco.Core/IO/IOHelper.cs @@ -56,11 +56,11 @@ namespace Umbraco.Core.IO { if (UmbracoConfig.For.UmbracoSettings().Content.ResolveUrlsFromTextString) { - using (var timer = DisposableTimer.DebugDuration(typeof(IOHelper), "ResolveUrlsFromTextString starting", "ResolveUrlsFromTextString complete")) + using (DisposableTimer.DebugDuration(typeof(IOHelper), "ResolveUrlsFromTextString starting", "ResolveUrlsFromTextString complete")) { // find all relative urls (ie. urls that contain ~) var tags = ResolveUrlPattern.Matches(text); - LogHelper.Debug(typeof(IOHelper), "After regex: " + timer.Stopwatch.ElapsedMilliseconds + " matched: " + tags.Count); + foreach (Match tag in tags) { string url = ""; diff --git a/src/Umbraco.Core/IO/MasterPageHelper.cs b/src/Umbraco.Core/IO/MasterPageHelper.cs new file mode 100644 index 0000000000..9560274b63 --- /dev/null +++ b/src/Umbraco.Core/IO/MasterPageHelper.cs @@ -0,0 +1,450 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Text; +using System.Text.RegularExpressions; +using Umbraco.Core.Models; +using Umbraco.Core.Persistence.Repositories; +using Umbraco.Core.Services; + +namespace Umbraco.Core.IO +{ + internal class MasterPageHelper + { + private readonly IFileSystem _masterPageFileSystem; + internal static readonly string DefaultMasterTemplate = SystemDirectories.Umbraco + "/masterpages/default.master"; + //private static readonly char[] NewLineChars = Environment.NewLine.ToCharArray(); + + public MasterPageHelper(IFileSystem masterPageFileSystem) + { + if (masterPageFileSystem == null) throw new ArgumentNullException("masterPageFileSystem"); + _masterPageFileSystem = masterPageFileSystem; + } + + public bool MasterPageExists(ITemplate t) + { + return _masterPageFileSystem.FileExists(GetFilePath(t)); + } + + [Obsolete("This is only used for legacy purposes and will be removed in future versions")] + internal string GetPhysicalFilePath(ITemplate t) + { + return _masterPageFileSystem.GetFullPath(GetFilePath(t.Alias)); + } + + private string GetFilePath(ITemplate t) + { + return GetFilePath(t.Alias); + } + + private string GetFilePath(string alias) + { + return alias + ".master"; + } + + public string CreateMasterPage(ITemplate t, ITemplateRepository templateRepo, bool overWrite = false) + { + string masterpageContent = ""; + + var filePath = GetFilePath(t); + if (_masterPageFileSystem.FileExists(filePath) == false || overWrite) + { + masterpageContent = t.Content.IsNullOrWhiteSpace() ? CreateDefaultMasterPageContent(t, templateRepo) : t.Content; + + var data = Encoding.UTF8.GetBytes(masterpageContent); + var withBom = Encoding.UTF8.GetPreamble().Concat(data).ToArray(); + + using (var ms = new MemoryStream(withBom)) + { + _masterPageFileSystem.AddFile(filePath, ms, true); + } + } + else + { + using (var s = _masterPageFileSystem.OpenFile(filePath)) + using (var tr = new StreamReader(s, Encoding.UTF8)) + { + masterpageContent = tr.ReadToEnd(); + tr.Close(); + } + } + + return masterpageContent; + } + + //internal string GetFileContents(ITemplate t) + //{ + // var masterpageContent = ""; + // if (_masterPageFileSystem.FileExists(GetFilePath(t))) + // { + // using (var s = _masterPageFileSystem.OpenFile(GetFilePath(t))) + // using (var tr = new StreamReader(s)) + // { + // masterpageContent = tr.ReadToEnd(); + // tr.Close(); + // } + // } + + // return masterpageContent; + //} + + public string UpdateMasterPageFile(ITemplate t, string currentAlias, ITemplateRepository templateRepo) + { + var template = UpdateMasterPageContent(t, currentAlias); + UpdateChildTemplates(t, currentAlias, templateRepo); + var filePath = GetFilePath(t); + + var data = Encoding.UTF8.GetBytes(template); + var withBom = Encoding.UTF8.GetPreamble().Concat(data).ToArray(); + + using (var ms = new MemoryStream(withBom)) + { + _masterPageFileSystem.AddFile(filePath, ms, true); + } + return template; + } + + private string CreateDefaultMasterPageContent(ITemplate template, ITemplateRepository templateRepo) + { + var design = new StringBuilder(); + design.Append(GetMasterPageHeader(template) + Environment.NewLine); + + if (template.MasterTemplateAlias.IsNullOrWhiteSpace() == false) + { + var master = templateRepo.Get(template.MasterTemplateAlias); + if (master != null) + { + foreach (var cpId in GetContentPlaceholderIds(master)) + { + design.Append("" + + Environment.NewLine + + Environment.NewLine + + "" + + Environment.NewLine + + Environment.NewLine); + } + + return design.ToString(); + } + } + + design.Append(GetMasterContentElement(template) + Environment.NewLine); + design.Append(template.Content + Environment.NewLine); + design.Append("" + Environment.NewLine); + + return design.ToString(); + } + + public static IEnumerable GetContentPlaceholderIds(ITemplate template) + { + var retVal = new List(); + + var mp = template.Content; + var path = ""; + var r = new Regex(path, RegexOptions.IgnoreCase); + var m = r.Match(mp); + + while (m.Success) + { + var cc = m.Groups[3].Captures; + retVal.AddRange(cc.Cast().Where(c => c.Value != "server").Select(c => c.Value)); + + m = m.NextMatch(); + } + + return retVal; + } + + private static string UpdateMasterPageContent(ITemplate template, string currentAlias) + { + var masterPageContent = template.Content; + + if (string.IsNullOrEmpty(currentAlias) == false && currentAlias != template.Alias) + { + var masterHeader = + masterPageContent.Substring(0, masterPageContent.IndexOf("%>", StringComparison.Ordinal) + 2).Trim( + Environment.NewLine.ToCharArray()); + + // find the masterpagefile attribute + var m = Regex.Matches(masterHeader, "(?\\S*)=\"(?[^\"]*)\"", + RegexOptions.IgnoreCase | RegexOptions.IgnorePatternWhitespace); + + foreach (Match attributeSet in m) + { + if (attributeSet.Groups["attributeName"].Value.ToLower() == "masterpagefile") + { + // validate the masterpagefile + var currentMasterPageFile = attributeSet.Groups["attributeValue"].Value; + var currentMasterTemplateFile = ParentTemplatePath(template); + + if (currentMasterPageFile != currentMasterTemplateFile) + { + masterPageContent = + masterPageContent.Replace( + attributeSet.Groups["attributeName"].Value + "=\"" + currentMasterPageFile + "\"", + attributeSet.Groups["attributeName"].Value + "=\"" + currentMasterTemplateFile + + "\""); + } + } + } + } + + return masterPageContent; + } + + private void UpdateChildTemplates(ITemplate template, string currentAlias, ITemplateRepository templateRepo) + { + //if we have a Old Alias if the alias and therefor the masterpage file name has changed... + //so before we save the new masterfile, we'll clear the old one, so we don't up with + //Unused masterpage files + if (string.IsNullOrEmpty(currentAlias) == false && currentAlias != template.Alias) + { + //Ensure that child templates have the right master masterpage file name + if (template.IsMasterTemplate) + { + var children = templateRepo.GetChildren(template.Id); + foreach (var t in children) + UpdateMasterPageFile(t, null, templateRepo); + } + } + } + + + //private void SaveDesignToFile(ITemplate t, string currentAlias, string design) + //{ + // //kill the old file.. + // if (string.IsNullOrEmpty(currentAlias) == false && currentAlias != t.Alias) + // { + // var oldFile = + // IOHelper.MapPath(SystemDirectories.Masterpages + "/" + currentAlias.Replace(" ", "") + ".master"); + // if (System.IO.File.Exists(oldFile)) + // System.IO.File.Delete(oldFile); + // } + + // // save the file in UTF-8 + // System.IO.File.WriteAllText(GetFilePath(t), design, Encoding.UTF8); + //} + + //internal static void RemoveMasterPageFile(string alias) + //{ + // if (string.IsNullOrWhiteSpace(alias) == false) + // { + // string file = IOHelper.MapPath(SystemDirectories.Masterpages + "/" + alias.Replace(" ", "") + ".master"); + // if (System.IO.File.Exists(file)) + // System.IO.File.Delete(file); + // } + //} + + //internal string SaveTemplateToFile(ITemplate template, string currentAlias, ITemplateRepository templateRepo) + //{ + // var masterPageContent = template.Content; + // if (IsMasterPageSyntax(masterPageContent) == false) + // masterPageContent = ConvertToMasterPageSyntax(template); + + // // Add header to master page if it doesn't exist + // if (masterPageContent.TrimStart().StartsWith("<%@") == false) + // { + // masterPageContent = GetMasterPageHeader(template) + Environment.NewLine + masterPageContent; + // } + // else + // { + // // verify that the masterpage attribute is the same as the masterpage + // var masterHeader = + // masterPageContent.Substring(0, masterPageContent.IndexOf("%>", StringComparison.Ordinal) + 2).Trim(NewLineChars); + + // // find the masterpagefile attribute + // var m = Regex.Matches(masterHeader, "(?\\S*)=\"(?[^\"]*)\"", + // RegexOptions.IgnoreCase | RegexOptions.IgnorePatternWhitespace); + + // foreach (Match attributeSet in m) + // { + // if (attributeSet.Groups["attributeName"].Value.ToLower() == "masterpagefile") + // { + // // validate the masterpagefile + // var currentMasterPageFile = attributeSet.Groups["attributeValue"].Value; + // var currentMasterTemplateFile = ParentTemplatePath(template); + + // if (currentMasterPageFile != currentMasterTemplateFile) + // { + // masterPageContent = + // masterPageContent.Replace( + // attributeSet.Groups["attributeName"].Value + "=\"" + currentMasterPageFile + "\"", + // attributeSet.Groups["attributeName"].Value + "=\"" + currentMasterTemplateFile + + // "\""); + + // } + // } + // } + + // } + + // //we have a Old Alias if the alias and therefor the masterpage file name has changed... + // //so before we save the new masterfile, we'll clear the old one, so we don't up with + // //Unused masterpage files + // if (string.IsNullOrEmpty(currentAlias) == false && currentAlias != template.Alias) + // { + + // //Ensure that child templates have the right master masterpage file name + // if (template.IsMasterTemplate) + // { + // var children = templateRepo.GetChildren(template.Id); + + // foreach (var t in children) + // UpdateMasterPageFile(t, null, templateRepo); + // } + + // //then kill the old file.. + // var oldFile = GetFilePath(currentAlias); + // if (_masterPageFileSystem.FileExists(oldFile)) + // _masterPageFileSystem.DeleteFile(oldFile); + // } + + // // save the file in UTF-8 + // System.IO.File.WriteAllText(GetFilePath(template), masterPageContent, Encoding.UTF8); + + // return masterPageContent; + //} + + //internal static string ConvertToMasterPageSyntax(ITemplate template) + //{ + // string masterPageContent = GetMasterContentElement(template) + Environment.NewLine; + + // masterPageContent += template.Content; + + // // Parse the design for getitems + // masterPageContent = EnsureMasterPageSyntax(template.Alias, masterPageContent); + + // // append ending asp:content element + // masterPageContent += Environment.NewLine + "" + Environment.NewLine; + + // return masterPageContent; + //} + + public static bool IsMasterPageSyntax(string code) + { + return Regex.IsMatch(code, @"<%@\s*Master", RegexOptions.IgnoreCase) || + code.InvariantContains("", ParentTemplatePath(template)) + Environment.NewLine; + } + + private static string ParentTemplatePath(ITemplate template) + { + var masterTemplate = DefaultMasterTemplate; + if (template.MasterTemplateAlias.IsNullOrWhiteSpace() == false) + masterTemplate = SystemDirectories.Masterpages + "/" + template.MasterTemplateAlias + ".master"; + + return masterTemplate; + } + + private static string GetMasterContentElement(ITemplate template) + { + if (template.MasterTemplateAlias.IsNullOrWhiteSpace() == false) + { + string masterAlias = template.MasterTemplateAlias; + return + String.Format("", masterAlias); + } + else + return + String.Format(""); + + } + + //internal static string EnsureMasterPageSyntax(string templateAlias, string masterPageContent) + //{ + // ReplaceElement(ref masterPageContent, "?UMBRACO_GETITEM", "umbraco:Item", true); + // ReplaceElement(ref masterPageContent, "?UMBRACO_GETITEM", "umbraco:Item", false); + + // // Parse the design for macros + // ReplaceElement(ref masterPageContent, "?UMBRACO_MACRO", "umbraco:Macro", true); + // ReplaceElement(ref masterPageContent, "?UMBRACO_MACRO", "umbraco:Macro", false); + + // // Parse the design for load childs + // masterPageContent = masterPageContent.Replace("", CreateDefaultPlaceHolder(templateAlias)) + // .Replace("", CreateDefaultPlaceHolder(templateAlias)); + // // Parse the design for aspnet forms + // GetAspNetMasterPageForm(ref masterPageContent, templateAlias); + // masterPageContent = masterPageContent.Replace("", ""); + // // Parse the design for aspnet heads + // masterPageContent = masterPageContent.Replace("", String.Format("", templateAlias.Replace(" ", ""))); + // masterPageContent = masterPageContent.Replace("", ""); + // return masterPageContent; + //} + + + //private static void GetAspNetMasterPageForm(ref string design, string templateAlias) + //{ + // var formElement = Regex.Match(design, GetElementRegExp("?ASPNET_FORM", false), RegexOptions.IgnoreCase | RegexOptions.IgnorePatternWhitespace); + + // if (string.IsNullOrEmpty(formElement.Value) == false) + // { + // string formReplace = String.Format("
", templateAlias.Replace(" ", "")); + // if (formElement.Groups.Count == 0) + // { + // formReplace += ""; + // } + // design = design.Replace(formElement.Value, formReplace); + // } + //} + + //private static string CreateDefaultPlaceHolder(string templateAlias) + //{ + // return String.Format("", templateAlias.Replace(" ", "")); + //} + + //private static void ReplaceElement(ref string design, string elementName, string newElementName, bool checkForQuotes) + //{ + // var m = + // Regex.Matches(design, GetElementRegExp(elementName, checkForQuotes), + // RegexOptions.IgnoreCase | RegexOptions.IgnorePatternWhitespace); + + // foreach (Match match in m) + // { + // GroupCollection groups = match.Groups; + + // // generate new element (compensate for a closing trail on single elements ("/")) + // string elementAttributes = groups[1].Value; + // // test for macro alias + // if (elementName == "?UMBRACO_MACRO") + // { + // var tags = XmlHelper.GetAttributesFromElement(match.Value); + // if (tags["macroAlias"] != null) + // elementAttributes = String.Format(" Alias=\"{0}\"", tags["macroAlias"]) + elementAttributes; + // else if (tags["macroalias"] != null) + // elementAttributes = String.Format(" Alias=\"{0}\"", tags["macroalias"]) + elementAttributes; + // } + // string newElement = "<" + newElementName + " runat=\"server\" " + elementAttributes.Trim() + ">"; + // if (elementAttributes.EndsWith("/")) + // { + // elementAttributes = elementAttributes.Substring(0, elementAttributes.Length - 1); + // } + // else if (groups[0].Value.StartsWith(""; + + // if (checkForQuotes) + // { + // // if it's inside quotes, we'll change element attribute quotes to single quotes + // newElement = newElement.Replace("\"", "'"); + // newElement = String.Format("\"{0}\"", newElement); + // } + // design = design.Replace(match.Value, newElement); + // } + //} + + //private static string GetElementRegExp(string elementName, bool checkForQuotes) + //{ + // if (checkForQuotes) + // return String.Format("\"<[^>\\s]*\\b{0}(\\b[^>]*)>\"", elementName); + // else + // return String.Format("<[^>\\s]*\\b{0}(\\b[^>]*)>", elementName); + + //} + + } +} \ No newline at end of file diff --git a/src/Umbraco.Core/IO/PhysicalFileSystem.cs b/src/Umbraco.Core/IO/PhysicalFileSystem.cs index 607e45aec7..13df315960 100644 --- a/src/Umbraco.Core/IO/PhysicalFileSystem.cs +++ b/src/Umbraco.Core/IO/PhysicalFileSystem.cs @@ -15,7 +15,7 @@ namespace Umbraco.Core.IO public PhysicalFileSystem(string virtualRoot) { if (virtualRoot == null) throw new ArgumentNullException("virtualRoot"); - if (!virtualRoot.StartsWith("~/")) + if (virtualRoot.StartsWith("~/") == false) throw new ArgumentException("The virtualRoot argument must be a virtual path and start with '~/'"); RootPath = IOHelper.MapPath(virtualRoot); @@ -65,7 +65,7 @@ namespace Umbraco.Core.IO public void DeleteDirectory(string path, bool recursive) { - if (!DirectoryExists(path)) + if (DirectoryExists(path) == false) return; try diff --git a/src/Umbraco.Core/IO/ViewHelper.cs b/src/Umbraco.Core/IO/ViewHelper.cs new file mode 100644 index 0000000000..28dad49dc0 --- /dev/null +++ b/src/Umbraco.Core/IO/ViewHelper.cs @@ -0,0 +1,149 @@ +using System; +using System.IO; +using System.Linq; +using System.Text; +using System.Text.RegularExpressions; +using Umbraco.Core.Models; + +namespace Umbraco.Core.IO +{ + internal class ViewHelper + { + private readonly IFileSystem _viewFileSystem; + + public ViewHelper(IFileSystem viewFileSystem) + { + if (viewFileSystem == null) throw new ArgumentNullException("viewFileSystem"); + _viewFileSystem = viewFileSystem; + } + + internal bool ViewExists(ITemplate t) + { + return _viewFileSystem.FileExists(ViewPath(t.Alias)); + } + + [Obsolete("This is only used for legacy purposes and will be removed in future versions")] + internal string GetPhysicalFilePath(ITemplate t) + { + return _viewFileSystem.GetFullPath(ViewPath(t.Alias)); + } + + internal string GetFileContents(ITemplate t) + { + string viewContent = ""; + string path = ViewPath(t.Alias); + + if (_viewFileSystem.FileExists(path)) + { + using (var tr = new StreamReader(_viewFileSystem.OpenFile(path))) + { + viewContent = tr.ReadToEnd(); + tr.Close(); + } + } + + return viewContent; + } + + public string CreateView(ITemplate t, bool overWrite = false) + { + string viewContent; + string path = ViewPath(t.Alias); + + if (_viewFileSystem.FileExists(path) == false || overWrite) + { + viewContent = SaveTemplateToFile(t); + } + else + { + using (var tr = new StreamReader(_viewFileSystem.OpenFile(path))) + { + viewContent = tr.ReadToEnd(); + tr.Close(); + } + } + + return viewContent; + } + + internal static string GetDefaultFileContent(string layoutPageAlias = null) + { + var design = @"@inherits Umbraco.Web.Mvc.UmbracoTemplatePage +@{ + Layout = null; +}"; + + if (layoutPageAlias.IsNullOrWhiteSpace() == false) + design = design.Replace("null", string.Format("\"{0}.cshtml\"", layoutPageAlias)); + + return design; + } + + private string SaveTemplateToFile(ITemplate template) + { + var design = template.Content.IsNullOrWhiteSpace() ? EnsureInheritedLayout(template) : template.Content; + var path = ViewPath(template.Alias); + + var data = Encoding.UTF8.GetBytes(design); + var withBom = Encoding.UTF8.GetPreamble().Concat(data).ToArray(); + + using (var ms = new MemoryStream(withBom)) + { + _viewFileSystem.AddFile(path, ms, true); + } + + return design; + } + + public string UpdateViewFile(ITemplate t, string currentAlias = null) + { + var path = ViewPath(t.Alias); + + if (string.IsNullOrEmpty(currentAlias) == false && currentAlias != t.Alias) + { + //then kill the old file.. + var oldFile = ViewPath(currentAlias); + if (_viewFileSystem.FileExists(oldFile)) + _viewFileSystem.DeleteFile(oldFile); + } + + var data = Encoding.UTF8.GetBytes(t.Content); + var withBom = Encoding.UTF8.GetPreamble().Concat(data).ToArray(); + + using (var ms = new MemoryStream(withBom)) + { + _viewFileSystem.AddFile(path, ms, true); + } + return t.Content; + } + + internal void RemoveViewFile(string alias) + { + if (string.IsNullOrWhiteSpace(alias) == false) + { + var file = ViewPath(alias); + if (_viewFileSystem.FileExists(file)) + _viewFileSystem.DeleteFile(file); + } + } + + public string ViewPath(string alias) + { + return _viewFileSystem.GetRelativePath(alias.Replace(" ", "") + ".cshtml"); + + //return SystemDirectories.MvcViews + "/" + alias.Replace(" ", "") + ".cshtml"; + } + + private string EnsureInheritedLayout(ITemplate template) + { + string design = template.Content; + + if (string.IsNullOrEmpty(design)) + { + design = GetDefaultFileContent(template.MasterTemplateAlias); + } + + return design; + } + } +} \ No newline at end of file diff --git a/src/Umbraco.Core/Logging/DebugDiagnosticsLogger.cs b/src/Umbraco.Core/Logging/DebugDiagnosticsLogger.cs new file mode 100644 index 0000000000..232a0316f1 --- /dev/null +++ b/src/Umbraco.Core/Logging/DebugDiagnosticsLogger.cs @@ -0,0 +1,43 @@ +using System; +using System.Linq; + +namespace Umbraco.Core.Logging +{ + internal class DebugDiagnosticsLogger : ILogger + { + public void Error(Type callingType, string message, Exception exception) + { + System.Diagnostics.Debug.Fail(callingType.ToString(), message + Environment.NewLine + exception); + } + + public void Warn(Type callingType, string message, params Func[] formatItems) + { + System.Diagnostics.Debug.Fail(callingType.ToString(), string.Format(message, formatItems.Select(x => x()).ToArray())); + } + + public void WarnWithException(Type callingType, string message, Exception e, params Func[] formatItems) + { + System.Diagnostics.Debug.Fail(callingType.ToString(), string.Format(message + Environment.NewLine + e, formatItems.Select(x => x()).ToArray())); + } + + public void Info(Type callingType, Func generateMessage) + { + System.Diagnostics.Debug.WriteLine(callingType.ToString(), generateMessage()); + } + + public void Info(Type type, string generateMessageFormat, params Func[] formatItems) + { + System.Diagnostics.Debug.WriteLine(type.ToString(), string.Format(generateMessageFormat, formatItems.Select(x => x()).ToArray())); + } + + public void Debug(Type callingType, Func generateMessage) + { + System.Diagnostics.Debug.WriteLine(callingType.ToString(), generateMessage()); + } + + public void Debug(Type type, string generateMessageFormat, params Func[] formatItems) + { + System.Diagnostics.Debug.WriteLine(type.ToString(), string.Format(generateMessageFormat, formatItems.Select(x => x()).ToArray())); + } + } +} \ No newline at end of file diff --git a/src/Umbraco.Core/Logging/ILogger.cs b/src/Umbraco.Core/Logging/ILogger.cs new file mode 100644 index 0000000000..3fb6bfc476 --- /dev/null +++ b/src/Umbraco.Core/Logging/ILogger.cs @@ -0,0 +1,24 @@ +using System; + +namespace Umbraco.Core.Logging +{ + /// + /// Interface for logging service. + /// + public interface ILogger + { + void Error(Type callingType, string message, Exception exception); + + void Warn(Type callingType, string message, params Func[] formatItems); + + void WarnWithException(Type callingType, string message, Exception e, params Func[] formatItems); + + void Info(Type callingType, Func generateMessage); + + void Info(Type type, string generateMessageFormat, params Func[] formatItems); + + void Debug(Type callingType, Func generateMessage); + + void Debug(Type type, string generateMessageFormat, params Func[] formatItems); + } +} \ No newline at end of file diff --git a/src/Umbraco.Core/Logging/LogHelper.cs b/src/Umbraco.Core/Logging/LogHelper.cs index 9291ffec1d..c789beb489 100644 --- a/src/Umbraco.Core/Logging/LogHelper.cs +++ b/src/Umbraco.Core/Logging/LogHelper.cs @@ -6,43 +6,14 @@ using log4net; namespace Umbraco.Core.Logging { - /// - /// Used for logging + /// + /// Used for logging, ILogger should be used instead but this is available for static access to logging /// + /// + /// this wraps ILogger + /// public static class LogHelper { - /// - /// Returns a logger for the type specified - /// - /// - /// - internal static ILog LoggerFor() - { - return LogManager.GetLogger(typeof(T)); - } - - /// - /// Returns a logger for the object's type - /// - /// - /// - internal static ILog LoggerFor(object getTypeFromInstance) - { - if (getTypeFromInstance == null) throw new ArgumentNullException("getTypeFromInstance"); - - return LogManager.GetLogger(getTypeFromInstance.GetType()); - } - - /// - /// Useful if the logger itself is running on another thread - /// - /// - /// - private static string PrefixThreadId(string generateMessageFormat) - { - return "[Thread " + Thread.CurrentThread.ManagedThreadId + "] " + generateMessageFormat; - } - #region Error /// /// Adds an error log @@ -52,14 +23,14 @@ namespace Umbraco.Core.Logging /// public static void Error(string message, Exception exception) { - Error(typeof (T), message, exception); + if (LoggerResolver.HasCurrent == false || LoggerResolver.Current.HasValue == false) return; + LoggerResolver.Current.Logger.Error(message, exception); } public static void Error(Type callingType, string message, Exception exception) { - var logger = LogManager.GetLogger(callingType); - if (logger != null) - logger.Error(PrefixThreadId(message), exception); + if (LoggerResolver.HasCurrent == false || LoggerResolver.Current.HasValue == false) return; + LoggerResolver.Current.Logger.Error(callingType, message, exception); } #endregion @@ -68,11 +39,11 @@ namespace Umbraco.Core.Logging public static void Warn(Type callingType, string message, params Func[] formatItems) { - var logger = LogManager.GetLogger(callingType); - if (logger == null || !logger.IsWarnEnabled) return; - logger.WarnFormat(PrefixThreadId(message), formatItems.Select(x => x.Invoke()).ToArray()); + if (LoggerResolver.HasCurrent == false || LoggerResolver.Current.HasValue == false) return; + LoggerResolver.Current.Logger.Warn(callingType, message, formatItems); } + [Obsolete("Warnings with http trace should not be used. This method will be removed in future versions")] public static void Warn(Type callingType, string message, bool showHttpTrace, params Func[] formatItems) { Mandate.ParameterNotNull(callingType, "callingType"); @@ -81,11 +52,10 @@ namespace Umbraco.Core.Logging if (showHttpTrace && HttpContext.Current != null) { HttpContext.Current.Trace.Warn(callingType.Name, string.Format(message, formatItems.Select(x => x.Invoke()).ToArray())); - } + } - var logger = LogManager.GetLogger(callingType); - if (logger == null || !logger.IsWarnEnabled) return; - logger.WarnFormat(PrefixThreadId(message), formatItems.Select(x => x.Invoke()).ToArray()); + if (LoggerResolver.HasCurrent == false || LoggerResolver.Current.HasValue == false) return; + LoggerResolver.Current.Logger.Warn(callingType, message, formatItems); } @@ -94,6 +64,7 @@ namespace Umbraco.Core.Logging WarnWithException(callingType, message, false, e, formatItems); } + [Obsolete("Warnings with http trace should not be used. This method will be removed in future versions")] public static void WarnWithException(Type callingType, string message, bool showHttpTrace, Exception e, params Func[] formatItems) { Mandate.ParameterNotNull(e, "e"); @@ -108,10 +79,8 @@ namespace Umbraco.Core.Logging e); } - var logger = LogManager.GetLogger(callingType); - if (logger == null || !logger.IsWarnEnabled) return; - var executedParams = formatItems.Select(x => x.Invoke()).ToArray(); - logger.WarnFormat(PrefixThreadId(message) + ". Exception: " + e, executedParams); + if (LoggerResolver.HasCurrent == false || LoggerResolver.Current.HasValue == false) return; + LoggerResolver.Current.Logger.WarnWithException(callingType, message, e, formatItems); } /// @@ -125,6 +94,7 @@ namespace Umbraco.Core.Logging Warn(typeof(T), message, formatItems); } + [Obsolete("Warnings with http trace should not be used. This method will be removed in future versions")] public static void Warn(string message, bool showHttpTrace, params Func[] formatItems) { Warn(typeof(T), message, showHttpTrace, formatItems); @@ -134,6 +104,8 @@ namespace Umbraco.Core.Logging { WarnWithException(typeof(T), message, e, formatItems); } + + [Obsolete("Warnings with http trace should not be used. This method will be removed in future versions")] public static void WarnWithException(string message, bool showHttpTrace, Exception e, params Func[] formatItems) { WarnWithException(typeof(T), message, showHttpTrace, e, formatItems); @@ -160,9 +132,8 @@ namespace Umbraco.Core.Logging /// public static void Info(Type callingType, Func generateMessage) { - var logger = LogManager.GetLogger(callingType); - if (logger == null || !logger.IsInfoEnabled) return; - logger.Info(PrefixThreadId(generateMessage.Invoke())); + if (LoggerResolver.HasCurrent == false || LoggerResolver.Current.HasValue == false) return; + LoggerResolver.Current.Logger.Info(callingType, generateMessage); } /// @@ -173,10 +144,8 @@ namespace Umbraco.Core.Logging /// The format items. public static void Info(Type type, string generateMessageFormat, params Func[] formatItems) { - var logger = LogManager.GetLogger(type); - if (logger == null || !logger.IsInfoEnabled) return; - var executedParams = formatItems.Select(x => x.Invoke()).ToArray(); - logger.InfoFormat(PrefixThreadId(generateMessageFormat), executedParams); + if (LoggerResolver.HasCurrent == false || LoggerResolver.Current.HasValue == false) return; + LoggerResolver.Current.Logger.Info(type, generateMessageFormat, formatItems); } /// @@ -211,9 +180,8 @@ namespace Umbraco.Core.Logging /// public static void Debug(Type callingType, Func generateMessage) { - var logger = LogManager.GetLogger(callingType); - if (logger == null || !logger.IsDebugEnabled) return; - logger.Debug(PrefixThreadId(generateMessage.Invoke())); + if (LoggerResolver.HasCurrent == false || LoggerResolver.Current.HasValue == false) return; + LoggerResolver.Current.Logger.Debug(callingType, generateMessage); } /// @@ -224,10 +192,8 @@ namespace Umbraco.Core.Logging /// The format items. public static void Debug(Type type, string generateMessageFormat, params Func[] formatItems) { - var logger = LogManager.GetLogger(type); - if (logger == null || !logger.IsDebugEnabled) return; - var executedParams = formatItems.Select(x => x.Invoke()).ToArray(); - logger.DebugFormat(PrefixThreadId(generateMessageFormat), executedParams); + if (LoggerResolver.HasCurrent == false || LoggerResolver.Current.HasValue == false) return; + LoggerResolver.Current.Logger.Debug(type, generateMessageFormat, formatItems); } /// @@ -250,6 +216,7 @@ namespace Umbraco.Core.Logging /// /// /// + [Obsolete("Warnings with http trace should not be used. This method will be removed in future versions")] public static void Debug(string generateMessageFormat, bool showHttpTrace, params Func[] formatItems) { if (showHttpTrace && HttpContext.Current != null) diff --git a/src/Umbraco.Core/Logging/Logger.cs b/src/Umbraco.Core/Logging/Logger.cs new file mode 100644 index 0000000000..58f696d82b --- /dev/null +++ b/src/Umbraco.Core/Logging/Logger.cs @@ -0,0 +1,166 @@ +using System; +using System.IO; +using System.Linq; +using System.Threading; +using System.Web; +using log4net; +using log4net.Config; + +namespace Umbraco.Core.Logging +{ + /// + /// Used for logging + /// + public class Logger : ILogger + { + public Logger(FileInfo log4NetConfigFile) + { + XmlConfigurator.Configure(log4NetConfigFile); + } + + private Logger() + { + + } + + /// + /// Creates a logger with the default log4net configuration discovered (i.e. from the web.config) + /// + /// + public static Logger CreateWithDefaultLog4NetConfiguration() + { + return new Logger(); + } + + /// + /// Returns a logger for the type specified + /// + /// + /// + internal ILog LoggerFor() + { + return LogManager.GetLogger(typeof(T)); + } + + /// + /// Returns a logger for the object's type + /// + /// + /// + internal ILog LoggerFor(object getTypeFromInstance) + { + if (getTypeFromInstance == null) throw new ArgumentNullException("getTypeFromInstance"); + + return LogManager.GetLogger(getTypeFromInstance.GetType()); + } + + /// + /// Useful if the logger itself is running on another thread + /// + /// + /// + private string PrefixThreadId(string generateMessageFormat) + { + return "[Thread " + Thread.CurrentThread.ManagedThreadId + "] " + generateMessageFormat; + } + + public void Error(Type callingType, string message, Exception exception) + { + var logger = LogManager.GetLogger(callingType); + if (logger != null) + logger.Error(PrefixThreadId(message), exception); + } + + + + public void Warn(Type callingType, string message, params Func[] formatItems) + { + var logger = LogManager.GetLogger(callingType); + if (logger == null || logger.IsWarnEnabled == false) return; + logger.WarnFormat(PrefixThreadId(message), formatItems.Select(x => x.Invoke()).ToArray()); + } + + public void Warn(Type callingType, string message, bool showHttpTrace, params Func[] formatItems) + { + Mandate.ParameterNotNull(callingType, "callingType"); + Mandate.ParameterNotNullOrEmpty(message, "message"); + + if (showHttpTrace && HttpContext.Current != null) + { + HttpContext.Current.Trace.Warn(callingType.Name, string.Format(message, formatItems.Select(x => x.Invoke()).ToArray())); + } + + var logger = LogManager.GetLogger(callingType); + if (logger == null || logger.IsWarnEnabled == false) return; + logger.WarnFormat(PrefixThreadId(message), formatItems.Select(x => x.Invoke()).ToArray()); + + } + + public void WarnWithException(Type callingType, string message, Exception e, params Func[] formatItems) + { + Mandate.ParameterNotNull(e, "e"); + Mandate.ParameterNotNull(callingType, "callingType"); + Mandate.ParameterNotNullOrEmpty(message, "message"); + + var logger = LogManager.GetLogger(callingType); + if (logger == null || logger.IsWarnEnabled == false) return; + var executedParams = formatItems.Select(x => x.Invoke()).ToArray(); + logger.WarnFormat(PrefixThreadId(message) + ". Exception: " + e, executedParams); + } + + /// + /// Traces if tracing is enabled. + /// + /// + /// + public void Info(Type callingType, Func generateMessage) + { + var logger = LogManager.GetLogger(callingType); + if (logger == null || logger.IsInfoEnabled == false) return; + logger.Info(PrefixThreadId(generateMessage.Invoke())); + } + + /// + /// Traces if tracing is enabled. + /// + /// The type for the logging namespace. + /// The message format. + /// The format items. + public void Info(Type type, string generateMessageFormat, params Func[] formatItems) + { + var logger = LogManager.GetLogger(type); + if (logger == null || logger.IsInfoEnabled == false) return; + var executedParams = formatItems.Select(x => x.Invoke()).ToArray(); + logger.InfoFormat(PrefixThreadId(generateMessageFormat), executedParams); + } + + + /// + /// Debugs if tracing is enabled. + /// + /// + /// + public void Debug(Type callingType, Func generateMessage) + { + var logger = LogManager.GetLogger(callingType); + if (logger == null || logger.IsDebugEnabled == false) return; + logger.Debug(PrefixThreadId(generateMessage.Invoke())); + } + + /// + /// Debugs if tracing is enabled. + /// + /// The type for the logging namespace. + /// The message format. + /// The format items. + public void Debug(Type type, string generateMessageFormat, params Func[] formatItems) + { + var logger = LogManager.GetLogger(type); + if (logger == null || logger.IsDebugEnabled == false) return; + var executedParams = formatItems.Select(x => x.Invoke()).ToArray(); + logger.DebugFormat(PrefixThreadId(generateMessageFormat), executedParams); + } + + + } +} diff --git a/src/Umbraco.Core/Logging/LoggerExtensions.cs b/src/Umbraco.Core/Logging/LoggerExtensions.cs new file mode 100644 index 0000000000..58bdc1da0b --- /dev/null +++ b/src/Umbraco.Core/Logging/LoggerExtensions.cs @@ -0,0 +1,90 @@ +using System; + +namespace Umbraco.Core.Logging +{ + /// + /// Allows for strongly typed log sources + /// + public static class LoggerExtensions + { + /// + /// Adds an error log + /// + /// + /// + /// + /// + public static void Error(this ILogger logger, string message, Exception exception) + { + logger.Error(typeof(T), message, exception); + } + + /// + /// Adds a warn log + /// + /// + /// + /// + /// + public static void Warn(this ILogger logger, string message, params Func[] formatItems) + { + logger.Warn(typeof(T), message, formatItems); + } + + public static void WarnWithException(this ILogger logger, string message, Exception e, params Func[] formatItems) + { + logger.WarnWithException(typeof(T), message, e, formatItems); + } + + + /// + /// Traces a message, only generating the message if tracing is actually enabled. Use this method to avoid calling any long-running methods such as "ToDebugString" if logging is disabled. + /// + /// + /// + /// The generate message format. + /// The format items. + /// + public static void Info(this ILogger logger, string generateMessageFormat, params Func[] formatItems) + { + logger.Info(typeof(T), generateMessageFormat, formatItems); + } + + /// + /// Traces a message, only generating the message if tracing is actually enabled. Use this method to avoid calling any long-running methods such as "ToDebugString" if logging is disabled. + /// + /// + /// + /// The delegate to generate a message. + /// + public static void Info(this ILogger logger, Func generateMessage) + { + logger.Info(typeof(T), generateMessage); + } + + /// + /// Debugs a message, only generating the message if tracing is actually enabled. Use this method to avoid calling any long-running methods such as "ToDebugString" if logging is disabled. + /// + /// + /// + /// The delegate to generate a message. + /// + public static void Debug(this ILogger logger, Func generateMessage) + { + logger.Debug(typeof(T), generateMessage); + } + + /// + /// Debugs a message, only generating the message if debug is actually enabled. Use this method to avoid calling any long-running methods such as "ToDebugString" if logging is disabled. + /// + /// + /// + /// The generate message format. + /// The format items. + /// + public static void Debug(this ILogger logger, string generateMessageFormat, params Func[] formatItems) + { + logger.Debug(typeof(T), generateMessageFormat, formatItems); + } + } +} \ No newline at end of file diff --git a/src/Umbraco.Core/Logging/LoggerResolver.cs b/src/Umbraco.Core/Logging/LoggerResolver.cs new file mode 100644 index 0000000000..5ca0839c60 --- /dev/null +++ b/src/Umbraco.Core/Logging/LoggerResolver.cs @@ -0,0 +1,31 @@ +using Umbraco.Core.ObjectResolution; + +namespace Umbraco.Core.Logging +{ + public sealed class LoggerResolver : SingleObjectResolverBase + { + public LoggerResolver(ILogger logger) + : base(logger) + { + + } + + /// + /// Method allowing to change the logger during startup + /// + /// + internal void SetLogger(ILogger profiler) + { + Value = profiler; + } + + /// + /// Gets the current logger + /// + public ILogger Logger + { + get { return Value; } + } + + } +} \ No newline at end of file diff --git a/src/Umbraco.Core/Logging/ProfilingLogger.cs b/src/Umbraco.Core/Logging/ProfilingLogger.cs new file mode 100644 index 0000000000..0d1efeb0d9 --- /dev/null +++ b/src/Umbraco.Core/Logging/ProfilingLogger.cs @@ -0,0 +1,52 @@ +using System; +using Umbraco.Core.Profiling; + +namespace Umbraco.Core.Logging +{ + /// + /// Used to create DisposableTimer instances for debugging or tracing durations + /// + public sealed class ProfilingLogger + { + public ILogger Logger { get; private set; } + public IProfiler Profiler { get; private set; } + + public ProfilingLogger(ILogger logger, IProfiler profiler) + { + Logger = logger; + Profiler = profiler; + if (logger == null) throw new ArgumentNullException("logger"); + if (profiler == null) throw new ArgumentNullException("profiler"); + } + + public DisposableTimer TraceDuration(string startMessage, string completeMessage) + { + return new DisposableTimer(Logger, DisposableTimer.LogType.Info, Profiler, typeof(T), startMessage, completeMessage); + } + + public DisposableTimer TraceDuration(string startMessage) + { + return new DisposableTimer(Logger, DisposableTimer.LogType.Info, Profiler, typeof(T), startMessage, "Complete"); + } + + public DisposableTimer TraceDuration(Type loggerType, string startMessage, string completeMessage) + { + return new DisposableTimer(Logger, DisposableTimer.LogType.Info, Profiler, loggerType, startMessage, completeMessage); + } + + public DisposableTimer DebugDuration(string startMessage, string completeMessage) + { + return new DisposableTimer(Logger, DisposableTimer.LogType.Debug, Profiler, typeof(T), startMessage, completeMessage); + } + + public DisposableTimer DebugDuration(string startMessage) + { + return new DisposableTimer(Logger, DisposableTimer.LogType.Debug, Profiler, typeof(T), startMessage, "Complete"); + } + + public DisposableTimer DebugDuration(Type loggerType, string startMessage, string completeMessage) + { + return new DisposableTimer(Logger, DisposableTimer.LogType.Debug, Profiler, loggerType, startMessage, completeMessage); + } + } +} \ No newline at end of file diff --git a/src/Umbraco.Core/Macros/MacroFieldEditorsResolver.cs b/src/Umbraco.Core/Macros/MacroFieldEditorsResolver.cs index eb0366eb93..1788932c8f 100644 --- a/src/Umbraco.Core/Macros/MacroFieldEditorsResolver.cs +++ b/src/Umbraco.Core/Macros/MacroFieldEditorsResolver.cs @@ -4,6 +4,7 @@ using System.Linq; using System.Web; using System.Web.UI; using System.Linq; +using Umbraco.Core.Logging; using Umbraco.Core.ObjectResolution; using umbraco.interfaces; @@ -18,13 +19,14 @@ namespace Umbraco.Core.Macros /// internal sealed class MacroFieldEditorsResolver : LazyManyObjectsResolverBase { - - /// - /// Constructor - /// - /// - internal MacroFieldEditorsResolver(Func> macroEditors) - : base(macroEditors, ObjectLifetimeScope.Transient) + /// + /// Constructor + /// + /// + /// + /// + internal MacroFieldEditorsResolver(IServiceProvider serviceProvider, ILogger logger, Func> macroEditors) + : base(serviceProvider, logger, macroEditors, ObjectLifetimeScope.Transient) { } /// @@ -70,10 +72,10 @@ namespace Umbraco.Core.Macros internal Control GetMacroRenderControlByType(PersistableMacroProperty prop, string uniqueId) { var m = MacroControlTypes.FindLast(macroGuiCcontrol => macroGuiCcontrol.ToString() == string.Format("{0}.{1}", prop.AssemblyName, prop.TypeName)); - var instance = PluginManager.Current.CreateInstance(m); + var instance = ServiceProvider.GetService(m) as IMacroGuiRendering; if (instance != null) { - if (!string.IsNullOrEmpty(prop.Value)) + if (string.IsNullOrEmpty(prop.Value) == false) { instance.Value = HttpUtility.HtmlDecode(prop.Value); } diff --git a/src/Umbraco.Core/Macros/XsltExtensionsResolver.cs b/src/Umbraco.Core/Macros/XsltExtensionsResolver.cs index 7927ee5745..0c754c9d3f 100644 --- a/src/Umbraco.Core/Macros/XsltExtensionsResolver.cs +++ b/src/Umbraco.Core/Macros/XsltExtensionsResolver.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using Umbraco.Core.Logging; using Umbraco.Core.ObjectResolution; namespace Umbraco.Core.Macros @@ -9,13 +10,14 @@ namespace Umbraco.Core.Macros /// internal sealed class XsltExtensionsResolver : LazyManyObjectsResolverBase { - /// - /// Constructor - /// - /// - internal XsltExtensionsResolver(Func> packageActions) - : base(packageActions, ObjectLifetimeScope.Application) + /// Constructor + /// + /// + /// + /// + internal XsltExtensionsResolver(IServiceProvider serviceProvider, ILogger logger, Func> packageActions) + : base(serviceProvider, logger, packageActions, ObjectLifetimeScope.Application) { } diff --git a/src/Umbraco.Core/Manifest/ManifestWatcher.cs b/src/Umbraco.Core/Manifest/ManifestWatcher.cs index f0bd46602b..24dff148be 100644 --- a/src/Umbraco.Core/Manifest/ManifestWatcher.cs +++ b/src/Umbraco.Core/Manifest/ManifestWatcher.cs @@ -1,3 +1,4 @@ +using System; using System.Collections.Generic; using System.IO; using System.Web; @@ -7,10 +8,17 @@ namespace Umbraco.Core.Manifest { internal class ManifestWatcher : DisposableObject { + private readonly ILogger _logger; private readonly List _fws = new List(); private static volatile bool _isRestarting = false; private static readonly object Locker = new object(); + public ManifestWatcher(ILogger logger) + { + if (logger == null) throw new ArgumentNullException("logger"); + _logger = logger; + } + public void Start(params string[] packageFolders) { foreach (var packageFolder in packageFolders) @@ -43,7 +51,7 @@ namespace Umbraco.Core.Manifest { _isRestarting = true; - LogHelper.Info("manifest has changed, app pool is restarting (" + e.FullPath + ")"); + _logger.Info("manifest has changed, app pool is restarting (" + e.FullPath + ")"); HttpRuntime.UnloadAppDomain(); Dispose(); } diff --git a/src/Umbraco.Core/Models/Css/CssCompactor.cs b/src/Umbraco.Core/Models/Css/CssCompactor.cs deleted file mode 100644 index 4f015fff69..0000000000 --- a/src/Umbraco.Core/Models/Css/CssCompactor.cs +++ /dev/null @@ -1,103 +0,0 @@ -using System; -using System.IO; -using System.Collections.Generic; - -namespace Umbraco.Core.Models.Css -{ - internal static class CssCompactor - { - #region CssCompactor.Options - - [Flags] - public enum Options - { - None = 0x00, - PrettyPrint = 0x01, - Overwrite = 0x02 - } - - #endregion CssCompactor.Options - - #region Public Methods - - internal static List Compact(string inputFile, string outputFile, string copyright, string timeStamp, CssCompactor.Options options) - { - if (!System.IO.File.Exists(inputFile)) - { - throw new FileNotFoundException(String.Format("File (\"{0}\") not found.", inputFile), inputFile); - } - - if ((options & CssCompactor.Options.Overwrite) == 0x0 && System.IO.File.Exists(outputFile)) - { - throw new AccessViolationException(String.Format("File (\"{0}\") already exists.", outputFile)); - } - - if (inputFile.Equals(outputFile, StringComparison.OrdinalIgnoreCase)) - { - throw new ApplicationException("Input and output file are set to the same path."); - } - - FileUtility.PrepSavePath(outputFile); - using (TextWriter output = System.IO.File.CreateText(outputFile)) - { - return CssCompactor.Compact(inputFile, null, output, copyright, timeStamp, options); - } - } - - internal static List Compact(string inputFile, string inputSource, TextWriter output, string copyright, string timeStamp, CssCompactor.Options options) - { - if (output == null) - { - throw new NullReferenceException("Output TextWriter was null."); - } - - // write out header with copyright and timestamp - CssCompactor.WriteHeader(output, copyright, timeStamp); - - // verify, compact and write out results - CssParser parser = new CssParser(inputFile, inputSource); - parser.Write(output, options); - - // return any errors - return parser.Errors; - } - - #endregion Public Methods - - #region Private Methods - - private static void WriteHeader(TextWriter writer, string copyright, string timeStamp) - { - if (!String.IsNullOrEmpty(copyright) || !String.IsNullOrEmpty(timeStamp)) - { - int width = 6; - if (!String.IsNullOrEmpty(copyright)) - { - copyright = copyright.Replace("*/", "");// make sure not to nest commments - width = Math.Max(copyright.Length + 6, width); - } - if (!String.IsNullOrEmpty(timeStamp)) - { - timeStamp = DateTime.Now.ToString(timeStamp).Replace("*/", "");// make sure not to nest commments - width = Math.Max(timeStamp.Length + 6, width); - } - - writer.WriteLine("/*".PadRight(width, '-') + "*\\"); - - if (!String.IsNullOrEmpty(copyright)) - { - writer.WriteLine("\t" + copyright); - } - - if (!String.IsNullOrEmpty(timeStamp)) - { - writer.WriteLine("\t" + timeStamp); - } - - writer.WriteLine("\\*".PadRight(width, '-') + "*/"); - } - } - - #endregion Private Methods - } -} \ No newline at end of file diff --git a/src/Umbraco.Core/Models/Css/CssParser.cs b/src/Umbraco.Core/Models/Css/CssParser.cs deleted file mode 100644 index 1c20e31279..0000000000 --- a/src/Umbraco.Core/Models/Css/CssParser.cs +++ /dev/null @@ -1,653 +0,0 @@ -using System; -using System.IO; -using System.Collections.Generic; -using System.Linq; - -namespace Umbraco.Core.Models.Css -{ - internal class CssParser - { - #region Constants - - // this defines comments for CSS - private static readonly ReadFilter[] ReadFilters = new ReadFilter[] { new ReadFilter("/*", "*/") }; - private readonly object SyncLock = new object(); - - #endregion Constants - - #region Fields - - private readonly List errors = new List(); - private LineReader reader; - private CssStyleSheet styleSheet; - private string fileContent; - private string source; - - #endregion Fields - - #region Init - - /// - /// Ctor. - /// - /// path to source - public CssParser(string fileContent) - : this(fileContent, null) - { - } - - /// - /// Ctor. - /// - /// path to source - /// actual source - public CssParser(string fileContent, string source) - { - this.fileContent = fileContent; - this.source = source; - } - - #endregion Init - - #region Properties - - public List Errors - { - get { return this.errors; } - } - - public CssStyleSheet StyleSheet - { - get - { - if (this.styleSheet == null) - { - lock (this.SyncLock) - { - // check again in case race condition - // so we don't parse twice - if (this.styleSheet == null) - { - this.styleSheet = this.ParseStyleSheet(); - } - } - } - return this.styleSheet; - } - } - - private int Position - { - get { return this.reader.Position; } - } - - #endregion Properties - - #region Parse Methods - - #region StyleSheet - - /// - /// (BNF) stylesheet : [ CDO | CDC | S | statement ]*; - /// - /// CSS StyleSheet parse tree - private CssStyleSheet ParseStyleSheet() - { - CssStyleSheet styleSheet = new CssStyleSheet(); - using (this.reader = new LineReader(this.fileContent, this.source, CssParser.ReadFilters)) - { - this.reader.NormalizeWhiteSpace = true; - -#if DEBUG - System.Diagnostics.Stopwatch watch = System.Diagnostics.Stopwatch.StartNew(); -#endif - - char ch; - while (this.Read(out ch)) - { - switch (ch) - { - case '\uFEFF': // BOM (UTF byte order mark) - case '\t': //TAB - case '\n': //LF - case '\r': //CR - case ' ': //Space - { - // skip whitespace - continue; - } - case '<': - { - // CDO (Char Data Open?) - if (!this.Read(out ch) || ch != '-' || - !this.Read(out ch) || ch != '-') - { - throw new SyntaxError("Expected \"\"", this.reader.FilePath, this.reader.Line, this.reader.Column); - } - continue; - } - default: - { - try - { - CssStatement statement = this.ParseStatement(); - styleSheet.Statements.Add(statement); - } - catch (ParseException ex) - { - this.errors.Add(ex); - - while (this.Read(out ch) && ch != '}') - { - // restabilize on next statement - } - } - continue; - } - } - } - -#if DEBUG - watch.Stop(); - Console.WriteLine("CSS parse duration: {0} ms for {1} chars", watch.ElapsedMilliseconds, this.reader.Length); -#endif - } - - this.reader = null; - this.source = null; - - return styleSheet; - } - - #endregion StyleSheet - - #region Statement - - /// - /// (BNF) statement : ruleset | at-rule; - /// - /// - private CssStatement ParseStatement() - { - if (this.reader.Current == '@') - { - return this.ParseAtRule(); - } - else - { - this.PutBack(); - return this.ParseRuleSet(); - } - } - - #endregion Statement - - #region At-Rule - - /// - /// (BNF) at-rule : ATKEYWORD S* any* [ block | ';' S* ]; - /// - /// - /// - /// NOTE: each at-rule might parse differently according to CSS3 - /// The @media block for example contains a block of statements - /// while other at-rules with a block contain a block of declarations - /// - private CssAtRule ParseAtRule() - { - CssAtRule atRule = new CssAtRule(); - int start = this.Position + 1;// start with first char of ident - - char ch; - while (this.Read(out ch) && !Char.IsWhiteSpace(ch)) - { - // continue consuming - } - - atRule.Ident = this.Copy(start); - - while (this.Read(out ch) && Char.IsWhiteSpace(ch)) - { - // consuming whitespace - } - - start = this.Position;// start with current char - do - { - switch (ch) - { - case '{': //Block Begin - { - atRule.Value = this.Copy(start); - - bool containsRuleSets = String.Equals(atRule.Ident, CssAtRule.MediaIdent, StringComparison.Ordinal); - while (true) - { - while (this.Read(out ch) && Char.IsWhiteSpace(ch)) - { - // consume whitespace - } - - if (ch == '}') - { - break; - } - - try - { - if (containsRuleSets) - { - // includes @media - CssStatement statement = this.ParseStatement(); - atRule.Block.Values.Add(statement); - } - else - { - // includes @font-face, @page - this.PutBack(); - CssDeclaration declaration = this.ParseDeclaration(); - atRule.Block.Values.Add(declaration); - } - } - catch (ParseException ex) - { - this.errors.Add(ex); - - while (this.Read(out ch) && ch != '}') - { - // restabilize on block end - } - break; - } - } - return atRule; - } - case ';': //At-Rule End - { - atRule.Value = this.Copy(start); - return atRule; - } - } - } while (this.Read(out ch)); - - throw new UnexpectedEndOfFile("Unclosed At-Rule", this.reader.FilePath, this.reader.Line, this.reader.Column); - } - - #endregion At-Rule - - #region RuleSet - - /// - /// (BNF) ruleset : selector? '{' S* declaration? [ ';' S* declaration? ]* '}' S*; - /// - /// - private CssRuleSet ParseRuleSet() - { - char ch; - CssRuleSet ruleSet = new CssRuleSet(); - - ParseSelectors: - while (true) - { - try - { - CssSelector selector = this.ParseSelector(); - if (selector == null) - { - break; - } - ruleSet.Selectors.Add(selector); - } - catch (ParseException ex) - { - this.errors.Add(ex); - - while (this.Read(out ch)) - { - // restabalize on next rulset - switch (ch) - { - case ',': - { - // continue parsing rest of Selectors - goto ParseSelectors; - } - case '{': - { - goto ParseDeclarations; - } - //case ':':// keep going - case ';': - case '}': - { - throw new SyntaxError("Invalid selector list", this.reader.FilePath, this.reader.Line, this.reader.Column); - } - } - } - } - } - - ParseDeclarations: - while (true) - { - try - { - CssDeclaration declaration = this.ParseDeclaration(); - if (declaration == null) - { - break; - } - ruleSet.Declarations.Add(declaration); - } - catch (ParseException ex) - { - this.errors.Add(ex); - - while (this.Read(out ch)) - { - // restabalize on next declaration - switch (ch) - { - case '{': - { - throw new SyntaxError("Invalid ruleset", this.reader.FilePath, this.reader.Line, this.reader.Column); - } - //case ':':// keep going - case ';': - { - // continue parsing rest of delcarations - goto ParseDeclarations; - } - case '}': - { - // no more declarations - return ruleSet; - } - } - } - } - } - - return ruleSet; - } - - #endregion RuleSet - - #region Selector - - /// - /// (BNF) selector: any+; - /// - /// - private CssSelector ParseSelector() - { - CssSelector selector = new CssSelector(); - char ch; - - while (this.Read(out ch) && (Char.IsWhiteSpace(ch) || ch == ',')) - { - // skip whitespace, and empty selectors - } - - // consume property name - switch (ch) - { - case '{': - { - // no more declarations - return null; - } - //case ':':// pseudoclass - case ';': - case '}': - { - throw new SyntaxError("Invalid chars in selector", this.reader.FilePath, this.reader.Line, this.reader.Column); - } - } - - int start = this.Position;// start with current char - - while (this.Read(out ch)) - { - // continue consuming selector - switch (ch) - { - case ',': - case '{': - { - selector.Value = this.Copy(start); - if (ch == '{') - { - this.PutBack(); - } - return selector; - } - //case ':':// pseudoclass - case ';': - case '}': - { - throw new SyntaxError("Invalid selector", this.reader.FilePath, this.reader.Line, this.reader.Column); - } - } - } - throw new UnexpectedEndOfFile("Unclosed ruleset", this.reader.FilePath, this.reader.Line, this.reader.Column); - } - - #endregion Selector - - #region Declaration - - /// - /// (BNF) declaration : property ':' S* value; - /// (BNF) property : IDENT S*; - /// - /// - private CssDeclaration ParseDeclaration() - { - CssDeclaration declaration = new CssDeclaration(); - char ch; - - while (this.Read(out ch) && (Char.IsWhiteSpace(ch) || ch == ';')) - { - // skip whitespace, and empty declarations - } - - // consume property name - switch (ch) - { - case '{': - case ':': - //case ';': - { - throw new SyntaxError("Declaration missing property name", this.reader.FilePath, this.reader.Line, this.reader.Column); - } - case '}': - { - // no more declarations - return null; - } - } - - // read property, starting with current char - int start = this.Position; - while (this.Read(out ch) && !Char.IsWhiteSpace(ch) && ch != ':') - { - // consume property name - switch (ch) - { - case '{': - //case ':': - case ';': - { - throw new SyntaxError("Invalid CSS property name: " + this.Copy(start), this.reader.FilePath, this.reader.Line, this.reader.Column); - } - case '}': - { - this.PutBack(); - goto case ';'; - } - } - } - declaration.Property = this.Copy(start); - - if (Char.IsWhiteSpace(ch)) - { - while (this.Read(out ch) && (Char.IsWhiteSpace(ch))) - { - // skip whitespace - } - } - - if (ch != ':') - { - // missing the property delim and value - - if (ch == ';' || ch == '}') - { - // these are good chars for resyncing - // so put them back on the stream to - // not create subsequent errors - this.PutBack(); - } - throw new SyntaxError("Expected : ", this.reader.FilePath, this.reader.Line, this.reader.Column); - } - - CssValueList value = this.ParseValue(); - declaration.Value = value; - - return declaration; - } - - #endregion Declaration - - #region Value - - /// - /// (BNF) value : [ any | block | ATKEYWORD S* ]+; - /// (BNF) any : [ IDENT | NUMBER | PERCENTAGE | DIMENSION | STRING - /// | DELIM | URI | HASH | UNICODE-RANGE | INCLUDES - /// | FUNCTION S* any* ')' | DASHMATCH | '(' S* any* ')' - /// | '[' S* any* ']' ] S*; - /// - /// - private CssValueList ParseValue() - { - CssValueList value = new CssValueList(); - char ch; - - while (this.Read(out ch) && Char.IsWhiteSpace(ch)) - { - // skip whitespace, and empty declarations - } - - switch (ch) - { - case '{': - case ':': - case ';': - case '}': - { - throw new SyntaxError("Invalid char in CSS property value: '" + ch + "'", this.reader.FilePath, this.reader.Line, this.reader.Column); - } - } - - // read value, starting with current char - int start = this.Position; - while (this.Read(out ch)) - { - // consume declaration value - - switch (ch) - { - case '{': - //case ':':// leave in for "filter: progid:DXImageTransform.Microsoft..." - { - throw new SyntaxError("Invalid CSS property value: " + this.Copy(start), this.reader.FilePath, this.reader.Line, this.reader.Column); - } - case '}': - case ';': - { - //Should this parse the value further? - - CssString any = new CssString(); - any.Value = this.Copy(start); - value.Values.Add(any); - if (ch == '}') - { - this.PutBack(); - } - return value; - } - } - } - throw new UnexpectedEndOfFile("Unclosed declaration", this.reader.FilePath, this.reader.Line, this.reader.Column); - } - - #endregion Value - - #endregion Parse Methods - - #region Methods - - public void Write(TextWriter writer, CssCompactor.Options options) - { - this.StyleSheet.Write(writer, options); - } - - #endregion Methods - - #region Reader Methods - - /// - /// - /// - /// - /// Success - private bool Read(out char ch) - { - if (this.reader.EndOfFile) - { - throw new UnexpectedEndOfFile("Unexpected end of file", this.reader.FilePath, this.reader.Line, this.reader.Column); - } - - int c = this.reader.Read(); - if (c < 0) - { - ch = '\0'; - return false; - } - ch = (char)c; - return true; - } - - /// - /// Copies chars from start until the position before the current position - /// - /// - private string Copy(int start) - { - // read block - return this.reader.Copy(start, this.reader.Position - 1); - } - - /// - /// Put one character back - /// - private void PutBack() - { - this.reader.PutBack(); - } - - #endregion Reader Methods - } -} \ No newline at end of file diff --git a/src/Umbraco.Core/Models/Css/CssSyntax.cs b/src/Umbraco.Core/Models/Css/CssSyntax.cs deleted file mode 100644 index b91047a6d9..0000000000 --- a/src/Umbraco.Core/Models/Css/CssSyntax.cs +++ /dev/null @@ -1,429 +0,0 @@ -using System; -using System.IO; -using System.Collections.Generic; -using System.Text; - -namespace Umbraco.Core.Models.Css -{ - #region Base Types - - /// - /// CSS3 inconsistently specifies more than one grammar: - /// http://www.w3.org/TR/css3-syntax/#style - /// http://www.w3.org/TR/css3-syntax/#detailed-grammar - /// - internal abstract class CssSyntax - { - #region Methods - - public abstract void Write(TextWriter writer, CssCompactor.Options options); - - protected static bool IsPrettyPrint(CssCompactor.Options options) - { - return (options & CssCompactor.Options.PrettyPrint) > 0; - } - - #endregion Methods - - #region Object Overrides - - public override string ToString() - { - var writer = new StringWriter(); - - this.Write(writer, CssCompactor.Options.PrettyPrint); - - return writer.ToString(); - } - - #endregion Object Overrides - } - - internal interface ICssValue - { - #region Methods - - void Write(TextWriter writer, CssCompactor.Options options); - - #endregion Methods - } - - internal class CssString : CssSyntax - { - #region Fields - - private string value; - - #endregion Fields - - #region Properties - - public virtual string Value - { - get { return this.value; } - set { this.value = value; } - } - - #endregion Properties - - #region Methods - - public override void Write(TextWriter writer, CssCompactor.Options options) - { - writer.Write(this.Value); - } - - #endregion Methods - } - - #endregion Base Types - - #region Grammar - - internal class CssStyleSheet : CssSyntax - { - #region Fields - - private readonly List statements = new List(); - - #endregion Fields - - #region Properties - - public List Statements - { - get { return this.statements; } - } - - #endregion Properties - - #region Methods - - public override void Write(TextWriter writer, CssCompactor.Options options) - { - bool prettyPrint = IsPrettyPrint(options); - - foreach (CssStatement statement in this.statements) - { - statement.Write(writer, options); - if (prettyPrint) - { - writer.WriteLine(); - } - } - } - - #endregion Methods - } - - internal abstract class CssStatement : CssSyntax, ICssValue - { - } - - /// - /// - /// - /// - /// NOTE: each at-rule might parse differently according to CSS3 - /// The @media block for example contains a block of statements - /// while other at-rules with a block contain a block of declarations - /// - internal class CssAtRule : CssStatement - { - #region Constants - - internal const string MediaIdent = "media"; - - #endregion Constants - - #region Fields - - private string ident; - private string value; - - private CssBlock block; - - #endregion Fields - - #region Properties - - public string Ident - { - get { return this.ident; } - set { this.ident = value; } - } - - public string Value - { - get { return this.value; } - set { this.value = value; } - } - - public CssBlock Block - { - get - { - if (this.block == null) - { - this.block = new CssBlock(); - } - return this.block; - } - set { this.block = value; } - } - - #endregion Properties - - #region Methods - - public override void Write(TextWriter writer, CssCompactor.Options options) - { - bool prettyPrint = IsPrettyPrint(options); - - writer.Write('@'); - writer.Write(this.ident); - - if (!String.IsNullOrEmpty(this.value)) - { - writer.Write(' '); - writer.Write(this.value); - } - - if (this.block != null) - { - if (prettyPrint) - { - writer.WriteLine(); - } - this.block.Write(writer, options); - } - else - { - writer.Write(';'); - } - - if (prettyPrint) - { - writer.WriteLine(); - } - } - - #endregion Methods - } - - internal class CssBlock : CssSyntax, ICssValue - { - #region Fields - - private readonly List values = new List(); - - #endregion Fields - - #region Properties - - public List Values - { - get { return this.values; } - } - - #endregion Properties - - #region Methods - - public override void Write(TextWriter writer, CssCompactor.Options options) - { - bool prettyPrint = IsPrettyPrint(options); - - writer.Write('{'); - if (prettyPrint) - { - writer.WriteLine(); - } - - foreach (ICssValue value in this.Values) - { - value.Write(writer, options); - } - - if (prettyPrint) - { - writer.WriteLine(); - } - writer.Write('}'); - } - - #endregion Methods - } - - internal class CssRuleSet : CssStatement - { - #region Fields - - private readonly List selectors = new List(); - private readonly List declarations = new List(); - - #endregion Fields - - #region Properties - - public List Selectors - { - get { return this.selectors; } - } - - public List Declarations - { - get { return this.declarations; } - } - - #endregion Properties - - #region Methods - - public override void Write(TextWriter writer, CssCompactor.Options options) - { - bool prettyPrint = IsPrettyPrint(options); - - bool comma = false; - - foreach (CssString selector in this.Selectors) - { - if (comma) - { - writer.Write(","); - if (prettyPrint) - { - writer.WriteLine(); - } - } - else - { - comma = true; - } - - selector.Write(writer, options); - } - - if (prettyPrint) - { - writer.WriteLine(); - } - writer.Write("{"); - if (prettyPrint) - { - writer.WriteLine(); - } - - foreach (CssDeclaration dec in this.Declarations) - { - dec.Write(writer, options); - } - - writer.Write("}"); - if (prettyPrint) - { - writer.WriteLine(); - } - } - - #endregion Methods - } - - internal class CssSelector : CssString - { - } - - internal class CssDeclaration : CssSyntax, ICssValue - { - #region Fields - - private string property; - private CssValueList value; - - #endregion Fields - - #region Properties - - public string Property - { - get { return this.property; } - set { this.property = value; } - } - - public CssValueList Value - { - get { return this.value; } - set { this.value = value; } - } - - #endregion Properties - - #region Methods - - public override void Write(TextWriter writer, CssCompactor.Options options) - { - bool prettyPrint = IsPrettyPrint(options); - if (prettyPrint) - { - writer.Write('\t'); - } - writer.Write(this.Property); - writer.Write(':'); - if (prettyPrint) - { - writer.Write(" "); - } - this.Value.Write(writer, options); - writer.Write(";"); - if (prettyPrint) - { - writer.WriteLine(); - } - } - - #endregion Methods - } - - internal class CssValueList : CssSyntax - { - #region Fields - - private readonly List values = new List(); - - #endregion Fields - - #region Properties - - public List Values - { - get { return this.values; } - } - - #endregion Properties - - #region Methods - - public override void Write(TextWriter writer, CssCompactor.Options options) - { - bool space = false; - - foreach (CssString value in this.Values) - { - if (space) - { - writer.Write(" "); - } - else - { - space = true; - } - - value.Write(writer, options); - } - } - - #endregion Methods - } - - #endregion Grammar -} \ No newline at end of file diff --git a/src/Umbraco.Core/Models/Css/FileUtility.cs b/src/Umbraco.Core/Models/Css/FileUtility.cs deleted file mode 100644 index 010feaf751..0000000000 --- a/src/Umbraco.Core/Models/Css/FileUtility.cs +++ /dev/null @@ -1,71 +0,0 @@ -using System; -using System.Collections.Generic; -using System.IO; - -namespace Umbraco.Core.Models.Css -{ - internal class FileUtility - { - #region Constants - - private static readonly char[] IllegalChars; - - #endregion Constants - - #region Init - - static FileUtility() - { - var chars = new List(Path.GetInvalidPathChars()); - foreach (char ch in Path.GetInvalidFileNameChars()) - { - if (!chars.Contains(ch) && ch != Path.DirectorySeparatorChar) - { - chars.Add(ch); - } - } - IllegalChars = chars.ToArray(); - } - - #endregion Init - - #region Methods - - /// - /// Makes sure directory exists and if file exists is not readonly. - /// - /// - /// if valid path - internal static bool PrepSavePath(string filename) - { - if (System.IO.File.Exists(filename)) - { - // make sure not readonly - FileAttributes attributes = System.IO.File.GetAttributes(filename); - attributes &= ~FileAttributes.ReadOnly; - System.IO.File.SetAttributes(filename, attributes); - } - else - { - string dir = Path.GetDirectoryName(filename); - if (!String.IsNullOrEmpty(dir) && dir.IndexOfAny(IllegalChars) >= 0) - { - return false; - } - if (!String.IsNullOrEmpty(dir) && !Directory.Exists(dir)) - { - // make sure path exists - Directory.CreateDirectory(dir); - } - string file = Path.GetFileName(filename); - if (!String.IsNullOrEmpty(file) && file.IndexOfAny(Path.GetInvalidFileNameChars()) >= 0) - { - return false; - } - } - return true; - } - - #endregion Methods - } -} \ No newline at end of file diff --git a/src/Umbraco.Core/Models/Css/FilterTrie.cs b/src/Umbraco.Core/Models/Css/FilterTrie.cs deleted file mode 100644 index 4ad4d2a774..0000000000 --- a/src/Umbraco.Core/Models/Css/FilterTrie.cs +++ /dev/null @@ -1,80 +0,0 @@ -using System; -using System.Collections.Generic; - -namespace Umbraco.Core.Models.Css -{ - /// - /// Defines a character sequence to filter out when reading. - /// - /// - /// If the sequence exists in the read source, it will be read out as if it was never there. - /// - internal struct ReadFilter - { - #region Fields - - public readonly string StartToken; - public readonly string EndToken; - - #endregion Fields - - #region Init - - public ReadFilter(string start, string end) - { - if (String.IsNullOrEmpty(start)) - { - throw new ArgumentNullException("start"); - } - if (String.IsNullOrEmpty(end)) - { - throw new ArgumentNullException("end"); - } - - this.StartToken = start; - this.EndToken = end; - } - - #endregion Init - } - - /// - /// Creates a Trie out of ReadFilters - /// - internal class FilterTrie : TrieNode - { - #region Constants - - private const int DefaultTrieWidth = 1; - - #endregion Constants - - #region Init - - internal FilterTrie(IEnumerable filters) - : base(DefaultTrieWidth) - { - // load trie - foreach (ReadFilter filter in filters) - { - TrieNode node = this; - - // build out the path for StartToken - foreach (char ch in filter.StartToken) - { - if (!node.Contains(ch)) - { - node[ch] = new TrieNode(DefaultTrieWidth); - } - - node = (TrieNode)node[ch]; - } - - // at the end of StartToken path is the EndToken - node.Value = filter.EndToken; - } - } - - #endregion Init - } -} \ No newline at end of file diff --git a/src/Umbraco.Core/Models/Css/LineReader.cs b/src/Umbraco.Core/Models/Css/LineReader.cs deleted file mode 100644 index eef5f7ba62..0000000000 --- a/src/Umbraco.Core/Models/Css/LineReader.cs +++ /dev/null @@ -1,464 +0,0 @@ -using System; -using System.Collections.Generic; -using System.IO; - -namespace Umbraco.Core.Models.Css -{ - internal class LineReader : TextReader - { - #region Fields - - private int line = 1; - private int column = 0; - private int position = -1; - - private string filePath; - private string source; - - private readonly FilterTrie trie; - - private bool normalizeWhiteSpace = false; - - #endregion Fields - - #region Init - - /// - /// Ctor. - /// - /// - /// - /// - internal LineReader(string filePath, IEnumerable filters) : this(filePath, null, filters) { } - - /// - /// Ctor. - /// - /// - /// - /// - internal LineReader(string filePath, string source, IEnumerable filters) - { - this.trie = new FilterTrie(filters); - this.source = source; - this.filePath = filePath; - - if (this.source == null) - { - this.source = filePath;//Changed to direct content string instead of file. - /*if (System.IO.File.Exists(filePath)) - { - this.source = System.IO.File.ReadAllText(filePath); - } - else - { - throw new FileError("File not found", filePath, 0, 0); - }*/ - } - } - - /// - /// Ctor. - /// - /// - /// - internal LineReader(string filePath, string source) - : this(filePath, source, new ReadFilter[0]) - { - } - - #endregion Init - - #region Properties - - /// - /// Gets the path to the source file - /// - public string FilePath - { - get { return this.filePath; } - } - - /// - /// Gets the size of source file in chars - /// - public int Length - { - get { return this.source.Length; } - } - - /// - /// Gets the current line number - /// - public int Line - { - get { return this.line; } - } - - /// - /// Gets the current col number - /// - public int Column - { - get { return this.column; } - } - - /// - /// Gets the current char position - /// - public int Position - { - get { return this.position; } - } - - /// - /// Gets if at end the end of file - /// - public bool EndOfFile - { - get { return this.position >= this.source.Length; } - } - - /// - /// Gets and sets if whitespace is normalized while reading - /// - public bool NormalizeWhiteSpace - { - get { return this.normalizeWhiteSpace; } - set { this.normalizeWhiteSpace = value; } - } - - /// - /// Gets the current char - /// - public int Current - { - get - { - if (this.EndOfFile) - { - return -1; - } - return this.source[this.position]; - } - } - - #endregion Properties - - #region TextReader Members - - /// - /// Unfiltered look ahead - /// - /// - public override int Peek() - { - return this.Peek(1); - } - - /// - /// Filtered read of the next source char. Counters are incremented. - /// - /// - /// - /// NewLine sequences (CR/LF, LF, CR) are normalized to LF. - /// - public override int Read() - { - return this.Read(true); - } - - #endregion TextReader Members - - #region Utility Methods - - /// - /// Backs the current position up one. - /// - public void PutBack() - { - if (this.position < 0) - { - throw new InvalidOperationException("Already at start of source"); - } - switch (this.source[this.position]) - { - case '\r': //CR - { - // manipulate CR/LF as one char - if ((this.position + 1 < this.Length) && this.source[this.position + 1] == '\n') - { - this.position--; - } - break; - } - case '\n': //LF - case '\f': //FF - { - this.line--; - break; - } - } - this.column--; - this.position--; - } - - /// - /// Copies a range from the source - /// - /// starting position, inclusive - /// ending position, inclusive - /// - public string Copy(int start, int end) - { - if (start < 0) - { - throw new ArgumentOutOfRangeException("start"); - } - if (end < 0) - { - throw new ArgumentOutOfRangeException("end"); - } - if (end < 1) - { - return null; - } - - // set to just before read, next char is start - int copyPosition = start - 1; - - // allocate the full range but may not use due to filtering - char[] buffer = new char[end - start + 1]; - - int count = 0; - while (copyPosition < end) - { - int ch = this.CopyRead(ref copyPosition); - if (ch == -1) - { - throw new UnexpectedEndOfFile("Read past end of file", this.FilePath, this.Line, this.Column); - } - buffer[count] = (char)ch; - count++; - } - - if (count < 1) - { - return null; - } - return new String(buffer, 0, count).Trim(); - } - - #endregion Utility Methods - - #region Filter Methods - - /// - /// Peeks with n chars of lookahead. - /// - /// - /// unfiltered read - protected int Peek(int lookahead) - { - int pos = this.position + lookahead; - if (pos >= this.source.Length) - { - return -1; - } - return this.source[pos]; - } - - /// - /// Reads the next char - /// - /// if filtering - /// the next char, or -1 if at EOF - protected int Read(bool filter) - { - if (this.position + 1 >= this.source.Length) - { - this.position = this.source.Length; - return -1; - } - - // increment counters - this.position++; - this.column++; - char ch = this.source[this.position]; - - if (Char.IsWhiteSpace(ch)) - { - ch = this.NormalizeSpaces(ch, ref this.position, ref this.line, ref this.column); - } - - return filter ? this.Filter(ch) : ch; - } - - /// - /// Normalized CR/CRLF/LF/FF to LF, or all whitespace to SPACE if NormalizeWhiteSpace is true - /// - /// - /// - /// - /// - /// - private char NormalizeSpaces(char ch, ref int pos, ref int line, ref int col) - { - int length = this.source.Length; - if (this.normalizeWhiteSpace) - { - // normalize runs of WhiteSpace to ' ' - while ((pos + 1 < length) && Char.IsWhiteSpace(this.source, pos + 1)) - { - pos++; - col++; - - // increment line count - switch (this.source[pos]) - { - case '\r': //CR - { - // manipulate CR/LF as one char - if ((pos + 1 < length) && this.source[pos + 1] == '\n') - { - pos++; - } - goto case '\n'; - } - case '\n': //LF - case '\f': //FF - { - line++; - col = 0; - break; - } - } - } - ch = ' '; - } - else - { - // normalize NewLines to '\n', increment line count - switch (ch) - { - case '\r': //CR - { - // manipulate CR/LF as one char - if ((pos + 1 < length) && this.source[pos + 1] == '\n') - { - pos++; - } - goto case '\n'; - } - case '\n': //LF - case '\f': //FF - { - line++; - col = 0; - ch = '\n'; - break; - } - } - } - return ch; - } - - /// - /// Read for Copying (doesn't reset line.col counters) - /// - /// - /// - protected int CopyRead(ref int copyPosition) - { - if (copyPosition + 1 >= this.source.Length) - { - return -1; - } - - // increment counters - copyPosition++; - char ch = this.source[copyPosition]; - - if (Char.IsWhiteSpace(ch)) - { - int dummyLine = 0, dummyCol = 0; - ch = this.NormalizeSpaces(ch, ref copyPosition, ref dummyLine, ref dummyCol); - } - - return this.Filter(ch); - } - - /// - /// Filters based upon an internal Trie - /// - /// - /// - private int Filter(char ch) - { - int lookAhead = 0; - ITrieNode node = this.trie[ch]; - - while (node != null) - { - if (node.HasValue) - { - // found StartToken - string endToken = node.Value; - int length = endToken.Length; - - // move to end of StartToken - this.position += lookAhead; - - for (int i = 0; i < length; i++) - { - int ch2 = this.Read(false); - if (ch < 0) - { - throw new UnexpectedEndOfFile("Expected " + endToken, this.FilePath, this.Line, this.Column); - } - if (ch2 != endToken[i]) - { - // reset search - while (i > 0) - { - i--; - this.PutBack(); - } - i--; - } - } - return this.Read(true); - } - else - { - lookAhead++; - int pk = this.Peek(lookAhead); - if (pk < 0) - { - return ch; - } - node = node[(char)pk]; - } - } - - return ch; - } - - #endregion Filter Methods - - #region IDisposable Members - - /// - /// Free source resources. - /// - /// - protected override void Dispose(bool disposing) - { - base.Dispose(disposing); - - this.source = null; - } - - #endregion IDisposable Members - } -} \ No newline at end of file diff --git a/src/Umbraco.Core/Models/Css/ParseException.cs b/src/Umbraco.Core/Models/Css/ParseException.cs deleted file mode 100644 index be01f9f50c..0000000000 --- a/src/Umbraco.Core/Models/Css/ParseException.cs +++ /dev/null @@ -1,224 +0,0 @@ -using System; - -namespace Umbraco.Core.Models.Css -{ - internal enum ParseExceptionType - { - Warning, - Error - } - - [Serializable] - internal abstract class ParseException : ApplicationException - { - #region Constants - - // this cannot change every char is important or Visual Studio will not list as error/warning - // http://blogs.msdn.com/msbuild/archive/2006/11/03/msbuild-visual-studio-aware-error-messages-and-message-formats.aspx - private const string MSBuildErrorFormat = "{0}({1},{2}): {3} {4}: {5}"; - - #endregion Constants - - #region Fields - - private string file; - private int line; - private int column; - private int code = 0; - - #endregion Fields - - #region Init - - public ParseException(string message, string file, int line, int column) - : base(message) - { - this.file = file; - this.line = line; - this.column = column; - } - - public ParseException(string message, string file, int line, int column, Exception innerException) - : base(message, innerException) - { - this.file = file; - this.line = line; - this.column = column; - } - - #endregion Init - - #region Properties - - public abstract ParseExceptionType Type - { - get; - } - - public virtual int Code - { - get { return this.code; } - } - - public string ErrorCode - { - get - { - string ext = System.IO.Path.GetExtension(file); - if (ext == null || ext.Length < 2) - { - return null; - } - - return ext.Substring(1).ToUpperInvariant() + this.Code.ToString("####0000"); - } - } - - public string File - { - get { return this.file; } - } - - public int Line - { - get { return this.line; } - } - - public int Column - { - get { return this.column; } - } - - #endregion Properties - - #region Methods - - public virtual string GetCompilerMessage() - { - return this.GetCompilerMessage(this.Type == ParseExceptionType.Warning); - } - - public virtual string GetCompilerMessage(bool isWarning) - { - // format exception as a VS2005 error/warning - return String.Format( - ParseException.MSBuildErrorFormat, - this.File, - (this.Line > 0) ? this.Line : 1, - (this.Column > 0) ? this.Column : 1, - isWarning ? "warning" : "error", - this.ErrorCode, - this.Message); - } - - #endregion Methods - } - - [Serializable] - internal class ParseWarning : ParseException - { - #region Init - - public ParseWarning(string message, string file, int line, int column) - : base(message, file, line, column) - { - } - - public ParseWarning(string message, string file, int line, int column, Exception innerException) - : base(message, file, line, column, innerException) - { - } - - #endregion Init - - #region Properties - - public override ParseExceptionType Type - { - get { return ParseExceptionType.Warning; } - } - - #endregion Properties - } - - [Serializable] - internal class ParseError : ParseException - { - #region Init - - public ParseError(string message, string file, int line, int column) - : base(message, file, line, column) - { - } - - public ParseError(string message, string file, int line, int column, Exception innerException) - : base(message, file, line, column, innerException) - { - } - - #endregion Init - - #region Properties - - public override ParseExceptionType Type - { - get { return ParseExceptionType.Error; } - } - - #endregion Properties - } - - [Serializable] - internal class UnexpectedEndOfFile : ParseError - { - #region Init - - public UnexpectedEndOfFile(string message, string file, int line, int column) - : base(message, file, line, column) - { - } - - public UnexpectedEndOfFile(string message, string file, int line, int column, Exception innerException) - : base(message, file, line, column, innerException) - { - } - - #endregion Init - } - - [Serializable] - internal class FileError : ParseWarning - { - #region Init - - public FileError(string message, string file, int line, int column) - : base(message, file, line, column) - { - } - - public FileError(string message, string file, int line, int column, Exception innerException) - : base(message, file, line, column, innerException) - { - } - - #endregion Init - } - - [Serializable] - internal class SyntaxError : ParseError - { - #region Init - - public SyntaxError(string message, string file, int line, int column) - : base(message, file, line, column) - { - } - - public SyntaxError(string message, string file, int line, int column, Exception innerException) - : base(message, file, line, column, innerException) - { - } - - #endregion Init - } -} \ No newline at end of file diff --git a/src/Umbraco.Core/Models/Css/TrieNode.cs b/src/Umbraco.Core/Models/Css/TrieNode.cs deleted file mode 100644 index ba58c3b95e..0000000000 --- a/src/Umbraco.Core/Models/Css/TrieNode.cs +++ /dev/null @@ -1,139 +0,0 @@ -using System; -using System.Collections.Generic; - -namespace Umbraco.Core.Models.Css -{ - /// - /// A generic node for building a Trie - /// - /// the Type used for the node path - /// the Type used for the node value - /// - /// http://en.wikipedia.org/wiki/Trie - /// - internal class TrieNode : ITrieNode - { - #region Fields - - private readonly IDictionary> Children; - private TValue value = default(TValue); - - #endregion Fields - - #region Init - - /// - /// Ctor - /// - public TrieNode() - : this(-1) - { - } - - /// - /// Ctor. - /// - /// - public TrieNode(int capacity) - { - if (capacity < 1) - { - this.Children = new Dictionary>(); - } - else - { - this.Children = new Dictionary>(capacity); - } - } - - #endregion Init - - #region Properties - - public ITrieNode this[TKey key] - { - get - { - if (!this.Children.ContainsKey(key)) - { - return null; - } - return this.Children[key]; - } - - // added "internal" to get around change in C# 3.0 modifiers - // this worked fine in C# 2.0 but they fixed that bug - // http://blogs.msdn.com/ericlippert/archive/2008/03/28/why-can-t-i-access-a-protected-member-from-a-derived-class-part-two-why-can-i.aspx - protected internal set { this.Children[key] = value; } - } - - public TValue Value - { - get { return this.value; } - - // added "internal" to get around change in C# 3.0 modifiers - // this worked fine in C# 2.0 but they fixed that bug - // http://blogs.msdn.com/ericlippert/archive/2008/03/28/why-can-t-i-access-a-protected-member-from-a-derived-class-part-two-why-can-i.aspx - protected internal set - { - if (!EqualityComparer.Default.Equals(this.value, default(TValue))) - { - throw new InvalidOperationException("Trie path collision: the value for TrieNode<" + value.GetType().Name + "> has already been assigned."); - } - this.value = value; - } - } - - public bool HasValue - { - get - { - return !EqualityComparer.Default.Equals(this.value, default(TValue)); - } - } - - #endregion Properties - - #region Methods - - /// - /// Determines if child exists - /// - /// - /// - public bool Contains(TKey key) - { - return this.Children.ContainsKey(key); - } - - #endregion Methods - } - - internal interface ITrieNode - { - #region Properties - - ITrieNode this[TKey key] - { - get; - } - - TValue Value - { - get; - } - - bool HasValue - { - get; - } - - #endregion Methods - - #region Methods - - bool Contains(TKey key); - - #endregion Methods - } -} \ No newline at end of file diff --git a/src/Umbraco.Core/Models/DictionaryItem.cs b/src/Umbraco.Core/Models/DictionaryItem.cs index 6c2ee47714..de7fd3414f 100644 --- a/src/Umbraco.Core/Models/DictionaryItem.cs +++ b/src/Umbraco.Core/Models/DictionaryItem.cs @@ -19,7 +19,7 @@ namespace Umbraco.Core.Models private IEnumerable _translations; public DictionaryItem(string itemKey) - : this(new Guid("41c7638d-f529-4bff-853e-59a0c2fb1bde"), itemKey) + : this(new Guid(Constants.Conventions.Localization.DictionaryItemRootId), itemKey) {} public DictionaryItem(Guid parentId, string itemKey) @@ -95,7 +95,7 @@ namespace Umbraco.Core.Models //If ParentId is not set we should default to the root parent id if(ParentId == Guid.Empty) - _parentId = new Guid("41c7638d-f529-4bff-853e-59a0c2fb1bde"); + _parentId = new Guid(Constants.Conventions.Localization.DictionaryItemRootId); } } diff --git a/src/Umbraco.Core/Models/DictionaryTranslation.cs b/src/Umbraco.Core/Models/DictionaryTranslation.cs index f1c1af0eb7..782ff14413 100644 --- a/src/Umbraco.Core/Models/DictionaryTranslation.cs +++ b/src/Umbraco.Core/Models/DictionaryTranslation.cs @@ -18,12 +18,14 @@ namespace Umbraco.Core.Models public DictionaryTranslation(ILanguage language, string value) { + if (language == null) throw new ArgumentNullException("language"); _language = language; _value = value; } public DictionaryTranslation(ILanguage language, string value, Guid uniqueId) { + if (language == null) throw new ArgumentNullException("language"); _language = language; _value = value; Key = uniqueId; diff --git a/src/Umbraco.Core/Models/File.cs b/src/Umbraco.Core/Models/File.cs index 3513e4e031..9b3229e016 100644 --- a/src/Umbraco.Core/Models/File.cs +++ b/src/Umbraco.Core/Models/File.cs @@ -14,11 +14,13 @@ namespace Umbraco.Core.Models public abstract class File : Entity, IFile { private string _path; + private string _originalPath; private string _content = string.Empty; //initialize to empty string, not null protected File(string path) { _path = path; + _originalPath = _path; } private static readonly PropertyInfo ContentSelector = ExpressionHelper.GetPropertyInfo(x => x.Content); @@ -32,14 +34,7 @@ namespace Umbraco.Core.Models [DataMember] public virtual string Name { - get - { - if (_name == null) - { - _name = System.IO.Path.GetFileName(Path); - } - return _name; - } + get { return _name ?? (_name = System.IO.Path.GetFileName(Path)); } } /// @@ -82,6 +77,22 @@ namespace Umbraco.Core.Models } } + /// + /// Gets the original path of the file + /// + public string OriginalPath + { + get { return _originalPath; } + } + + /// + /// Called to re-set the OriginalPath to the Path + /// + public void ResetOriginalPath() + { + _originalPath = _path; + } + /// /// Gets or sets the Content of a File /// @@ -104,11 +115,11 @@ namespace Umbraco.Core.Models /// public string VirtualPath { get; set; } - /// - /// Boolean indicating whether the file could be validated - /// - /// True if file is valid, otherwise false - public abstract bool IsValid(); + [Obsolete("This is no longer used and will be removed from the codebase in future versions")] + public virtual bool IsValid() + { + return true; + } public override object DeepClone() { diff --git a/src/Umbraco.Core/Models/IFile.cs b/src/Umbraco.Core/Models/IFile.cs index b4d0b75a79..de900c50ec 100644 --- a/src/Umbraco.Core/Models/IFile.cs +++ b/src/Umbraco.Core/Models/IFile.cs @@ -1,4 +1,5 @@ -using Umbraco.Core.Models.EntityBase; +using System; +using Umbraco.Core.Models.EntityBase; namespace Umbraco.Core.Models { @@ -23,6 +24,16 @@ namespace Umbraco.Core.Models /// string Path { get; set; } + /// + /// Gets the original path of the file + /// + string OriginalPath { get; } + + /// + /// Called to re-set the OriginalPath to the Path + /// + void ResetOriginalPath(); + /// /// Gets or sets the Content of a File /// @@ -33,10 +44,7 @@ namespace Umbraco.Core.Models /// string VirtualPath { get; set; } - /// - /// Boolean indicating whether the file could be validated - /// - /// True if file is valid, otherwise false + [Obsolete("This is no longer used and will be removed from the codebase in future versions")] bool IsValid(); } } \ No newline at end of file diff --git a/src/Umbraco.Core/Models/ITemplate.cs b/src/Umbraco.Core/Models/ITemplate.cs index 33c80338b2..7a8d0c8bd0 100644 --- a/src/Umbraco.Core/Models/ITemplate.cs +++ b/src/Umbraco.Core/Models/ITemplate.cs @@ -1,4 +1,6 @@ -using Umbraco.Core.Models.EntityBase; +using System; +using System.Runtime.Serialization; +using Umbraco.Core.Models.EntityBase; namespace Umbraco.Core.Models { @@ -7,10 +9,31 @@ namespace Umbraco.Core.Models /// public interface ITemplate : IFile, IRememberBeingDirty, ICanBeDirty { + /// + /// Gets the Name of the File including extension + /// + new string Name { get; set; } + + /// + /// Gets the Alias of the File, which is the name without the extension + /// + new string Alias { get; set; } + + /// + /// Returns true if the template is used as a layout for other templates (i.e. it has 'children') + /// + bool IsMasterTemplate { get; } + + /// + /// returns the master template alias + /// + string MasterTemplateAlias { get; } + /// /// Returns the that corresponds to the template file /// /// + [Obsolete("This is no longer used and will be removed from the codebase in future versions, use the IFileSystem DetermineRenderingEngine method instead")] RenderingEngine GetTypeOfRenderingEngine(); /// diff --git a/src/Umbraco.Core/Models/PartialView.cs b/src/Umbraco.Core/Models/PartialView.cs index 0f0279d8d3..d483de4176 100644 --- a/src/Umbraco.Core/Models/PartialView.cs +++ b/src/Umbraco.Core/Models/PartialView.cs @@ -7,20 +7,7 @@ using Umbraco.Core.IO; namespace Umbraco.Core.Models { - //internal class PartialViewMacro : PartialView - //{ - // public PartialViewMacro() - // : base(string.Empty) - // { - // } - - // public PartialViewMacro(string path) : base(path) - // { - // } - - // public IMacro AssociatedMacro { get; set; } - //} - + /// /// Represents a Partial View file /// @@ -28,9 +15,6 @@ namespace Umbraco.Core.Models [DataContract(IsReference = true)] public class PartialView : File, IPartialView { - //public PartialView(): base(string.Empty) - //{ - //} public PartialView(string path) : base(path) @@ -38,19 +22,5 @@ namespace Umbraco.Core.Models base.Path = path; } - /// - /// Boolean indicating whether the file could be validated - /// - /// True if file is valid, otherwise false - public override bool IsValid() - { - //TODO: Why is this here? Needs to go on the FileService - - var validatePath = IOHelper.ValidateEditPath(Path, new[] { SystemDirectories.MvcViews + "/Partials/", SystemDirectories.MvcViews + "/MacroPartials/" }); - var verifyFileExtension = IOHelper.VerifyFileExtension(Path, new List { "cshtml" }); - - return validatePath && verifyFileExtension; - } - } } \ No newline at end of file diff --git a/src/Umbraco.Core/Models/Rdbms/RelationTypeDto.cs b/src/Umbraco.Core/Models/Rdbms/RelationTypeDto.cs index 62a27e9506..8a6eb5c02a 100644 --- a/src/Umbraco.Core/Models/Rdbms/RelationTypeDto.cs +++ b/src/Umbraco.Core/Models/Rdbms/RelationTypeDto.cs @@ -9,8 +9,10 @@ namespace Umbraco.Core.Models.Rdbms [ExplicitColumns] internal class RelationTypeDto { + public const int NodeIdSeed = 3; + [Column("id")] - [PrimaryKeyColumn(IdentitySeed = 2)] + [PrimaryKeyColumn(IdentitySeed = NodeIdSeed)] public int Id { get; set; } [Column("dual")] diff --git a/src/Umbraco.Core/Models/Rdbms/TemplateDto.cs b/src/Umbraco.Core/Models/Rdbms/TemplateDto.cs index ee24e4a0a6..8e2fe0b9f5 100644 --- a/src/Umbraco.Core/Models/Rdbms/TemplateDto.cs +++ b/src/Umbraco.Core/Models/Rdbms/TemplateDto.cs @@ -15,12 +15,7 @@ namespace Umbraco.Core.Models.Rdbms [Column("nodeId")] [Index(IndexTypes.UniqueNonClustered)] [ForeignKey(typeof(NodeDto), Name = "FK_cmsTemplate_umbracoNode")] - public int NodeId { get; set; } - - [Column("master")] - [NullSetting(NullSetting = NullSettings.Null)] - [ForeignKey(typeof(NodeDto), Name = "FK_cmsTemplate_cmsTemplate")] - public int? Master { get; set; } + public int NodeId { get; set; } [Column("alias")] [Length(100)] diff --git a/src/Umbraco.Core/Models/Script.cs b/src/Umbraco.Core/Models/Script.cs index e7df4a56e1..71f0684447 100644 --- a/src/Umbraco.Core/Models/Script.cs +++ b/src/Umbraco.Core/Models/Script.cs @@ -14,56 +14,16 @@ namespace Umbraco.Core.Models [DataContract(IsReference = true)] public class Script : File { - private readonly IContentSection _contentConfig; - public Script(string path) - : this(path, UmbracoConfig.For.UmbracoSettings().Content) + : base(path) { } + [Obsolete("This is no longer used and will be removed from the codebase in future versions")] public Script(string path, IContentSection contentConfig) - : base(path) - { - _contentConfig = contentConfig; - base.Path = path; - } - - /// - /// Boolean indicating whether the file could be validated - /// - /// - /// The validation logic was previsouly placed in the codebehind of editScript.aspx, - /// but has been moved to the script file so the validation is central. - /// - /// True if file is valid, otherwise false - //TODO: This makes no sense to be here, any validation methods should be at the service level, - // when we move Scripts to truly use IFileSystem, then this validation logic doesn't work anymore - public override bool IsValid() - { - //NOTE Since a script file can be both JS, Razor Views, Razor Macros and Xslt - //it might be an idea to create validations for all 3 and divide the validation - //into 4 private methods. - //See codeEditorSave.asmx.cs for reference. - - var exts = _contentConfig.ScriptFileTypes.ToList(); - /*if (UmbracoSettings.DefaultRenderingEngine == RenderingEngine.Mvc) - { - exts.Add("cshtml"); - exts.Add("vbhtml"); - }*/ - - var dirs = SystemDirectories.Scripts; - /*if (UmbracoSettings.DefaultRenderingEngine == RenderingEngine.Mvc) - dirs += "," + SystemDirectories.MvcViews;*/ - - //Validate file - var validFile = IOHelper.VerifyEditPath(Path, dirs.Split(',')); - - //Validate extension - var validExtension = IOHelper.VerifyFileExtension(Path, exts); - - return validFile && validExtension; + : this(path) + { } /// diff --git a/src/Umbraco.Core/Models/Stylesheet.cs b/src/Umbraco.Core/Models/Stylesheet.cs index 01acff85dd..7381da0930 100644 --- a/src/Umbraco.Core/Models/Stylesheet.cs +++ b/src/Umbraco.Core/Models/Stylesheet.cs @@ -1,10 +1,11 @@ using System; using System.Collections.Generic; +using System.Data; using System.Linq; using System.Runtime.Serialization; using System.Text; using Umbraco.Core.IO; -using Umbraco.Core.Models.Css; +using Umbraco.Core.Strings.Css; namespace Umbraco.Core.Models { @@ -15,140 +16,147 @@ namespace Umbraco.Core.Models [DataContract(IsReference = true)] public class Stylesheet : File { - public Stylesheet(string path) : base(path) + public Stylesheet(string path) + : base(path) + { + InitializeProperties(); + } + + private Lazy> _properties; + + private void InitializeProperties() { - base.Path = path; + //if the value is already created, we need to be created and update the collection according to + //what is now in the content + if (_properties != null && _properties.IsValueCreated) + { + //re-parse it so we can check what properties are different and adjust the event handlers + var parsed = StylesheetHelper.ParseRules(Content).ToArray(); + var names = parsed.Select(x => x.Name).ToArray(); + var existing = _properties.Value.Where(x => names.Contains(x.Name)).ToArray(); + //update existing + foreach (var stylesheetProperty in existing) + { + var updateFrom = parsed.Single(x => x.Name == stylesheetProperty.Name); + //remove current event handler while we update, we'll reset it after + stylesheetProperty.PropertyChanged -= Property_PropertyChanged; + stylesheetProperty.Alias = updateFrom.Selector; + stylesheetProperty.Value = updateFrom.Styles; + //re-add + stylesheetProperty.PropertyChanged += Property_PropertyChanged; + } + //remove no longer existing + var nonExisting = _properties.Value.Where(x => names.Contains(x.Name) == false).ToArray(); + foreach (var stylesheetProperty in nonExisting) + { + stylesheetProperty.PropertyChanged -= Property_PropertyChanged; + _properties.Value.Remove(stylesheetProperty); + } + //add new ones + var newItems = parsed.Where(x => _properties.Value.Select(p => p.Name).Contains(x.Name) == false); + foreach (var stylesheetRule in newItems) + { + var prop = new StylesheetProperty(stylesheetRule.Name, stylesheetRule.Selector, stylesheetRule.Styles); + prop.PropertyChanged += Property_PropertyChanged; + _properties.Value.Add(prop); + } + } + + //we haven't read the properties yet so create the lazy delegate + _properties = new Lazy>(() => + { + var parsed = StylesheetHelper.ParseRules(Content); + return parsed.Select(statement => + { + var property = new StylesheetProperty(statement.Name, statement.Selector, statement.Styles); + property.PropertyChanged += Property_PropertyChanged; + return property; + + }).ToList(); + }); } /// - /// Returns a flat list of objects + /// If the property has changed then we need to update the content + /// + /// + /// + void Property_PropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e) + { + var prop = (StylesheetProperty) sender; + + //Ensure we are setting base.Content here so that the properties don't get reset and thus any event handlers would get reset too + base.Content = StylesheetHelper.ReplaceRule(Content, prop.Name, new StylesheetRule + { + Name = prop.Name, + Selector = prop.Alias, + Styles = prop.Value + }); + } + + /// + /// Gets or sets the Content of a File + /// + public override string Content + { + get { return base.Content; } + set + { + base.Content = value; + //re-set the properties so they are re-read from the content + InitializeProperties(); + } + } + + /// + /// Returns a list of umbraco back office enabled stylesheet properties /// /// - /// Please note that the list is flattend by formatting single css selectors with - /// its value(s). Blocks in css @ rules are also flatten, but noted as part of an @ rule - /// by setting the property IsPartOfAtRule=true. - /// This is done to make the stylesheet usable in the backoffice. + /// An umbraco back office enabled stylesheet property has a special prefix, for example: + /// + /// /** umb_name: MyPropertyName */ p { font-size: 1em; } /// [IgnoreDataMember] public IEnumerable Properties { - get - { - var properties = new List(); - var parser = new CssParser(Content); - - foreach (var statement in parser.StyleSheet.Statements.OfType()) - { - var cssBlock = statement.Block; - if(cssBlock == null) continue; - - var cssValues = cssBlock.Values; - if(cssValues == null) continue; - - properties.AddRange(FormatCss(cssBlock.Values, true)); - } - - var statements = parser.StyleSheet.Statements.Where(s => s is CssRuleSet); - properties.AddRange(FormatCss(statements, false)); - - return properties; - } + get { return _properties.Value; } } /// - /// Formats a list of statements to a simple object + /// Adds an Umbraco stylesheet property for use in the back office /// - /// Enumerable list of statements - /// Boolean indicating whether the current list of statements is part of an @ rule - /// An Enumerable list of objects - private IEnumerable FormatCss(IEnumerable statements, bool isPartOfAtRule) + /// + public void AddProperty(StylesheetProperty property) { - var properties = new List(); - - foreach (var statement in statements.OfType()) + if (Properties.Any(x => x.Name == property.Name)) { - foreach (var selector in statement.Selectors) - { - var declarations = new StringBuilder(); - foreach (var declaration in statement.Declarations) - { - declarations.AppendFormat("{0}:{1};", declaration.Property, FormatCss(declaration.Value)); - declarations.AppendLine(""); - } - properties.Add(new StylesheetProperty(selector.Value.TrimStart('.', '#'), declarations.ToString()) { IsPartOfAtRule = isPartOfAtRule }); - } + throw new DuplicateNameException("The property with the name " + property.Name + " already exists in the collection"); } - return properties; + //now we need to serialize out the new property collection over-top of the string Content. + Content = StylesheetHelper.AppendRule(Content, new StylesheetRule + { + Name = property.Name, + Selector = property.Alias, + Styles = property.Value + }); + + //re-set lazy collection + InitializeProperties(); } /// - /// Formats a to a single string + /// Removes an Umbraco stylesheet property /// - /// to format - /// Value list formatted as a string - private string FormatCss(CssValueList valueList) + /// + public void RemoveProperty(string name) { - bool space = false; - var values = new StringBuilder(); - - foreach (CssString value in valueList.Values) + if (Properties.Any(x => x.Name == name)) { - if (space) - { - values.Append(" "); - } - else - { - space = true; - } - - values.Append(value); + Content = StylesheetHelper.ReplaceRule(Content, name, null); } - - return values.ToString(); } - - /// - /// Boolean indicating whether the file could be validated - /// - /// True if file is valid, otherwise false - //TODO: This makes no sense to be here, any validation methods should be at the service level, - // when we move Scripts to truly use IFileSystem, then this validation logic doesn't work anymore - public override bool IsValid() - { - var dirs = SystemDirectories.Css; - - //Validate file - var validFile = IOHelper.VerifyEditPath(Path, dirs.Split(',')); - - //Validate extension - var validExtension = IOHelper.VerifyFileExtension(Path, new List {"css"}); - - return validFile && validExtension; - } - - /// - /// Boolean indicating whether the file is valid css using a css parser - /// - /// True if css is valid, otherwise false - public bool IsFileValidCss() - { - var parser = new CssParser(Content); - - try - { - var styleSheet = parser.StyleSheet;//Get stylesheet to invoke parsing - } - catch (Exception ex) - { - //Log exception? - return false; - } - - return !parser.Errors.Any(); - } - + /// /// Indicates whether the current entity has an identity, which in this case is a path/name. /// diff --git a/src/Umbraco.Core/Models/StylesheetProperty.cs b/src/Umbraco.Core/Models/StylesheetProperty.cs index 6053f75bd6..fead6f033a 100644 --- a/src/Umbraco.Core/Models/StylesheetProperty.cs +++ b/src/Umbraco.Core/Models/StylesheetProperty.cs @@ -1,4 +1,5 @@ using System; +using System.Reflection; using System.Runtime.Serialization; using Umbraco.Core.Models.EntityBase; @@ -12,16 +13,57 @@ namespace Umbraco.Core.Models /// [Serializable] [DataContract(IsReference = true)] - public class StylesheetProperty : IValueObject + public class StylesheetProperty : TracksChangesEntityBase, IValueObject { - public StylesheetProperty(string @alias, string value) + private string _alias; + private string _value; + + public StylesheetProperty(string name, string @alias, string value) { - Alias = alias; - Value = value; + Name = name; + _alias = alias; + _value = value; + } + + private static readonly PropertyInfo AliasSelector = ExpressionHelper.GetPropertyInfo(x => x.Alias); + private static readonly PropertyInfo ValueSelector = ExpressionHelper.GetPropertyInfo(x => x.Value); + + /// + /// The CSS rule name that can be used by Umbraco in the back office + /// + public string Name { get; private set; } + + /// + /// This is the CSS Selector + /// + public string Alias + { + get { return _alias; } + set + { + SetPropertyValueAndDetectChanges(o => + { + _alias = value; + return _alias; + }, _alias, AliasSelector); + } + } + + /// + /// The CSS value for the selector + /// + public string Value + { + get { return _value; } + set + { + SetPropertyValueAndDetectChanges(o => + { + _value = value; + return _value; + }, _value, ValueSelector); + } } - public string Alias { get; set; } - public string Value { get; set; } - public bool IsPartOfAtRule { get; set; } } } \ No newline at end of file diff --git a/src/Umbraco.Core/Models/Template.cs b/src/Umbraco.Core/Models/Template.cs index fc10c818ef..05b756af32 100644 --- a/src/Umbraco.Core/Models/Template.cs +++ b/src/Umbraco.Core/Models/Template.cs @@ -3,8 +3,10 @@ using System.Collections.Generic; using System.Reflection; using System.Runtime.Serialization; using Umbraco.Core.Configuration; +using Umbraco.Core.Configuration.UmbracoSettings; using Umbraco.Core.IO; using Umbraco.Core.Models.EntityBase; +using Umbraco.Core.Services; using Umbraco.Core.Strings; namespace Umbraco.Core.Models @@ -18,88 +20,43 @@ namespace Umbraco.Core.Models { private string _alias; private string _name; - private int _creatorId; - private int _level; - private int _sortOrder; - private int _parentId; private string _masterTemplateAlias; + private Lazy _masterTemplateId; - private static readonly PropertyInfo CreatorIdSelector = ExpressionHelper.GetPropertyInfo(x => x.CreatorId); - private static readonly PropertyInfo LevelSelector = ExpressionHelper.GetPropertyInfo(x => x.Level); - private static readonly PropertyInfo SortOrderSelector = ExpressionHelper.GetPropertyInfo(x => x.SortOrder); - private static readonly PropertyInfo ParentIdSelector = ExpressionHelper.GetPropertyInfo(x => x.ParentId); private static readonly PropertyInfo MasterTemplateAliasSelector = ExpressionHelper.GetPropertyInfo(x => x.MasterTemplateAlias); - - public Template(string path, string name, string alias) - : base(path) + private static readonly PropertyInfo MasterTemplateIdSelector = ExpressionHelper.GetPropertyInfo>(x => x.MasterTemplateId); + private static readonly PropertyInfo AliasSelector = ExpressionHelper.GetPropertyInfo(x => x.Alias); + private static readonly PropertyInfo NameSelector = ExpressionHelper.GetPropertyInfo(x => x.Name); + + public Template(string name, string alias) + : base(string.Empty) { - base.Path = path; - ParentId = -1; - _name = name; //.Replace("/", ".").Replace("\\", ""); // why? that's just the name! + _name = name; _alias = alias.ToCleanString(CleanStringType.UnderscoreAlias); + _masterTemplateId = new Lazy(() => -1); + } + + [Obsolete("This constructor should not be used, file path is determined by alias, setting the path here will have no affect")] + public Template(string path, string name, string alias) + : this(name, alias) + { } [DataMember] - internal int CreatorId + public Lazy MasterTemplateId { - get { return _creatorId; } + get { return _masterTemplateId; } set { SetPropertyValueAndDetectChanges(o => { - _creatorId = value; - return _creatorId; - }, _creatorId, CreatorIdSelector); + _masterTemplateId = value; + return _masterTemplateId; + }, _masterTemplateId, MasterTemplateIdSelector); } } - [DataMember] - internal int Level - { - get { return _level; } - set - { - SetPropertyValueAndDetectChanges(o => - { - _level = value; - return _level; - }, _level, LevelSelector); - } - } - - [DataMember] - internal int SortOrder - { - get { return _sortOrder; } - set - { - SetPropertyValueAndDetectChanges(o => - { - _sortOrder = value; - return _sortOrder; - }, _sortOrder, SortOrderSelector); - } - } - - [DataMember] - internal int ParentId - { - get { return _parentId; } - set - { - SetPropertyValueAndDetectChanges(o => - { - _parentId = value; - return _parentId; - }, _parentId, ParentIdSelector); - } - } - - [DataMember] - internal Lazy MasterTemplateId { get; set; } - - [DataMember] - internal string MasterTemplateAlias + public string MasterTemplateAlias { get { return _masterTemplateAlias; } set @@ -108,68 +65,50 @@ namespace Umbraco.Core.Models { _masterTemplateAlias = value; return _masterTemplateAlias; - }, _masterTemplateAlias, MasterTemplateAliasSelector); + }, _masterTemplateAlias, MasterTemplateAliasSelector); } } [DataMember] - public override string Alias + public new string Name { - get + get { return _name; } + set { - return _alias; + SetPropertyValueAndDetectChanges(o => + { + _name = value; + return _name; + }, _name, NameSelector); + } } [DataMember] - public override string Name + public new string Alias { - get + get { return _alias; } + set { - return _name; + SetPropertyValueAndDetectChanges(o => + { + _alias = value.ToCleanString(CleanStringType.UnderscoreAlias); + return _alias; + }, _alias, AliasSelector); + } } /// - /// Returns the that corresponds to the template file + /// Returns true if the template is used as a layout for other templates (i.e. it has 'children') /// - /// + public bool IsMasterTemplate { get; internal set; } + + [Obsolete("This is no longer used and will be removed from the codebase in future versions, use the IFileSystem DetermineRenderingEngine method instead")] public RenderingEngine GetTypeOfRenderingEngine() { - if(Path.EndsWith("cshtml") || Path.EndsWith("vbhtml")) - return RenderingEngine.Mvc; - - return RenderingEngine.WebForms; - } - - /// - /// Boolean indicating whether the file could be validated - /// - /// True if file is valid, otherwise false - public override bool IsValid() - { - var exts = new List(); - if (UmbracoConfig.For.UmbracoSettings().Templates.DefaultRenderingEngine == RenderingEngine.Mvc) - { - exts.Add("cshtml"); - exts.Add("vbhtml"); - } - else - { - exts.Add(UmbracoConfig.For.UmbracoSettings().Templates.UseAspNetMasterPages ? "master" : "aspx"); - } - - var dirs = SystemDirectories.Masterpages; - if (UmbracoConfig.For.UmbracoSettings().Templates.DefaultRenderingEngine == RenderingEngine.Mvc) - dirs += "," + SystemDirectories.MvcViews; - - //Validate file - var validFile = IOHelper.VerifyEditPath(Path, dirs.Split(',')); - - //Validate extension - var validExtension = IOHelper.VerifyFileExtension(Path, exts); - - return validFile && validExtension; + //Hack! TODO: Remove this method entirely + return ApplicationContext.Current.Services.FileService.DetermineTemplateRenderingEngine(this); } /// @@ -187,20 +126,33 @@ namespace Umbraco.Core.Models public void SetMasterTemplate(ITemplate masterTemplate) { - MasterTemplateId = new Lazy(() => masterTemplate.Id); + if (masterTemplate == null) + { + MasterTemplateId = new Lazy(() => -1); + MasterTemplateAlias = null; + } + else + { + MasterTemplateId = new Lazy(() => masterTemplate.Id); + MasterTemplateAlias = masterTemplate.Alias; + } + } public override object DeepClone() { - var clone = (Template)base.DeepClone(); + //We cannot call in to the base classes to clone because the base File class treats Alias, Name.. differently so we need to manually do the clone - //need to manually assign since they are readonly properties - clone._alias = Alias; - clone._name = Name; + //Memberwise clone on Entity will work since it doesn't have any deep elements + // for any sub class this will work for standard properties as well that aren't complex object's themselves. + var clone = (Template)MemberwiseClone(); + //Automatically deep clone ref properties that are IDeepCloneable + DeepCloneHelper.DeepCloneRefProperties(this, clone); clone.ResetDirtyProperties(false); - return clone; } + + } } diff --git a/src/Umbraco.Core/NameValueCollectionExtensions.cs b/src/Umbraco.Core/NameValueCollectionExtensions.cs index d47add61ed..7b55d8131a 100644 --- a/src/Umbraco.Core/NameValueCollectionExtensions.cs +++ b/src/Umbraco.Core/NameValueCollectionExtensions.cs @@ -8,6 +8,13 @@ namespace Umbraco.Core { internal static class NameValueCollectionExtensions { + public static IEnumerable> AsEnumerable(this NameValueCollection nvc) + { + foreach (string key in nvc.AllKeys) + { + yield return new KeyValuePair(key, nvc[key]); + } + } public static bool ContainsKey(this NameValueCollection collection, string key) { diff --git a/src/Umbraco.Core/ObjectResolution/ApplicationEventsResolver.cs b/src/Umbraco.Core/ObjectResolution/ApplicationEventsResolver.cs index a31598bfc8..1b55a89a9c 100644 --- a/src/Umbraco.Core/ObjectResolution/ApplicationEventsResolver.cs +++ b/src/Umbraco.Core/ObjectResolution/ApplicationEventsResolver.cs @@ -2,6 +2,7 @@ using System; using System.Collections.Generic; using System.Linq; using System.Threading; +using Umbraco.Core.Logging; using umbraco.interfaces; namespace Umbraco.Core.ObjectResolution @@ -18,11 +19,13 @@ namespace Umbraco.Core.ObjectResolution private readonly LegacyStartupHandlerResolver _legacyResolver; /// - /// Constructor - /// - /// - internal ApplicationEventsResolver(IEnumerable applicationEventHandlers) - : base(applicationEventHandlers) + /// Constructor + /// + /// + /// + /// + internal ApplicationEventsResolver(IServiceProvider serviceProvider, ILogger logger, IEnumerable applicationEventHandlers) + : base(serviceProvider, logger, applicationEventHandlers) { //create the legacy resolver and only include the legacy types _legacyResolver = new LegacyStartupHandlerResolver( diff --git a/src/Umbraco.Core/ObjectResolution/LazyManyObjectsResolverbase.cs b/src/Umbraco.Core/ObjectResolution/LazyManyObjectsResolverbase.cs index 6aa3cce51c..2851a70e15 100644 --- a/src/Umbraco.Core/ObjectResolution/LazyManyObjectsResolverbase.cs +++ b/src/Umbraco.Core/ObjectResolution/LazyManyObjectsResolverbase.cs @@ -1,8 +1,9 @@ using System; using System.Collections.Generic; +using System.ComponentModel; using System.Linq; -using System.Threading; using System.Web; +using Umbraco.Core.Logging; namespace Umbraco.Core.ObjectResolution { @@ -15,98 +16,133 @@ namespace Umbraco.Core.ObjectResolution /// This is a special case resolver for when types get lazily resolved in order to resolve the actual types. This is useful /// for when there is some processing overhead (i.e. Type finding in assemblies) to return the Types used to instantiate the instances. /// In some these cases we don't want to have to type-find during application startup, only when we need to resolve the instances. - /// Important notes about this resolver: it does not support Insert or Remove and therefore does not support any ordering unless + /// Important notes about this resolver: it does not support Insert or Remove and therefore does not support any ordering unless /// the types are marked with the WeightedPluginAttribute. - /// + /// public abstract class LazyManyObjectsResolverBase : ManyObjectsResolverBase - where TResolved : class + where TResolved : class where TResolver : ResolverBase - { - #region Constructors + { + #region Constructors /// - /// Initializes a new instance of the class with an empty list of objects, - /// with creation of objects based on an HttpRequest lifetime scope. + /// Initializes a new instance of the class with an empty list of objects, + /// and an optional lifetime scope. /// + /// + /// /// The lifetime scope of instantiated objects, default is per Application. /// If is per HttpRequest then there must be a current HttpContext. /// is per HttpRequest but the current HttpContext is null. + protected LazyManyObjectsResolverBase(IServiceProvider serviceProvider, ILogger logger, ObjectLifetimeScope scope = ObjectLifetimeScope.Application) + : base(serviceProvider, logger, scope) + { + Initialize(); + } + + [EditorBrowsable(EditorBrowsableState.Never)] + [Obsolete("Use ctor specifying IServiceProvider instead")] protected LazyManyObjectsResolverBase(ObjectLifetimeScope scope = ObjectLifetimeScope.Application) : base(scope) { Initialize(); } - /// - /// Initializes a new instance of the class with an empty list of objects, - /// with creation of objects based on an HttpRequest lifetime scope. - /// - /// The HttpContextBase corresponding to the HttpRequest. - /// is null. + [EditorBrowsable(EditorBrowsableState.Never)] + [Obsolete("Use ctor specifying IServiceProvider instead")] protected LazyManyObjectsResolverBase(HttpContextBase httpContext) : base(httpContext) { Initialize(); } - /// - /// Initializes a new instance of the class with an initial list - /// If is per HttpRequest then there must be a current HttpContext. - /// is per HttpRequest but the current HttpContext is null. - /// + protected LazyManyObjectsResolverBase(IServiceProvider serviceProvider, ILogger logger, IEnumerable> lazyTypeList, ObjectLifetimeScope scope = ObjectLifetimeScope.Application) + : this(serviceProvider, logger, scope) + { + AddTypes(lazyTypeList); + } + + [EditorBrowsable(EditorBrowsableState.Never)] + [Obsolete("Use ctor specifying IServiceProvider instead")] protected LazyManyObjectsResolverBase(IEnumerable> lazyTypeList, ObjectLifetimeScope scope = ObjectLifetimeScope.Application) - : this(scope) - { - AddTypes(lazyTypeList); - } + : this(new ActivatorServiceProvider(), LoggerResolver.Current.Logger, lazyTypeList, scope) + { + } + + protected LazyManyObjectsResolverBase(IServiceProvider serviceProvider, ILogger logger, Func> typeListProducerList, ObjectLifetimeScope scope = ObjectLifetimeScope.Application) + : this(serviceProvider, logger, scope) + { + _typeListProducerList.Add(typeListProducerList); + } + + [EditorBrowsable(EditorBrowsableState.Never)] + [Obsolete("Use ctor specifying IServiceProvider instead")] + protected LazyManyObjectsResolverBase(Func> typeListProducerList, ObjectLifetimeScope scope = ObjectLifetimeScope.Application) + : this(new ActivatorServiceProvider(), LoggerResolver.Current.Logger, typeListProducerList, scope) + { + } + + protected LazyManyObjectsResolverBase(IServiceProvider serviceProvider, ILogger logger, HttpContextBase httpContext, IEnumerable> lazyTypeList) + : this(serviceProvider, logger, httpContext) + { + AddTypes(lazyTypeList); + } + + [EditorBrowsable(EditorBrowsableState.Never)] + [Obsolete("Use ctor specifying IServiceProvider instead")] + protected LazyManyObjectsResolverBase(HttpContextBase httpContext, IEnumerable> lazyTypeList) + : this(new ActivatorServiceProvider(), LoggerResolver.Current.Logger, httpContext, lazyTypeList) + { + } + + protected LazyManyObjectsResolverBase(IServiceProvider serviceProvider, ILogger logger, HttpContextBase httpContext, Func> typeListProducerList) + : this(serviceProvider, logger, httpContext) + { + _typeListProducerList.Add(typeListProducerList); + } + + [EditorBrowsable(EditorBrowsableState.Never)] + [Obsolete("Use ctor specifying IServiceProvider instead")] + protected LazyManyObjectsResolverBase(HttpContextBase httpContext, Func> typeListProducerList) + : this(new ActivatorServiceProvider(), LoggerResolver.Current.Logger, httpContext, typeListProducerList) + { + } + + #endregion + + private readonly List> _lazyTypeList = new List>(); + private readonly List>> _typeListProducerList = new List>>(); + private readonly List _excludedTypesList = new List(); + private Lazy> _resolvedTypes; /// - /// Initializes a new instance of the class with an initial list - /// of functions producing types, and an optional lifetime scope. + /// Initializes a new instance of the class with an empty list of objects, + /// with creation of objects based on an HttpRequest lifetime scope. /// - /// The list of functions producing types. + /// + /// + /// The HttpContextBase corresponding to the HttpRequest. + /// is null. + protected LazyManyObjectsResolverBase(IServiceProvider serviceProvider, ILogger logger, HttpContextBase httpContext) + : base(serviceProvider, logger, httpContext) + { + } + + /// + /// Initializes a new instance of the class with an initial list of object types, + /// and an optional lifetime scope. + /// + /// + /// + /// The list of object types. /// The lifetime scope of instantiated objects, default is per Application. /// If is per HttpRequest then there must be a current HttpContext. /// is per HttpRequest but the current HttpContext is null. - protected LazyManyObjectsResolverBase(Func> typeListProducerList, ObjectLifetimeScope scope = ObjectLifetimeScope.Application) - : this(scope) - { - _typeListProducerList.Add(typeListProducerList); - } + protected LazyManyObjectsResolverBase(IServiceProvider serviceProvider, ILogger logger, IEnumerable value, ObjectLifetimeScope scope = ObjectLifetimeScope.Application) + : base(serviceProvider, logger, value, scope) + { + } - /// - /// Initializes a new instance of the class with an initial list of - /// lazy object types, with creation of objects based on an HttpRequest lifetime scope. - /// - /// The HttpContextBase corresponding to the HttpRequest. - /// The list of lazy object types. - /// is null. - protected LazyManyObjectsResolverBase(HttpContextBase httpContext, IEnumerable> lazyTypeList) - : this(httpContext) - { - AddTypes(lazyTypeList); - } - - /// - /// Initializes a new instance of the class with an initial list of - /// functions producing types, with creation of objects based on an HttpRequest lifetime scope. - /// - /// The HttpContextBase corresponding to the HttpRequest. - /// The list of functions producing types. - /// is null. - protected LazyManyObjectsResolverBase(HttpContextBase httpContext, Func> typeListProducerList) - : this(httpContext) - { - _typeListProducerList.Add(typeListProducerList); - } - - #endregion - - private readonly List> _lazyTypeList = new List>(); - private readonly List>> _typeListProducerList = new List>>(); - private readonly List _excludedTypesList = new List(); - private Lazy> _resolvedTypes = null; - private void Initialize() { _resolvedTypes = new Lazy>(() => @@ -129,23 +165,23 @@ namespace Umbraco.Core.ObjectResolution }); } - /// - /// Gets a value indicating whether the resolver has resolved types to create instances from. - /// + /// + /// Gets a value indicating whether the resolver has resolved types to create instances from. + /// /// To be used in unit tests. - public bool HasResolvedTypes - { - get { return _resolvedTypes.IsValueCreated; } - } + public bool HasResolvedTypes + { + get { return _resolvedTypes.IsValueCreated; } + } /// /// Gets the list of types to create instances from. /// /// When called, will get the types from the lazy list. protected override IEnumerable InstanceTypes - { - get { return _resolvedTypes.Value; } - } + { + get { return _resolvedTypes.Value; } + } /// /// Ensures that type is valid and not a duplicate @@ -154,15 +190,15 @@ namespace Umbraco.Core.ObjectResolution /// /// private void AddValidAndNoDuplicate(List list, Type type) - { + { EnsureCorrectType(type); if (list.Contains(type)) - { + { throw new InvalidOperationException(string.Format( "Type {0} is already in the collection of types.", type.FullName)); } list.Add(type); - } + } #region Types collection manipulation @@ -179,86 +215,86 @@ namespace Umbraco.Core.ObjectResolution /// /// Lazily adds types from lazy types. - /// + /// /// The lazy types, to add. - protected void AddTypes(IEnumerable> types) - { - EnsureSupportsAdd(); + protected void AddTypes(IEnumerable> types) + { + EnsureSupportsAdd(); using (Resolution.Configuration) using (GetWriteLock()) - { - foreach (var t in types) - { - _lazyTypeList.Add(t); - } - } - } + { + foreach (var t in types) + { + _lazyTypeList.Add(t); + } + } + } - /// + /// /// Lazily adds types from a function producing types. - /// + /// /// The functions producing types, to add. public void AddTypeListDelegate(Func> typeListProducer) - { + { EnsureSupportsAdd(); using (Resolution.Configuration) using (GetWriteLock()) - { + { _typeListProducerList.Add(typeListProducer); - } - } + } + } - /// + /// /// Lazily adds a type from a lazy type. - /// + /// /// The lazy type, to add. - public void AddType(Lazy value) - { + public void AddType(Lazy value) + { EnsureSupportsAdd(); using (Resolution.Configuration) using (GetWriteLock()) - { - _lazyTypeList.Add(value); - } - } + { + _lazyTypeList.Add(value); + } + } - /// + /// /// Lazily adds a type from an actual type. - /// + /// /// The actual type, to add. /// The type is converted to a lazy type. - public override void AddType(Type value) - { - AddType(new Lazy(() => value)); - } + public override void AddType(Type value) + { + AddType(new Lazy(() => value)); + } - /// - /// Clears all lazy types - /// - public override void Clear() - { - EnsureSupportsClear(); + /// + /// Clears all lazy types + /// + public override void Clear() + { + EnsureSupportsClear(); using (Resolution.Configuration) using (GetWriteLock()) - { - _lazyTypeList.Clear(); - } - } + { + _lazyTypeList.Clear(); + } + } #endregion #region Types collection manipulation support - /// + /// /// Gets a false value indicating that the resolver does NOT support inserting types. - /// - protected override bool SupportsInsert - { - get { return false; } + /// + protected override bool SupportsInsert + { + get { return false; } } #endregion diff --git a/src/Umbraco.Core/ObjectResolution/LegacyTransientObjectsResolver.cs b/src/Umbraco.Core/ObjectResolution/LegacyTransientObjectsResolver.cs index 9362ed54fe..62ce20cbbb 100644 --- a/src/Umbraco.Core/ObjectResolution/LegacyTransientObjectsResolver.cs +++ b/src/Umbraco.Core/ObjectResolution/LegacyTransientObjectsResolver.cs @@ -1,8 +1,8 @@ using System; using System.Collections.Concurrent; using System.Collections.Generic; -using System.Linq; using System.Threading; +using Umbraco.Core.Logging; namespace Umbraco.Core.ObjectResolution { @@ -22,21 +22,23 @@ namespace Umbraco.Core.ObjectResolution where TResolver : ResolverBase { private readonly ReaderWriterLockSlim _lock = new ReaderWriterLockSlim(); - private ConcurrentDictionary _id2type; + private ConcurrentDictionary _id2Type; #region Constructors - - /// - /// Initializes a new instance of the class with an initial list of object types. - /// - /// A function returning the list of object types. - /// - /// We are creating Transient instances (new instances each time) because this is how the legacy code worked and - /// I don't want to muck anything up by changing them to application based instances. - /// TODO: However, it would make much more sense to do this and would speed up the application plus this would make the GetById method much easier. - /// - protected LegacyTransientObjectsResolver(Func> value) - : base(value, ObjectLifetimeScope.Transient) // new objects every time + + /// + /// Initializes a new instance of the class with an initial list of object types. + /// + /// + /// + /// A function returning the list of object types. + /// + /// We are creating Transient instances (new instances each time) because this is how the legacy code worked and + /// I don't want to muck anything up by changing them to application based instances. + /// TODO: However, it would make much more sense to do this and would speed up the application plus this would make the GetById method much easier. + /// + protected LegacyTransientObjectsResolver(IServiceProvider serviceProvider, ILogger logger, Func> value) + : base(serviceProvider, logger, value, ObjectLifetimeScope.Transient) // new objects every time { } #endregion @@ -55,9 +57,9 @@ namespace Umbraco.Core.ObjectResolution public TResolved GetById(Guid id) { EnsureIsInitialized(); - return !_id2type.ContainsKey(id) + return _id2Type.ContainsKey(id) == false ? null - : PluginManager.Current.CreateInstance(_id2type[id]); + : ServiceProvider.GetService(_id2Type[id]) as TResolved; } /// @@ -72,14 +74,14 @@ namespace Umbraco.Core.ObjectResolution { using (var l = new UpgradeableReadLock(_lock)) { - if (_id2type == null) + if (_id2Type == null) { l.UpgradeToWriteLock(); - _id2type = new ConcurrentDictionary(); + _id2Type = new ConcurrentDictionary(); foreach (var value in Values) { - _id2type.TryAdd(GetUniqueIdentifier(value), value.GetType()); + _id2Type.TryAdd(GetUniqueIdentifier(value), value.GetType()); } } } diff --git a/src/Umbraco.Core/ObjectResolution/ManyObjectsResolverBase.cs b/src/Umbraco.Core/ObjectResolution/ManyObjectsResolverBase.cs index 95ff923c58..1cfa81228a 100644 --- a/src/Umbraco.Core/ObjectResolution/ManyObjectsResolverBase.cs +++ b/src/Umbraco.Core/ObjectResolution/ManyObjectsResolverBase.cs @@ -1,8 +1,10 @@ using System; using System.Collections.Generic; +using System.ComponentModel; using System.Linq; using System.Threading; using System.Web; +using Umbraco.Core.Logging; namespace Umbraco.Core.ObjectResolution { @@ -15,75 +17,111 @@ namespace Umbraco.Core.ObjectResolution where TResolved : class where TResolver : ResolverBase { - private Lazy> _applicationInstances = null; + private Lazy> _applicationInstances; private readonly ReaderWriterLockSlim _lock = new ReaderWriterLockSlim(); private readonly string _httpContextKey; private readonly List _instanceTypes = new List(); - private IEnumerable _sortedValues = null; + private IEnumerable _sortedValues; private int _defaultPluginWeight = 10; #region Constructors - - /// - /// Initializes a new instance of the class with an empty list of objects, + + /// + /// Initializes a new instance of the class with an empty list of objects, /// and an optional lifetime scope. - /// - /// The lifetime scope of instantiated objects, default is per Application. - /// If is per HttpRequest then there must be a current HttpContext. - /// is per HttpRequest but the current HttpContext is null. + /// + /// + /// + /// The lifetime scope of instantiated objects, default is per Application. + /// If is per HttpRequest then there must be a current HttpContext. + /// is per HttpRequest but the current HttpContext is null. + protected ManyObjectsResolverBase(IServiceProvider serviceProvider, ILogger logger, ObjectLifetimeScope scope = ObjectLifetimeScope.Application) + { + if (serviceProvider == null) throw new ArgumentNullException("serviceProvider"); + if (logger == null) throw new ArgumentNullException("logger"); + CanResolveBeforeFrozen = false; + if (scope == ObjectLifetimeScope.HttpRequest) + { + if (HttpContext.Current == null) + throw new InvalidOperationException("Use alternative constructor accepting a HttpContextBase object in order to set the lifetime scope to HttpRequest when HttpContext.Current is null"); + + CurrentHttpContext = new HttpContextWrapper(HttpContext.Current); + } + + ServiceProvider = serviceProvider; + Logger = logger; + LifetimeScope = scope; + if (scope == ObjectLifetimeScope.HttpRequest) + _httpContextKey = GetType().FullName; + _instanceTypes = new List(); + + InitializeAppInstances(); + } + + [EditorBrowsable(EditorBrowsableState.Never)] + [Obsolete("Use ctor specifying IServiceProvider instead")] protected ManyObjectsResolverBase(ObjectLifetimeScope scope = ObjectLifetimeScope.Application) + : this(new ActivatorServiceProvider(), LoggerResolver.Current.Logger, scope) { - CanResolveBeforeFrozen = false; - if (scope == ObjectLifetimeScope.HttpRequest) - { - if (HttpContext.Current == null) - throw new InvalidOperationException("Use alternative constructor accepting a HttpContextBase object in order to set the lifetime scope to HttpRequest when HttpContext.Current is null"); - - CurrentHttpContext = new HttpContextWrapper(HttpContext.Current); - } - - LifetimeScope = scope; - if (scope == ObjectLifetimeScope.HttpRequest) - _httpContextKey = this.GetType().FullName; - _instanceTypes = new List(); - - InitializeAppInstances(); + } - /// - /// Initializes a new instance of the class with an empty list of objects, - /// with creation of objects based on an HttpRequest lifetime scope. - /// - /// The HttpContextBase corresponding to the HttpRequest. - /// is null. - protected ManyObjectsResolverBase(HttpContextBase httpContext) + /// + /// Initializes a new instance of the class with an empty list of objects, + /// with creation of objects based on an HttpRequest lifetime scope. + /// + /// + /// + /// The HttpContextBase corresponding to the HttpRequest. + /// is null. + protected ManyObjectsResolverBase(IServiceProvider serviceProvider, ILogger logger, HttpContextBase httpContext) { - CanResolveBeforeFrozen = false; - if (httpContext == null) - throw new ArgumentNullException("httpContext"); + if (serviceProvider == null) throw new ArgumentNullException("serviceProvider"); + if (httpContext == null) throw new ArgumentNullException("httpContext"); + CanResolveBeforeFrozen = false; + Logger = logger; LifetimeScope = ObjectLifetimeScope.HttpRequest; - _httpContextKey = this.GetType().FullName; - CurrentHttpContext = httpContext; + _httpContextKey = GetType().FullName; + ServiceProvider = serviceProvider; + CurrentHttpContext = httpContext; _instanceTypes = new List(); InitializeAppInstances(); } - /// - /// Initializes a new instance of the class with an initial list of object types, + [EditorBrowsable(EditorBrowsableState.Never)] + [Obsolete("Use ctor specifying IServiceProvider instead")] + protected ManyObjectsResolverBase(HttpContextBase httpContext) + : this(new ActivatorServiceProvider(), LoggerResolver.Current.Logger, httpContext) + { + + } + + /// + /// Initializes a new instance of the class with an initial list of object types, /// and an optional lifetime scope. - /// - /// The list of object types. - /// The lifetime scope of instantiated objects, default is per Application. - /// If is per HttpRequest then there must be a current HttpContext. - /// is per HttpRequest but the current HttpContext is null. - protected ManyObjectsResolverBase(IEnumerable value, ObjectLifetimeScope scope = ObjectLifetimeScope.Application) - : this(scope) + /// + /// + /// + /// The list of object types. + /// The lifetime scope of instantiated objects, default is per Application. + /// If is per HttpRequest then there must be a current HttpContext. + /// is per HttpRequest but the current HttpContext is null. + protected ManyObjectsResolverBase(IServiceProvider serviceProvider, ILogger logger, IEnumerable value, ObjectLifetimeScope scope = ObjectLifetimeScope.Application) + : this(serviceProvider, logger, scope) { _instanceTypes = value.ToList(); } + [EditorBrowsable(EditorBrowsableState.Never)] + [Obsolete("Use ctor specifying IServiceProvider instead")] + protected ManyObjectsResolverBase(IEnumerable value, ObjectLifetimeScope scope = ObjectLifetimeScope.Application) + : this(new ActivatorServiceProvider(), LoggerResolver.Current.Logger, value, scope) + { + + } + /// /// Initializes a new instance of the class with an initial list of objects, /// with creation of objects based on an HttpRequest lifetime scope. @@ -91,8 +129,9 @@ namespace Umbraco.Core.ObjectResolution /// The HttpContextBase corresponding to the HttpRequest. /// The list of object types. /// is null. - protected ManyObjectsResolverBase(HttpContextBase httpContext, IEnumerable value) - : this(httpContext) + [Obsolete("Use ctor specifying IServiceProvider instead")] + protected ManyObjectsResolverBase(HttpContextBase httpContext, IEnumerable value) + : this(new ActivatorServiceProvider(), LoggerResolver.Current.Logger, httpContext) { _instanceTypes = value.ToList(); } @@ -123,7 +162,14 @@ namespace Umbraco.Core.ObjectResolution /// If not null, then LifetimeScope will be ObjectLifetimeScope.HttpRequest. protected HttpContextBase CurrentHttpContext { get; private set; } - /// + /// + /// Returns the service provider used to instantiate objects + /// + public IServiceProvider ServiceProvider { get; private set; } + + public ILogger Logger { get; private set; } + + /// /// Gets or sets the lifetime scope of resolved objects. /// protected ObjectLifetimeScope LifetimeScope { get; private set; } @@ -191,7 +237,14 @@ namespace Umbraco.Core.ObjectResolution // create new instances per HttpContext if (CurrentHttpContext.Items[_httpContextKey] == null) { - CurrentHttpContext.Items[_httpContextKey] = CreateInstances().ToArray(); + var instances = CreateInstances().ToArray(); + var disposableInstances = instances.OfType(); + //Ensure anything resolved that is IDisposable is disposed when the request termintates + foreach (var disposable in disposableInstances) + { + CurrentHttpContext.DisposeOnPipelineCompleted(disposable); + } + CurrentHttpContext.Items[_httpContextKey] = instances; } return (TResolved[])CurrentHttpContext.Items[_httpContextKey]; @@ -214,7 +267,7 @@ namespace Umbraco.Core.ObjectResolution /// A list of objects of type . protected virtual IEnumerable CreateInstances() { - return PluginManager.Current.CreateInstances(InstanceTypes); + return ServiceProvider.CreateInstances(InstanceTypes, Logger); } #region Types collection manipulation @@ -423,7 +476,7 @@ namespace Umbraco.Core.ObjectResolution { EnsureCorrectType(existingType); EnsureCorrectType(value); - if (!_instanceTypes.Contains(existingType)) + if (_instanceTypes.Contains(existingType) == false) { throw new InvalidOperationException(string.Format( "Type {0} is not in the collection of types.", existingType.FullName)); @@ -514,9 +567,9 @@ namespace Umbraco.Core.ObjectResolution /// the type is not a valid type for the resolver. protected virtual void EnsureCorrectType(Type value) { - if (!TypeHelper.IsTypeAssignableFrom(value)) + if (TypeHelper.IsTypeAssignableFrom(value) == false) throw new InvalidOperationException(string.Format( - "Type {0} is not an acceptable type for resolver {1}.", value.FullName, this.GetType().FullName)); + "Type {0} is not an acceptable type for resolver {1}.", value.FullName, GetType().FullName)); } #endregion @@ -529,7 +582,7 @@ namespace Umbraco.Core.ObjectResolution /// The resolver does not support removing types. protected void EnsureSupportsRemove() { - if (!SupportsRemove) + if (SupportsRemove == false) throw new InvalidOperationException("This resolver does not support removing types"); } @@ -538,7 +591,7 @@ namespace Umbraco.Core.ObjectResolution /// /// The resolver does not support clearing types. protected void EnsureSupportsClear() { - if (!SupportsClear) + if (SupportsClear == false) throw new InvalidOperationException("This resolver does not support clearing types"); } @@ -548,7 +601,7 @@ namespace Umbraco.Core.ObjectResolution /// The resolver does not support adding types. protected void EnsureSupportsAdd() { - if (!SupportsAdd) + if (SupportsAdd == false) throw new InvalidOperationException("This resolver does not support adding new types"); } @@ -558,7 +611,7 @@ namespace Umbraco.Core.ObjectResolution /// The resolver does not support inserting types. protected void EnsureSupportsInsert() { - if (!SupportsInsert) + if (SupportsInsert == false) throw new InvalidOperationException("This resolver does not support inserting new types"); } diff --git a/src/Umbraco.Core/PackageActionsResolver.cs b/src/Umbraco.Core/PackageActionsResolver.cs index 551bf8cfa7..717262d100 100644 --- a/src/Umbraco.Core/PackageActionsResolver.cs +++ b/src/Umbraco.Core/PackageActionsResolver.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using Umbraco.Core.Logging; using Umbraco.Core.ObjectResolution; using umbraco.interfaces; @@ -10,13 +11,14 @@ namespace Umbraco.Core /// internal sealed class PackageActionsResolver : LazyManyObjectsResolverBase { - - /// - /// Constructor - /// - /// - internal PackageActionsResolver(Func> packageActions) - : base(packageActions) + /// + /// Constructor + /// + /// + /// + /// + internal PackageActionsResolver(IServiceProvider serviceProvider, ILogger logger, Func> packageActions) + : base(serviceProvider, logger, packageActions) { } diff --git a/src/Umbraco.Core/Persistence/Caching/IRepositoryCacheProvider.cs b/src/Umbraco.Core/Persistence/Caching/IRepositoryCacheProvider.cs deleted file mode 100644 index fca941d6eb..0000000000 --- a/src/Umbraco.Core/Persistence/Caching/IRepositoryCacheProvider.cs +++ /dev/null @@ -1,57 +0,0 @@ -using System; -using System.Collections.Generic; -using Umbraco.Core.Cache; -using Umbraco.Core.Models.EntityBase; - -namespace Umbraco.Core.Persistence.Caching -{ - - /// - /// Defines the implementation of a Cache Provider intented to back a repository - /// - internal interface IRepositoryCacheProvider - { - /// - /// Gets an Entity from the cache by Type and Id - /// - /// - /// - /// - IEntity GetById(Type type, Guid id); - - /// - /// Gets an Entity from the cache by Type and Ids - /// - /// - /// - /// - IEnumerable GetByIds(Type type, List ids); - - /// - /// Gets all Entities of specified type - /// - /// - /// - IEnumerable GetAllByType(Type type); - - /// - /// Saves the Entity - /// - /// - /// - void Save(Type type, IEntity entity); - - /// - /// Deletes the Entity from the cache - /// - /// - /// - void Delete(Type type, IEntity entity); - - /// - /// Clears the cache by type - /// - /// - void Clear(Type type); - } -} \ No newline at end of file diff --git a/src/Umbraco.Core/Persistence/Caching/InMemoryCacheProvider.cs b/src/Umbraco.Core/Persistence/Caching/InMemoryCacheProvider.cs deleted file mode 100644 index 7572dcd5c5..0000000000 --- a/src/Umbraco.Core/Persistence/Caching/InMemoryCacheProvider.cs +++ /dev/null @@ -1,142 +0,0 @@ -using System; -using System.Collections.Concurrent; -using System.Collections.Generic; -using System.Linq; -using Umbraco.Core.Models.EntityBase; - -namespace Umbraco.Core.Persistence.Caching -{ - /// - /// The InMemory registry looks up objects in an in-memory dictionary for fast retrival - /// - internal class InMemoryCacheProvider : IRepositoryCacheProvider - { - #region Singleton - - private static readonly Lazy lazy = new Lazy(() => new InMemoryCacheProvider()); - - public static InMemoryCacheProvider Current { get { return lazy.Value; } } - - private InMemoryCacheProvider() - { - } - - #endregion - - private readonly ConcurrentDictionary _cache = new ConcurrentDictionary(); - - /// - /// Retrives an object of the specified type by its Id - /// - /// The type of the object to retrive, which implements - /// The Guid Id of the Object to retrive - /// - public IEntity GetById(Type type, Guid id) - { - var compositeKey = GetCompositeId(type, id); - var containsKey = _cache.ContainsKey(compositeKey); - if (containsKey) - { - var result = _cache[compositeKey]; - - //IMPORTANT: we must clone to resolve, see: http://issues.umbraco.org/issue/U4-4259 - return (IEntity)result.DeepClone(); - } - - return null; - } - - /// - /// Retrives objects of the specified type by their Ids - /// - /// The type of the objects to retrive, which implements - /// The Guid Ids of the Objects to retrive - /// - public IEnumerable GetByIds(Type type, List ids) - { - var list = (from id in ids - select GetCompositeId(type, id) - into key - let containsKey = _cache.ContainsKey(key) - where containsKey - select _cache[key] - into result - //don't return null objects - where result != null - //IMPORTANT: we must clone to resolve, see: http://issues.umbraco.org/issue/U4-4259 - select (IEntity)result.DeepClone()).ToList(); - return list; - } - - /// - /// Retrives all objects of the specified type - /// - /// The type of the objects to retrive, which implements - /// - public IEnumerable GetAllByType(Type type) - { - var list = _cache.Keys - .Where(key => key.Contains(type.Name)) - .Select(key => _cache[key]) - //don't return null objects - .Where(result => result != null) - //IMPORTANT: we must clone to resolve, see: http://issues.umbraco.org/issue/U4-4259 - .Select(result => (IEntity)result.DeepClone()) - .ToList(); - return list; - } - - /// - /// Saves an object in the registry cache - /// - /// - /// - public void Save(Type type, IEntity entity) - { - //IMPORTANT: we must clone to store, see: http://issues.umbraco.org/issue/U4-4259 - entity = (IEntity)entity.DeepClone(); - - _cache.AddOrUpdate(GetCompositeId(type, entity.Id), entity, (x, y) => entity); - } - - /// - /// Deletes an object from the registry cache - /// - /// - /// - public void Delete(Type type, IEntity entity) - { - IEntity entity1; - bool result = _cache.TryRemove(GetCompositeId(type, entity.Id), out entity1); - } - - /// - /// Clear cache by type - /// - /// - public void Clear(Type type) - { - var keys = _cache.Keys; - foreach (var key in keys.Where(x => x.StartsWith(string.Format("{0}-", type.Name)))) - { - IEntity e; - _cache.TryRemove(key, out e); - } - } - - public void Clear() - { - _cache.Clear(); - } - - private string GetCompositeId(Type type, Guid id) - { - return string.Format("{0}-{1}", type.Name, id.ToString()); - } - - private string GetCompositeId(Type type, int id) - { - return string.Format("{0}-{1}", type.Name, id.ToGuid()); - } - } -} \ No newline at end of file diff --git a/src/Umbraco.Core/Persistence/Caching/NullCacheProvider.cs b/src/Umbraco.Core/Persistence/Caching/NullCacheProvider.cs deleted file mode 100644 index c7e868389b..0000000000 --- a/src/Umbraco.Core/Persistence/Caching/NullCacheProvider.cs +++ /dev/null @@ -1,56 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using Umbraco.Core.Models.EntityBase; - -namespace Umbraco.Core.Persistence.Caching -{ - internal class NullCacheProvider : IRepositoryCacheProvider - { - #region Singleton - - private static readonly Lazy lazy = new Lazy(() => new NullCacheProvider()); - - public static NullCacheProvider Current { get { return lazy.Value; } } - - private NullCacheProvider() - { - } - - #endregion - - #region Implementation of IRepositoryCacheProvider - - public IEntity GetById(Type type, Guid id) - { - return null; - } - - public IEnumerable GetByIds(Type type, List ids) - { - return Enumerable.Empty(); - } - - public IEnumerable GetAllByType(Type type) - { - return Enumerable.Empty(); - } - - public void Save(Type type, IEntity entity) - { - return; - } - - public void Delete(Type type, IEntity entity) - { - return; - } - - public void Clear(Type type) - { - return; - } - - #endregion - } -} \ No newline at end of file diff --git a/src/Umbraco.Core/Persistence/Caching/RuntimeCacheProvider.cs b/src/Umbraco.Core/Persistence/Caching/RuntimeCacheProvider.cs deleted file mode 100644 index 611036f852..0000000000 --- a/src/Umbraco.Core/Persistence/Caching/RuntimeCacheProvider.cs +++ /dev/null @@ -1,258 +0,0 @@ -using System; -using System.Collections; -using System.Collections.Concurrent; -using System.Collections.Generic; -using System.Linq; -using System.Runtime.Caching; -using System.Threading; -using System.Web; -using Umbraco.Core.Models.EntityBase; - -namespace Umbraco.Core.Persistence.Caching -{ - /// - /// The Runtime Cache provider looks up objects in the Runtime cache for fast retrival - /// - /// - /// - /// If a web session is detected then the HttpRuntime.Cache will be used for the runtime cache, otherwise a custom - /// MemoryCache instance will be used. It is important to use the HttpRuntime.Cache when a web session is detected so - /// that the memory management of cache in IIS can be handled appopriately. - /// - /// When a web sessions is detected we will pre-fix all HttpRuntime.Cache entries so that when we clear it we are only - /// clearing items that have been inserted by this provider. - /// - /// NOTE: These changes are all temporary until we finalize the ApplicationCache implementation which will support static cache, runtime cache - /// and request based cache which will all live in one central location so it is easily managed. - /// - /// Also note that we don't always keep checking if HttpContext.Current == null and instead check for _memoryCache != null. This is because - /// when there are async requests being made even in the context of a web request, the HttpContext.Current will be null but the HttpRuntime.Cache will - /// always be available. - /// - /// TODO: Each item that get's added to this cache will be a clone of the original with it's dirty properties reset, and every item that is resolved from the cache - /// is a clone of the item that is in there, otherwise we end up with thread safety issues since multiple thread would be working on the exact same entity at the same time. - /// - /// - internal sealed class RuntimeCacheProvider : IRepositoryCacheProvider - { - #region Singleton - - private static readonly Lazy lazy = new Lazy(() => new RuntimeCacheProvider()); - - public static RuntimeCacheProvider Current { get { return lazy.Value; } } - - //internal for testing! - though I'm not a huge fan of these being singletons! - internal RuntimeCacheProvider() - { - if (HttpContext.Current == null) - { - _memoryCache = new MemoryCache("in-memory"); - } - } - - #endregion - - //TODO Save this in cache as well, so its not limited to a single server usage - private readonly ConcurrentHashSet _keyTracker = new ConcurrentHashSet(); - private ObjectCache _memoryCache; - private static readonly ReaderWriterLockSlim ClearLock = new ReaderWriterLockSlim(); - - public IEntity GetById(Type type, Guid id) - { - var key = GetCompositeId(type, id); - var item = _memoryCache != null - ? _memoryCache.Get(key) - : HttpRuntime.Cache.Get(key); - var result = item as IEntity; - if (result == null) - { - //ensure the key doesn't exist anymore in the tracker - _keyTracker.Remove(key); - return null; - } - - //IMPORTANT: we must clone to resolve, see: http://issues.umbraco.org/issue/U4-4259 - return (IEntity)result.DeepClone(); - } - - public IEnumerable GetByIds(Type type, List ids) - { - var collection = new List(); - foreach (var guid in ids) - { - var key = GetCompositeId(type, guid); - var item = _memoryCache != null - ? _memoryCache.Get(key) - : HttpRuntime.Cache.Get(key); - var result = item as IEntity; - if (result == null) - { - //ensure the key doesn't exist anymore in the tracker - _keyTracker.Remove(key); - } - else - { - //IMPORTANT: we must clone to resolve, see: http://issues.umbraco.org/issue/U4-4259 - collection.Add((IEntity)result.DeepClone()); - } - } - return collection; - } - - public IEnumerable GetAllByType(Type type) - { - var collection = new List(); - foreach (var key in _keyTracker) - { - if (key.StartsWith(string.Format("{0}{1}-", CacheItemPrefix, type.Name))) - { - var item = _memoryCache != null - ? _memoryCache.Get(key) - : HttpRuntime.Cache.Get(key); - - var result = item as IEntity; - if (result == null) - { - //ensure the key doesn't exist anymore in the tracker - _keyTracker.Remove(key); - } - else - { - //IMPORTANT: we must clone to resolve, see: http://issues.umbraco.org/issue/U4-4259 - collection.Add((IEntity)result.DeepClone()); - } - } - } - return collection; - } - - public void Save(Type type, IEntity entity) - { - //IMPORTANT: we must clone to store, see: http://issues.umbraco.org/issue/U4-4259 - var clone = (IEntity)entity.DeepClone(); - - var key = GetCompositeId(type, clone.Id); - - _keyTracker.TryAdd(key); - - //NOTE: Before we were checking if it already exists but the MemoryCache.Set handles this implicitly and does - // an add or update, same goes for HttpRuntime.Cache.Insert. - - if (_memoryCache != null) - { - _memoryCache.Set(key, clone, new CacheItemPolicy { SlidingExpiration = TimeSpan.FromMinutes(5) }); - } - else - { - HttpRuntime.Cache.Insert(key, clone, null, System.Web.Caching.Cache.NoAbsoluteExpiration, TimeSpan.FromMinutes(5)); - } - } - - public void Delete(Type type, IEntity entity) - { - var key = GetCompositeId(type, entity.Id); - if (_memoryCache != null) - { - _memoryCache.Remove(key); - } - else - { - HttpRuntime.Cache.Remove(key); - } - - _keyTracker.Remove(key); - } - - public void Delete(Type type, int entityId) - { - var key = GetCompositeId(type, entityId); - if (_memoryCache != null) - { - _memoryCache.Remove(key); - } - else - { - HttpRuntime.Cache.Remove(key); - } - - _keyTracker.Remove(key); - } - - /// - /// Clear cache by type - /// - /// - public void Clear(Type type) - { - using (new WriteLock(ClearLock)) - { - var keys = new string[_keyTracker.Count]; - _keyTracker.CopyTo(keys, 0); - var keysToRemove = new List(); - foreach (var key in keys.Where(x => x.StartsWith(string.Format("{0}{1}-", CacheItemPrefix, type.Name)))) - { - _keyTracker.Remove(key); - keysToRemove.Add(key); - } - foreach (var key in keysToRemove) - { - if (_memoryCache != null) - { - _memoryCache.Remove(key); - } - else - { - HttpRuntime.Cache.Remove(key); - } - } - } - } - - public void Clear() - { - using (new WriteLock(ClearLock)) - { - _keyTracker.Clear(); - - ClearDataCache(); - } - } - - //DO not call this unless it's for testing since it clears the data cached but not the keys - internal void ClearDataCache() - { - if (_memoryCache != null) - { - _memoryCache.DisposeIfDisposable(); - _memoryCache = new MemoryCache("in-memory"); - } - else - { - foreach (DictionaryEntry c in HttpRuntime.Cache) - { - if (c.Key is string && ((string)c.Key).InvariantStartsWith(CacheItemPrefix)) - { - if (HttpRuntime.Cache[(string)c.Key] == null) return; - HttpRuntime.Cache.Remove((string)c.Key); - } - } - } - } - - /// - /// We prefix all cache keys with this so that we know which ones this class has created when - /// using the HttpRuntime cache so that when we clear it we don't clear other entries we didn't create. - /// - private const string CacheItemPrefix = "umbrtmche_"; - - private string GetCompositeId(Type type, Guid id) - { - return string.Format("{0}{1}-{2}", CacheItemPrefix, type.Name, id); - } - - private string GetCompositeId(Type type, int id) - { - return string.Format("{0}{1}-{2}", CacheItemPrefix, type.Name, id.ToGuid()); - } - } -} \ No newline at end of file diff --git a/src/Umbraco.Core/Persistence/DatabaseFactory.cs b/src/Umbraco.Core/Persistence/DatabaseFactory.cs deleted file mode 100644 index 6ce5bd6ac4..0000000000 --- a/src/Umbraco.Core/Persistence/DatabaseFactory.cs +++ /dev/null @@ -1,34 +0,0 @@ -using System; -using System.Threading; -using Umbraco.Core.Configuration; - -namespace Umbraco.Core.Persistence -{ - /// - /// Provides access to the PetaPoco database as Singleton, so the database is created once in app lifecycle. - /// This is necessary for transactions to work properly - /// - public sealed class DatabaseFactory - { - #region Singleton - - private static readonly Database _database = new Database(GlobalSettings.DbDsn); - private static readonly Lazy lazy = new Lazy(() => new DatabaseFactory()); - - public static DatabaseFactory Current { get { return lazy.Value; } } - - private DatabaseFactory() - { - } - - #endregion - - /// - /// Returns an instance of the PetaPoco database - /// - public Database Database - { - get { return _database; } - } - } -} \ No newline at end of file diff --git a/src/Umbraco.Core/Persistence/DatabaseSchemaHelper.cs b/src/Umbraco.Core/Persistence/DatabaseSchemaHelper.cs new file mode 100644 index 0000000000..5129032bcf --- /dev/null +++ b/src/Umbraco.Core/Persistence/DatabaseSchemaHelper.cs @@ -0,0 +1,193 @@ +using System; +using System.Linq; +using Umbraco.Core.Logging; +using Umbraco.Core.Models.Rdbms; +using Umbraco.Core.Persistence.DatabaseModelDefinitions; +using Umbraco.Core.Persistence.Migrations.Initial; +using Umbraco.Core.Persistence.SqlSyntax; + +namespace Umbraco.Core.Persistence +{ + + public class DatabaseSchemaHelper + { + private readonly Database _db; + private readonly ILogger _logger; + private readonly ISqlSyntaxProvider _syntaxProvider; + private readonly BaseDataCreation _baseDataCreation; + + public DatabaseSchemaHelper(Database db, ILogger logger, ISqlSyntaxProvider syntaxProvider) + { + _db = db; + _logger = logger; + _syntaxProvider = syntaxProvider; + _baseDataCreation = new BaseDataCreation(db, logger); + } + + public bool TableExist(string tableName) + { + return _syntaxProvider.DoesTableExist(_db, tableName); + } + + internal void UninstallDatabaseSchema() + { + var creation = new DatabaseSchemaCreation(_db, _logger, _syntaxProvider); + creation.UninstallDatabaseSchema(); + } + + /// + /// Creates the Umbraco db schema in the Database of the current Database. + /// Safe method that is only able to create the schema in non-configured + /// umbraco instances. + /// + public void CreateDatabaseSchema(ApplicationContext applicationContext) + { + if (applicationContext == null) throw new ArgumentNullException("applicationContext"); + CreateDatabaseSchema(true, applicationContext); + } + + /// + /// Creates the Umbraco db schema in the Database of the current Database + /// with the option to guard the db from having the schema created + /// multiple times. + /// + /// + /// + public void CreateDatabaseSchema(bool guardConfiguration, ApplicationContext applicationContext) + { + if (applicationContext == null) throw new ArgumentNullException("applicationContext"); + + if (guardConfiguration && applicationContext.IsConfigured) + throw new Exception("Umbraco is already configured!"); + + CreateDatabaseSchemaDo(); + } + + internal void CreateDatabaseSchemaDo(bool guardConfiguration, ApplicationContext applicationContext) + { + if (guardConfiguration && applicationContext.IsConfigured) + throw new Exception("Umbraco is already configured!"); + + CreateDatabaseSchemaDo(); + } + + internal void CreateDatabaseSchemaDo() + { + _logger.Info("Initializing database schema creation"); + + var creation = new DatabaseSchemaCreation(_db, _logger, _syntaxProvider); + creation.InitializeDatabaseSchema(); + + _logger.Info("Finalized database schema creation"); + } + + public void CreateTable(bool overwrite) + where T : new() + { + var tableType = typeof(T); + CreateTable(overwrite, tableType); + } + + public void CreateTable() + where T : new() + { + var tableType = typeof(T); + CreateTable(false, tableType); + } + + public void CreateTable(bool overwrite, Type modelType) + { + var tableDefinition = DefinitionFactory.GetTableDefinition(modelType); + var tableName = tableDefinition.Name; + + string createSql = _syntaxProvider.Format(tableDefinition); + string createPrimaryKeySql = _syntaxProvider.FormatPrimaryKey(tableDefinition); + var foreignSql = _syntaxProvider.Format(tableDefinition.ForeignKeys); + var indexSql = _syntaxProvider.Format(tableDefinition.Indexes); + + var tableExist = _db.TableExist(tableName); + if (overwrite && tableExist) + { + _db.DropTable(tableName); + tableExist = false; + } + + if (tableExist == false) + { + using (var transaction = _db.GetTransaction()) + { + //Execute the Create Table sql + int created = _db.Execute(new Sql(createSql)); + _logger.Info(string.Format("Create Table sql {0}:\n {1}", created, createSql)); + + //If any statements exists for the primary key execute them here + if (!string.IsNullOrEmpty(createPrimaryKeySql)) + { + int createdPk = _db.Execute(new Sql(createPrimaryKeySql)); + _logger.Info(string.Format("Primary Key sql {0}:\n {1}", createdPk, createPrimaryKeySql)); + } + + //Turn on identity insert if db provider is not mysql + if (_syntaxProvider.SupportsIdentityInsert() && tableDefinition.Columns.Any(x => x.IsIdentity)) + _db.Execute(new Sql(string.Format("SET IDENTITY_INSERT {0} ON ", _syntaxProvider.GetQuotedTableName(tableName)))); + + //Call the NewTable-event to trigger the insert of base/default data + //OnNewTable(tableName, _db, e, _logger); + + _baseDataCreation.InitializeBaseData(tableName); + + //Turn off identity insert if db provider is not mysql + if (_syntaxProvider.SupportsIdentityInsert() && tableDefinition.Columns.Any(x => x.IsIdentity)) + _db.Execute(new Sql(string.Format("SET IDENTITY_INSERT {0} OFF;", _syntaxProvider.GetQuotedTableName(tableName)))); + + //Special case for MySql + if (_syntaxProvider is MySqlSyntaxProvider && tableName.Equals("umbracoUser")) + { + _db.Update("SET id = @IdAfter WHERE id = @IdBefore AND userLogin = @Login", new { IdAfter = 0, IdBefore = 1, Login = "admin" }); + } + + //Loop through foreignkey statements and execute sql + foreach (var sql in foreignSql) + { + int createdFk = _db.Execute(new Sql(sql)); + _logger.Info(string.Format("Create Foreign Key sql {0}:\n {1}", createdFk, sql)); + } + + //Loop through index statements and execute sql + foreach (var sql in indexSql) + { + int createdIndex = _db.Execute(new Sql(sql)); + _logger.Info(string.Format("Create Index sql {0}:\n {1}", createdIndex, sql)); + } + + transaction.Complete(); + } + } + + _logger.Info(string.Format("New table '{0}' was created", tableName)); + } + + public void DropTable() + where T : new() + { + Type type = typeof(T); + var tableNameAttribute = type.FirstAttribute(); + if (tableNameAttribute == null) + throw new Exception( + string.Format( + "The Type '{0}' does not contain a TableNameAttribute, which is used to find the name of the table to drop. The operation could not be completed.", + type.Name)); + + string tableName = tableNameAttribute.Value; + DropTable(tableName); + } + + public void DropTable(string tableName) + { + var sql = new Sql(string.Format( + _syntaxProvider.DropTable, + _syntaxProvider.GetQuotedTableName(tableName))); + _db.Execute(sql); + } + } +} \ No newline at end of file diff --git a/src/Umbraco.Core/Persistence/DefaultDatabaseFactory.cs b/src/Umbraco.Core/Persistence/DefaultDatabaseFactory.cs index 2014ceb1cf..72c4275541 100644 --- a/src/Umbraco.Core/Persistence/DefaultDatabaseFactory.cs +++ b/src/Umbraco.Core/Persistence/DefaultDatabaseFactory.cs @@ -1,6 +1,7 @@ using System; using System.Web; using Umbraco.Core.Configuration; +using Umbraco.Core.Logging; namespace Umbraco.Core.Persistence { @@ -15,7 +16,8 @@ namespace Umbraco.Core.Persistence internal class DefaultDatabaseFactory : DisposableObject, IDatabaseFactory { private readonly string _connectionStringName; - public string ConnectionString { get; private set; } + private readonly ILogger _logger; + public string ConnectionString { get; private set; } public string ProviderName { get; private set; } //very important to have ThreadStatic: @@ -25,35 +27,33 @@ namespace Umbraco.Core.Persistence private static readonly object Locker = new object(); - /// - /// Default constructor initialized with the GlobalSettings.UmbracoConnectionName - /// - public DefaultDatabaseFactory() : this(GlobalSettings.UmbracoConnectionName) + /// + /// Constructor accepting custom connection string + /// + /// Name of the connection string in web.config + /// + public DefaultDatabaseFactory(string connectionStringName, ILogger logger) { - - } - - /// - /// Constructor accepting custom connection string - /// - /// Name of the connection string in web.config - public DefaultDatabaseFactory(string connectionStringName) - { - Mandate.ParameterNotNullOrEmpty(connectionStringName, "connectionStringName"); + 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) + /// + /// 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) { - Mandate.ParameterNotNullOrEmpty(connectionString, "connectionString"); + if (logger == null) throw new ArgumentNullException("logger"); + Mandate.ParameterNotNullOrEmpty(connectionString, "connectionString"); Mandate.ParameterNotNullOrEmpty(providerName, "providerName"); ConnectionString = connectionString; ProviderName = providerName; + _logger = logger; } public UmbracoDatabase CreateDatabase() @@ -69,8 +69,8 @@ namespace Umbraco.Core.Persistence if (_nonHttpInstance == null) { _nonHttpInstance = string.IsNullOrEmpty(ConnectionString) == false && string.IsNullOrEmpty(ProviderName) == false - ? new UmbracoDatabase(ConnectionString, ProviderName) - : new UmbracoDatabase(_connectionStringName); + ? new UmbracoDatabase(ConnectionString, ProviderName, _logger) + : new UmbracoDatabase(_connectionStringName, _logger); } } } @@ -82,8 +82,8 @@ namespace Umbraco.Core.Persistence { HttpContext.Current.Items.Add(typeof (DefaultDatabaseFactory), string.IsNullOrEmpty(ConnectionString) == false && string.IsNullOrEmpty(ProviderName) == false - ? new UmbracoDatabase(ConnectionString, ProviderName) - : new UmbracoDatabase(_connectionStringName)); + ? new UmbracoDatabase(ConnectionString, ProviderName, _logger) + : new UmbracoDatabase(_connectionStringName, _logger)); } return (UmbracoDatabase)HttpContext.Current.Items[typeof(DefaultDatabaseFactory)]; } diff --git a/src/Umbraco.Core/Persistence/Factories/ContentFactory.cs b/src/Umbraco.Core/Persistence/Factories/ContentFactory.cs index d5f89e762c..3e2477594d 100644 --- a/src/Umbraco.Core/Persistence/Factories/ContentFactory.cs +++ b/src/Umbraco.Core/Persistence/Factories/ContentFactory.cs @@ -5,7 +5,7 @@ using Umbraco.Core.Models.Rdbms; namespace Umbraco.Core.Persistence.Factories { - internal class ContentFactory : IEntityFactory + internal class ContentFactory { private readonly IContentType _contentType; private readonly Guid _nodeObjectTypeId; diff --git a/src/Umbraco.Core/Persistence/Factories/ContentTypeFactory.cs b/src/Umbraco.Core/Persistence/Factories/ContentTypeFactory.cs index cc9ab387f8..23c9270906 100644 --- a/src/Umbraco.Core/Persistence/Factories/ContentTypeFactory.cs +++ b/src/Umbraco.Core/Persistence/Factories/ContentTypeFactory.cs @@ -6,7 +6,7 @@ using Umbraco.Core.Models.Rdbms; namespace Umbraco.Core.Persistence.Factories { - internal class ContentTypeFactory : IEntityFactory + internal class ContentTypeFactory { private readonly Guid _nodeObjectType; diff --git a/src/Umbraco.Core/Persistence/Factories/DataTypeDefinitionFactory.cs b/src/Umbraco.Core/Persistence/Factories/DataTypeDefinitionFactory.cs index 13a7ecad35..7b57800277 100644 --- a/src/Umbraco.Core/Persistence/Factories/DataTypeDefinitionFactory.cs +++ b/src/Umbraco.Core/Persistence/Factories/DataTypeDefinitionFactory.cs @@ -5,7 +5,7 @@ using Umbraco.Core.Models.Rdbms; namespace Umbraco.Core.Persistence.Factories { - internal class DataTypeDefinitionFactory : IEntityFactory + internal class DataTypeDefinitionFactory { private readonly Guid _nodeObjectTypeId; private int _primaryKey; diff --git a/src/Umbraco.Core/Persistence/Factories/DictionaryItemFactory.cs b/src/Umbraco.Core/Persistence/Factories/DictionaryItemFactory.cs index 4b8e0a74ee..14dca6b366 100644 --- a/src/Umbraco.Core/Persistence/Factories/DictionaryItemFactory.cs +++ b/src/Umbraco.Core/Persistence/Factories/DictionaryItemFactory.cs @@ -4,7 +4,7 @@ using Umbraco.Core.Models.Rdbms; namespace Umbraco.Core.Persistence.Factories { - internal class DictionaryItemFactory : IEntityFactory + internal class DictionaryItemFactory { #region Implementation of IEntityFactory diff --git a/src/Umbraco.Core/Persistence/Factories/DictionaryTranslationFactory.cs b/src/Umbraco.Core/Persistence/Factories/DictionaryTranslationFactory.cs index ee2c8659d2..8dca2494d0 100644 --- a/src/Umbraco.Core/Persistence/Factories/DictionaryTranslationFactory.cs +++ b/src/Umbraco.Core/Persistence/Factories/DictionaryTranslationFactory.cs @@ -4,7 +4,7 @@ using Umbraco.Core.Models.Rdbms; namespace Umbraco.Core.Persistence.Factories { - internal class DictionaryTranslationFactory : IEntityFactory + internal class DictionaryTranslationFactory { private readonly Guid _uniqueId; private ILanguage _language; diff --git a/src/Umbraco.Core/Persistence/Factories/IEntityFactory.cs b/src/Umbraco.Core/Persistence/Factories/IEntityFactory.cs deleted file mode 100644 index d413e30308..0000000000 --- a/src/Umbraco.Core/Persistence/Factories/IEntityFactory.cs +++ /dev/null @@ -1,13 +0,0 @@ -namespace Umbraco.Core.Persistence.Factories -{ - //TODO: Not sure why we need this interface as it's never referenced in code. - //TODO: Delete this - - internal interface IEntityFactory - where TEntity : class - where TDto : class - { - TEntity BuildEntity(TDto dto); - TDto BuildDto(TEntity entity); - } -} \ No newline at end of file diff --git a/src/Umbraco.Core/Persistence/Factories/LanguageFactory.cs b/src/Umbraco.Core/Persistence/Factories/LanguageFactory.cs index a2fd9892cd..0287a58b78 100644 --- a/src/Umbraco.Core/Persistence/Factories/LanguageFactory.cs +++ b/src/Umbraco.Core/Persistence/Factories/LanguageFactory.cs @@ -4,7 +4,7 @@ using Umbraco.Core.Models.Rdbms; namespace Umbraco.Core.Persistence.Factories { - internal class LanguageFactory : IEntityFactory + internal class LanguageFactory { #region Implementation of IEntityFactory diff --git a/src/Umbraco.Core/Persistence/Factories/MacroFactory.cs b/src/Umbraco.Core/Persistence/Factories/MacroFactory.cs index 9a3445fe78..d6b54e4797 100644 --- a/src/Umbraco.Core/Persistence/Factories/MacroFactory.cs +++ b/src/Umbraco.Core/Persistence/Factories/MacroFactory.cs @@ -5,7 +5,7 @@ using Umbraco.Core.Models.Rdbms; namespace Umbraco.Core.Persistence.Factories { - internal class MacroFactory : IEntityFactory + internal class MacroFactory { #region Implementation of IEntityFactory diff --git a/src/Umbraco.Core/Persistence/Factories/MediaFactory.cs b/src/Umbraco.Core/Persistence/Factories/MediaFactory.cs index 1ce8a7b37d..cf285cbf66 100644 --- a/src/Umbraco.Core/Persistence/Factories/MediaFactory.cs +++ b/src/Umbraco.Core/Persistence/Factories/MediaFactory.cs @@ -5,7 +5,7 @@ using Umbraco.Core.Models.Rdbms; namespace Umbraco.Core.Persistence.Factories { - internal class MediaFactory : IEntityFactory + internal class MediaFactory { private readonly IMediaType _contentType; private readonly Guid _nodeObjectTypeId; diff --git a/src/Umbraco.Core/Persistence/Factories/MediaTypeFactory.cs b/src/Umbraco.Core/Persistence/Factories/MediaTypeFactory.cs index ee2709a79e..b63512e1b6 100644 --- a/src/Umbraco.Core/Persistence/Factories/MediaTypeFactory.cs +++ b/src/Umbraco.Core/Persistence/Factories/MediaTypeFactory.cs @@ -5,7 +5,7 @@ using Umbraco.Core.Models.Rdbms; namespace Umbraco.Core.Persistence.Factories { - internal class MediaTypeFactory : IEntityFactory + internal class MediaTypeFactory { private readonly Guid _nodeObjectType; diff --git a/src/Umbraco.Core/Persistence/Factories/MemberFactory.cs b/src/Umbraco.Core/Persistence/Factories/MemberFactory.cs index 3a5786d554..42e09b2f9c 100644 --- a/src/Umbraco.Core/Persistence/Factories/MemberFactory.cs +++ b/src/Umbraco.Core/Persistence/Factories/MemberFactory.cs @@ -6,7 +6,7 @@ using Umbraco.Core.Models.Rdbms; namespace Umbraco.Core.Persistence.Factories { - internal class MemberFactory : IEntityFactory + internal class MemberFactory { private readonly IMemberType _contentType; private readonly Guid _nodeObjectTypeId; diff --git a/src/Umbraco.Core/Persistence/Factories/MemberGroupFactory.cs b/src/Umbraco.Core/Persistence/Factories/MemberGroupFactory.cs index 207eea83b3..17dbba3001 100644 --- a/src/Umbraco.Core/Persistence/Factories/MemberGroupFactory.cs +++ b/src/Umbraco.Core/Persistence/Factories/MemberGroupFactory.cs @@ -4,7 +4,7 @@ using Umbraco.Core.Models.Rdbms; namespace Umbraco.Core.Persistence.Factories { - internal class MemberGroupFactory : IEntityFactory + internal class MemberGroupFactory { private readonly Guid _nodeObjectTypeId; diff --git a/src/Umbraco.Core/Persistence/Factories/MemberTypeFactory.cs b/src/Umbraco.Core/Persistence/Factories/MemberTypeFactory.cs index 7d971b4d7b..345981342b 100644 --- a/src/Umbraco.Core/Persistence/Factories/MemberTypeFactory.cs +++ b/src/Umbraco.Core/Persistence/Factories/MemberTypeFactory.cs @@ -7,7 +7,7 @@ using Umbraco.Core.Models.Rdbms; namespace Umbraco.Core.Persistence.Factories { - internal class MemberTypeFactory : IEntityFactory + internal class MemberTypeFactory { private readonly Guid _nodeObjectType; diff --git a/src/Umbraco.Core/Persistence/Factories/MemberTypeReadOnlyFactory.cs b/src/Umbraco.Core/Persistence/Factories/MemberTypeReadOnlyFactory.cs index 2a59f564e2..3db2fd8ba1 100644 --- a/src/Umbraco.Core/Persistence/Factories/MemberTypeReadOnlyFactory.cs +++ b/src/Umbraco.Core/Persistence/Factories/MemberTypeReadOnlyFactory.cs @@ -7,7 +7,7 @@ using Umbraco.Core.Persistence.Repositories; namespace Umbraco.Core.Persistence.Factories { - internal class MemberTypeReadOnlyFactory : IEntityFactory + internal class MemberTypeReadOnlyFactory { public IMemberType BuildEntity(MemberTypeReadOnlyDto dto) { diff --git a/src/Umbraco.Core/Persistence/Factories/PropertyGroupFactory.cs b/src/Umbraco.Core/Persistence/Factories/PropertyGroupFactory.cs index a7afd2bafc..4764f41544 100644 --- a/src/Umbraco.Core/Persistence/Factories/PropertyGroupFactory.cs +++ b/src/Umbraco.Core/Persistence/Factories/PropertyGroupFactory.cs @@ -6,7 +6,7 @@ using Umbraco.Core.Models.Rdbms; namespace Umbraco.Core.Persistence.Factories { - internal class PropertyGroupFactory : IEntityFactory, IEnumerable> + internal class PropertyGroupFactory { private readonly int _id; private readonly DateTime _createDate; diff --git a/src/Umbraco.Core/Persistence/Factories/RelationFactory.cs b/src/Umbraco.Core/Persistence/Factories/RelationFactory.cs index f8fa4bed16..5d614fb6d3 100644 --- a/src/Umbraco.Core/Persistence/Factories/RelationFactory.cs +++ b/src/Umbraco.Core/Persistence/Factories/RelationFactory.cs @@ -3,7 +3,7 @@ using Umbraco.Core.Models.Rdbms; namespace Umbraco.Core.Persistence.Factories { - internal class RelationFactory : IEntityFactory + internal class RelationFactory { private readonly IRelationType _relationType; diff --git a/src/Umbraco.Core/Persistence/Factories/RelationTypeFactory.cs b/src/Umbraco.Core/Persistence/Factories/RelationTypeFactory.cs index 08a80397ea..358b652d0b 100644 --- a/src/Umbraco.Core/Persistence/Factories/RelationTypeFactory.cs +++ b/src/Umbraco.Core/Persistence/Factories/RelationTypeFactory.cs @@ -3,7 +3,7 @@ using Umbraco.Core.Models.Rdbms; namespace Umbraco.Core.Persistence.Factories { - internal class RelationTypeFactory : IEntityFactory + internal class RelationTypeFactory { #region Implementation of IEntityFactory diff --git a/src/Umbraco.Core/Persistence/Factories/ServerRegistrationFactory.cs b/src/Umbraco.Core/Persistence/Factories/ServerRegistrationFactory.cs index 5f93bf56d3..e13b24e1e1 100644 --- a/src/Umbraco.Core/Persistence/Factories/ServerRegistrationFactory.cs +++ b/src/Umbraco.Core/Persistence/Factories/ServerRegistrationFactory.cs @@ -4,7 +4,7 @@ using Umbraco.Core.Models.Rdbms; namespace Umbraco.Core.Persistence.Factories { - internal class ServerRegistrationFactory : IEntityFactory + internal class ServerRegistrationFactory { #region Implementation of IEntityFactory diff --git a/src/Umbraco.Core/Persistence/Factories/TagFactory.cs b/src/Umbraco.Core/Persistence/Factories/TagFactory.cs index 7cebe5f65e..0aa60733de 100644 --- a/src/Umbraco.Core/Persistence/Factories/TagFactory.cs +++ b/src/Umbraco.Core/Persistence/Factories/TagFactory.cs @@ -3,7 +3,7 @@ using Umbraco.Core.Models.Rdbms; namespace Umbraco.Core.Persistence.Factories { - internal class TagFactory : IEntityFactory + internal class TagFactory { public ITag BuildEntity(TagDto dto) { diff --git a/src/Umbraco.Core/Persistence/Factories/TemplateFactory.cs b/src/Umbraco.Core/Persistence/Factories/TemplateFactory.cs index a62e9d3c00..1124d2e9a8 100644 --- a/src/Umbraco.Core/Persistence/Factories/TemplateFactory.cs +++ b/src/Umbraco.Core/Persistence/Factories/TemplateFactory.cs @@ -1,17 +1,24 @@ using System; +using System.Collections.Generic; using System.Globalization; +using System.Linq; +using Umbraco.Core.Configuration.UmbracoSettings; +using Umbraco.Core.IO; using Umbraco.Core.Models; +using Umbraco.Core.Models.EntityBase; using Umbraco.Core.Models.Rdbms; namespace Umbraco.Core.Persistence.Factories { - internal class TemplateFactory : IEntityFactory + internal class TemplateFactory { private readonly int _primaryKey; private readonly Guid _nodeObjectTypeId; public TemplateFactory() - {} + { + + } public TemplateFactory(Guid nodeObjectTypeId) { @@ -25,23 +32,25 @@ namespace Umbraco.Core.Persistence.Factories } #region Implementation of IEntityFactory - - public Template BuildEntity(TemplateDto dto) + + public Template BuildEntity(TemplateDto dto, IEnumerable childDefinitions) { - var template = new Template(string.Empty, dto.NodeDto.Text, dto.Alias) + var template = new Template(dto.NodeDto.Text, dto.Alias) { CreateDate = dto.NodeDto.CreateDate, Id = dto.NodeId, - Key = dto.NodeDto.UniqueId.Value, - CreatorId = dto.NodeDto.UserId.Value, - Level = dto.NodeDto.Level, - ParentId = dto.NodeDto.ParentId, - SortOrder = dto.NodeDto.SortOrder, + Key = dto.NodeDto.UniqueId.Value, Path = dto.NodeDto.Path }; - - if(dto.Master.HasValue) - template.MasterTemplateId = new Lazy(() => dto.Master.Value); + + if (childDefinitions.Any(x => x.ParentId == dto.NodeId)) + { + template.IsMasterTemplate = true; + } + + //TODO: Change this to ParentId: http://issues.umbraco.org/issue/U4-5846 + if(dto.NodeDto.ParentId > 0) + template.MasterTemplateId = new Lazy(() => dto.NodeDto.ParentId); //on initial construction we don't want to have dirty properties tracked // http://issues.umbraco.org/issue/U4-1946 @@ -54,13 +63,13 @@ namespace Umbraco.Core.Persistence.Factories var dto = new TemplateDto { Alias = entity.Alias, - Design = entity.Content, + Design = entity.Content ?? string.Empty, NodeDto = BuildNodeDto(entity) }; - if (entity.MasterTemplateId != null && entity.MasterTemplateId.Value != default(int)) + if (entity.MasterTemplateId != null && entity.MasterTemplateId.Value > 0) { - dto.Master = entity.MasterTemplateId.Value; + dto.NodeDto.ParentId = entity.MasterTemplateId.Value; } if (entity.HasIdentity) @@ -80,15 +89,13 @@ namespace Umbraco.Core.Persistence.Factories { CreateDate = entity.CreateDate, NodeId = entity.Id, - Level = short.Parse(entity.Level.ToString(CultureInfo.InvariantCulture)), + Level = 1, NodeObjectType = _nodeObjectTypeId, - ParentId = entity.ParentId, + ParentId = entity.MasterTemplateId.Value, Path = entity.Path, - SortOrder = entity.SortOrder, Text = entity.Name, Trashed = false, - UniqueId = entity.Key, - UserId = entity.CreatorId + UniqueId = entity.Key }; return nodeDto; diff --git a/src/Umbraco.Core/Persistence/Factories/UmbracoEntityFactory.cs b/src/Umbraco.Core/Persistence/Factories/UmbracoEntityFactory.cs index f33ae1af2f..056d554d17 100644 --- a/src/Umbraco.Core/Persistence/Factories/UmbracoEntityFactory.cs +++ b/src/Umbraco.Core/Persistence/Factories/UmbracoEntityFactory.cs @@ -9,7 +9,7 @@ using Umbraco.Core.Persistence.Repositories; namespace Umbraco.Core.Persistence.Factories { - internal class UmbracoEntityFactory : IEntityFactory + internal class UmbracoEntityFactory { internal void AddAdditionalData(UmbracoEntity entity, IDictionary originalEntityProperties) { diff --git a/src/Umbraco.Core/Persistence/Factories/UserFactory.cs b/src/Umbraco.Core/Persistence/Factories/UserFactory.cs index 305c630a71..f13f4e94b4 100644 --- a/src/Umbraco.Core/Persistence/Factories/UserFactory.cs +++ b/src/Umbraco.Core/Persistence/Factories/UserFactory.cs @@ -6,7 +6,7 @@ using Umbraco.Core.Models.Rdbms; namespace Umbraco.Core.Persistence.Factories { - internal class UserFactory : IEntityFactory + internal class UserFactory { private readonly IUserType _userType; diff --git a/src/Umbraco.Core/Persistence/Factories/UserSectionFactory.cs b/src/Umbraco.Core/Persistence/Factories/UserSectionFactory.cs index e8c7d2e7c1..0e6a17594f 100644 --- a/src/Umbraco.Core/Persistence/Factories/UserSectionFactory.cs +++ b/src/Umbraco.Core/Persistence/Factories/UserSectionFactory.cs @@ -7,7 +7,7 @@ using Umbraco.Core.Models.Rdbms; namespace Umbraco.Core.Persistence.Factories { - internal class UserSectionFactory : IEntityFactory, IEnumerable> + internal class UserSectionFactory { private readonly IUser _user; diff --git a/src/Umbraco.Core/Persistence/Factories/UserTypeFactory.cs b/src/Umbraco.Core/Persistence/Factories/UserTypeFactory.cs index ad81d2b584..b5718b7c3b 100644 --- a/src/Umbraco.Core/Persistence/Factories/UserTypeFactory.cs +++ b/src/Umbraco.Core/Persistence/Factories/UserTypeFactory.cs @@ -5,7 +5,7 @@ using Umbraco.Core.Models.Rdbms; namespace Umbraco.Core.Persistence.Factories { - internal class UserTypeFactory : IEntityFactory + internal class UserTypeFactory { #region Implementation of IEntityFactory diff --git a/src/Umbraco.Core/Persistence/FaultHandling/RetryPolicy.cs b/src/Umbraco.Core/Persistence/FaultHandling/RetryPolicy.cs index 382c639e79..2f8a37dc41 100644 --- a/src/Umbraco.Core/Persistence/FaultHandling/RetryPolicy.cs +++ b/src/Umbraco.Core/Persistence/FaultHandling/RetryPolicy.cs @@ -198,10 +198,7 @@ namespace Umbraco.Core.Persistence.FaultHandling protected virtual void OnRetrying(int retryCount, Exception lastError, TimeSpan delay) { if (this.Retrying != null) - { - LogHelper.Info(string.Format("Retrying - Count: {0}, Delay: {1}, Exception: {2}", - retryCount, delay.TotalMilliseconds, lastError.Message)); - + { this.Retrying(this, new RetryingEventArgs(retryCount, delay, lastError)); } } diff --git a/src/Umbraco.Core/Persistence/Mappers/MappingResolver.cs b/src/Umbraco.Core/Persistence/Mappers/MappingResolver.cs index 007ddbd014..ea44964219 100644 --- a/src/Umbraco.Core/Persistence/Mappers/MappingResolver.cs +++ b/src/Umbraco.Core/Persistence/Mappers/MappingResolver.cs @@ -12,9 +12,11 @@ namespace Umbraco.Core.Persistence.Mappers /// /// Constructor accepting a list of BaseMapper types that are attributed with the MapperFor attribute /// + /// + /// /// - public MappingResolver(Func> assignedMapperTypes) - : base(assignedMapperTypes) + public MappingResolver(IServiceProvider serviceProvider, ILogger logger, Func> assignedMapperTypes) + : base(serviceProvider, logger, assignedMapperTypes) { } diff --git a/src/Umbraco.Core/Persistence/Mappers/TemplateMapper.cs b/src/Umbraco.Core/Persistence/Mappers/TemplateMapper.cs index c498222fce..08a7de0777 100644 --- a/src/Umbraco.Core/Persistence/Mappers/TemplateMapper.cs +++ b/src/Umbraco.Core/Persistence/Mappers/TemplateMapper.cs @@ -38,8 +38,7 @@ namespace Umbraco.Core.Persistence.Mappers if(PropertyInfoCache.IsEmpty) { CacheMap(src => src.Id, dto => dto.NodeId); - - CacheMap(src => src.MasterTemplateId, dto => dto.Master); + CacheMap(src => src.MasterTemplateId, dto => dto.ParentId); CacheMap(src => src.Alias, dto => dto.Alias); CacheMap(src => src.Content, dto => dto.Design); } diff --git a/src/Umbraco.Core/Persistence/Migrations/Initial/BaseDataCreation.cs b/src/Umbraco.Core/Persistence/Migrations/Initial/BaseDataCreation.cs index b15f491587..a641a4055e 100644 --- a/src/Umbraco.Core/Persistence/Migrations/Initial/BaseDataCreation.cs +++ b/src/Umbraco.Core/Persistence/Migrations/Initial/BaseDataCreation.cs @@ -10,11 +10,13 @@ namespace Umbraco.Core.Persistence.Migrations.Initial internal class BaseDataCreation { private readonly Database _database; + private readonly ILogger _logger; - public BaseDataCreation(Database database) + public BaseDataCreation(Database database, ILogger logger) { _database = database; - } + _logger = logger; + } /// /// Initialize the base data creation by inserting the data foundation for umbraco @@ -23,7 +25,7 @@ namespace Umbraco.Core.Persistence.Migrations.Initial /// Name of the table to create base data for public void InitializeBaseData(string tableName) { - LogHelper.Info(string.Format("Creating data in table {0}", tableName)); + _logger.Info(string.Format("Creating data in table {0}", tableName)); if(tableName.Equals("umbracoNode")) { @@ -89,7 +91,7 @@ namespace Umbraco.Core.Persistence.Migrations.Initial CreateCmsTaskTypeData(); } - LogHelper.Info(string.Format("Done creating data in table {0}", tableName)); + _logger.Info(string.Format("Done creating data in table {0}", tableName)); } private void CreateUmbracNodeData() @@ -268,7 +270,8 @@ namespace Umbraco.Core.Persistence.Migrations.Initial private void CreateUmbracoRelationTypeData() { - _database.Insert("umbracoRelationType", "id", false, new RelationTypeDto { Id = 1, Alias = Constants.Conventions.RelationTypes.RelateDocumentOnCopyAlias, ChildObjectType = new Guid(Constants.ObjectTypes.Document), ParentObjectType = new Guid("C66BA18E-EAF3-4CFF-8A22-41B16D66A972"), Dual = true, Name = Constants.Conventions.RelationTypes.RelateDocumentOnCopyName }); + _database.Insert("umbracoRelationType", "id", false, new RelationTypeDto { Id = 1, Alias = Constants.Conventions.RelationTypes.RelateDocumentOnCopyAlias, ChildObjectType = new Guid(Constants.ObjectTypes.Document), ParentObjectType = new Guid(Constants.ObjectTypes.Document), Dual = true, Name = Constants.Conventions.RelationTypes.RelateDocumentOnCopyName }); + _database.Insert("umbracoRelationType", "id", false, new RelationTypeDto { Id = 2, Alias = Constants.Conventions.RelationTypes.RelateParentDocumentOnDeleteAlias, ChildObjectType = new Guid(Constants.ObjectTypes.Document), ParentObjectType = new Guid(Constants.ObjectTypes.Document), Dual = false, Name = Constants.Conventions.RelationTypes.RelateParentDocumentOnDeleteName }); } private void CreateCmsTaskTypeData() diff --git a/src/Umbraco.Core/Persistence/Migrations/Initial/DatabaseSchemaCreation.cs b/src/Umbraco.Core/Persistence/Migrations/Initial/DatabaseSchemaCreation.cs index 7b32b59564..8f75bbb189 100644 --- a/src/Umbraco.Core/Persistence/Migrations/Initial/DatabaseSchemaCreation.cs +++ b/src/Umbraco.Core/Persistence/Migrations/Initial/DatabaseSchemaCreation.cs @@ -14,8 +14,27 @@ namespace Umbraco.Core.Persistence.Migrations.Initial /// internal class DatabaseSchemaCreation { + /// + /// Constructor + /// + /// + /// + /// + public DatabaseSchemaCreation(Database database, ILogger logger, ISqlSyntaxProvider sqlSyntaxProvider) + { + _database = database; + _logger = logger; + _sqlSyntaxProvider = sqlSyntaxProvider; + _schemaHelper = new DatabaseSchemaHelper(database, logger, sqlSyntaxProvider); + } + #region Private Members + + private readonly DatabaseSchemaHelper _schemaHelper; private readonly Database _database; + private readonly ILogger _logger; + private readonly ISqlSyntaxProvider _sqlSyntaxProvider; + private static readonly Dictionary OrderedTables = new Dictionary { {0, typeof (NodeDto)}, @@ -68,7 +87,7 @@ namespace Umbraco.Core.Persistence.Migrations.Initial /// internal void UninstallDatabaseSchema() { - LogHelper.Info("Start UninstallDatabaseSchema"); + _logger.Info("Start UninstallDatabaseSchema"); foreach (var item in OrderedTables.OrderByDescending(x => x.Key)) { @@ -76,28 +95,25 @@ namespace Umbraco.Core.Persistence.Migrations.Initial string tableName = tableNameAttribute == null ? item.Value.Name : tableNameAttribute.Value; - LogHelper.Info("Uninstall" + tableName); + _logger.Info("Uninstall" + tableName); try { - if (_database.TableExist(tableName)) + if (_schemaHelper.TableExist(tableName)) { - _database.DropTable(tableName); + _schemaHelper.DropTable(tableName); } } catch (Exception ex) { //swallow this for now, not sure how best to handle this with diff databases... though this is internal // and only used for unit tests. If this fails its because the table doesn't exist... generally! - LogHelper.Error("Could not drop table " + tableName, ex); + _logger.Error("Could not drop table " + tableName, ex); } } } - public DatabaseSchemaCreation(Database database) - { - _database = database; - } + /// /// Initialize the database by creating the umbraco db schema @@ -111,7 +127,7 @@ namespace Umbraco.Core.Persistence.Migrations.Initial { foreach (var item in OrderedTables.OrderBy(x => x.Key)) { - _database.CreateTable(false, item.Value); + _schemaHelper.CreateTable(false, item.Value); } } @@ -126,7 +142,7 @@ namespace Umbraco.Core.Persistence.Migrations.Initial var result = new DatabaseSchemaResult(); //get the db index defs - result.DbIndexDefinitions = SqlSyntaxContext.SqlSyntaxProvider.GetDefinedIndexes(_database) + result.DbIndexDefinitions = _sqlSyntaxProvider.GetDefinedIndexes(_database) .Select(x => new DbIndexDefinition() { TableName = x.Item1, @@ -157,11 +173,11 @@ namespace Umbraco.Core.Persistence.Migrations.Initial //MySql doesn't conform to the "normal" naming of constraints, so there is currently no point in doing these checks. //TODO: At a later point we do other checks for MySql, but ideally it should be necessary to do special checks for different providers. // ALso note that to get the constraints for MySql we have to open a connection which we currently have not. - if (SqlSyntaxContext.SqlSyntaxProvider is MySqlSyntaxProvider) + if (_sqlSyntaxProvider is MySqlSyntaxProvider) return; //Check constraints in configured database against constraints in schema - var constraintsInDatabase = SqlSyntaxContext.SqlSyntaxProvider.GetConstraintsPerColumn(_database).DistinctBy(x => x.Item3).ToList(); + var constraintsInDatabase = _sqlSyntaxProvider.GetConstraintsPerColumn(_database).DistinctBy(x => x.Item3).ToList(); var foreignKeysInDatabase = constraintsInDatabase.Where(x => x.Item3.InvariantStartsWith("FK_")).Select(x => x.Item3).ToList(); var primaryKeysInDatabase = constraintsInDatabase.Where(x => x.Item3.InvariantStartsWith("PK_")).Select(x => x.Item3).ToList(); var indexesInDatabase = constraintsInDatabase.Where(x => x.Item3.InvariantStartsWith("IX_")).Select(x => x.Item3).ToList(); @@ -244,7 +260,7 @@ namespace Umbraco.Core.Persistence.Migrations.Initial private void ValidateDbColumns(DatabaseSchemaResult result) { //Check columns in configured database against columns in schema - var columnsInDatabase = SqlSyntaxContext.SqlSyntaxProvider.GetColumnsInSchema(_database); + var columnsInDatabase = _sqlSyntaxProvider.GetColumnsInSchema(_database); var columnsPerTableInDatabase = columnsInDatabase.Select(x => string.Concat(x.TableName, ",", x.ColumnName)).ToList(); var columnsPerTableInSchema = result.TableDefinitions.SelectMany(x => x.Columns.Select(y => string.Concat(y.TableName, ",", y.Name))).ToList(); //Add valid and invalid column differences to the result object @@ -266,7 +282,7 @@ namespace Umbraco.Core.Persistence.Migrations.Initial private void ValidateDbTables(DatabaseSchemaResult result) { //Check tables in configured database against tables in schema - var tablesInDatabase = SqlSyntaxContext.SqlSyntaxProvider.GetTablesInSchema(_database).ToList(); + var tablesInDatabase = _sqlSyntaxProvider.GetTablesInSchema(_database).ToList(); var tablesInSchema = result.TableDefinitions.Select(x => x.Name).ToList(); //Add valid and invalid table differences to the result object var validTableDifferences = tablesInDatabase.Intersect(tablesInSchema, StringComparer.InvariantCultureIgnoreCase); diff --git a/src/Umbraco.Core/Persistence/Migrations/MigrationBase.cs b/src/Umbraco.Core/Persistence/Migrations/MigrationBase.cs index 642a920319..e37d001fea 100644 --- a/src/Umbraco.Core/Persistence/Migrations/MigrationBase.cs +++ b/src/Umbraco.Core/Persistence/Migrations/MigrationBase.cs @@ -1,4 +1,6 @@ -using Umbraco.Core.Persistence.Migrations.Syntax.Alter; +using System; +using Umbraco.Core.Logging; +using Umbraco.Core.Persistence.Migrations.Syntax.Alter; using Umbraco.Core.Persistence.Migrations.Syntax.Create; using Umbraco.Core.Persistence.Migrations.Syntax.Delete; using Umbraco.Core.Persistence.Migrations.Syntax.Execute; @@ -6,11 +8,27 @@ using Umbraco.Core.Persistence.Migrations.Syntax.IfDatabase; using Umbraco.Core.Persistence.Migrations.Syntax.Insert; using Umbraco.Core.Persistence.Migrations.Syntax.Rename; using Umbraco.Core.Persistence.Migrations.Syntax.Update; +using Umbraco.Core.Persistence.SqlSyntax; namespace Umbraco.Core.Persistence.Migrations { public abstract class MigrationBase : IMigration { + public ISqlSyntaxProvider SqlSyntax { get; private set; } + public ILogger Logger { get; private set; } + + [Obsolete("Use the other constructor specifying all dependencies instead")] + protected MigrationBase() + : this(SqlSyntaxContext.SqlSyntaxProvider, LoggerResolver.Current.Logger) + { + } + + protected MigrationBase(ISqlSyntaxProvider sqlSyntax, ILogger logger) + { + SqlSyntax = sqlSyntax; + Logger = logger; + } + internal IMigrationContext Context; public abstract void Up(); @@ -35,12 +53,12 @@ namespace Umbraco.Core.Persistence.Migrations public ICreateBuilder Create { - get { return new CreateBuilder(Context); } + get { return new CreateBuilder(Context, SqlSyntax); } } public IDeleteBuilder Delete { - get { return new DeleteBuilder(Context); } + get { return new DeleteBuilder(Context, SqlSyntax); } } public IExecuteBuilder Execute diff --git a/src/Umbraco.Core/Persistence/Migrations/MigrationContext.cs b/src/Umbraco.Core/Persistence/Migrations/MigrationContext.cs index e173bccc6d..07fc3db387 100644 --- a/src/Umbraco.Core/Persistence/Migrations/MigrationContext.cs +++ b/src/Umbraco.Core/Persistence/Migrations/MigrationContext.cs @@ -1,15 +1,17 @@ using System.Collections.Generic; using System.Collections.ObjectModel; +using Umbraco.Core.Logging; namespace Umbraco.Core.Persistence.Migrations { internal class MigrationContext : IMigrationContext { - public MigrationContext(DatabaseProviders databaseProvider, Database database) + public MigrationContext(DatabaseProviders databaseProvider, Database database, ILogger logger) { Expressions = new Collection(); CurrentDatabaseProvider = databaseProvider; Database = database; + Logger = logger; } public ICollection Expressions { get; set; } @@ -17,5 +19,7 @@ namespace Umbraco.Core.Persistence.Migrations public DatabaseProviders CurrentDatabaseProvider { get; private set; } public Database Database { get; private set; } + + public ILogger Logger { get; private set; } } } \ No newline at end of file diff --git a/src/Umbraco.Core/Persistence/Migrations/MigrationExpressionBase.cs b/src/Umbraco.Core/Persistence/Migrations/MigrationExpressionBase.cs index fc7b4f3b58..e7535e78d4 100644 --- a/src/Umbraco.Core/Persistence/Migrations/MigrationExpressionBase.cs +++ b/src/Umbraco.Core/Persistence/Migrations/MigrationExpressionBase.cs @@ -1,20 +1,38 @@ -using System.Linq; +using System; +using System.Linq; +using Umbraco.Core.Logging; +using Umbraco.Core.Persistence.SqlSyntax; namespace Umbraco.Core.Persistence.Migrations { public abstract class MigrationExpressionBase : IMigrationExpression { + [Obsolete("Use the other constructors specifying an ISqlSyntaxProvider instead")] protected MigrationExpressionBase() + : this(SqlSyntaxContext.SqlSyntaxProvider) { } + [Obsolete("Use the other constructors specifying an ISqlSyntaxProvider instead")] protected MigrationExpressionBase(DatabaseProviders current, DatabaseProviders[] databaseProviders) + : this(current, databaseProviders, SqlSyntaxContext.SqlSyntaxProvider) + { + } + + protected MigrationExpressionBase(ISqlSyntaxProvider sqlSyntax) + { + SqlSyntax = sqlSyntax; + } + + protected MigrationExpressionBase(DatabaseProviders current, DatabaseProviders[] databaseProviders, ISqlSyntaxProvider sqlSyntax) { SupportedDatabaseProviders = databaseProviders; + SqlSyntax = sqlSyntax; CurrentDatabaseProvider = current; } public virtual DatabaseProviders[] SupportedDatabaseProviders { get; private set; } + public ISqlSyntaxProvider SqlSyntax { get; private set; } public virtual DatabaseProviders CurrentDatabaseProvider { get; private set; } public bool IsExpressionSupported() diff --git a/src/Umbraco.Core/Persistence/Migrations/MigrationResolver.cs b/src/Umbraco.Core/Persistence/Migrations/MigrationResolver.cs index 3d28e99c56..69391c7485 100644 --- a/src/Umbraco.Core/Persistence/Migrations/MigrationResolver.cs +++ b/src/Umbraco.Core/Persistence/Migrations/MigrationResolver.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using Umbraco.Core.Logging; using Umbraco.Core.ObjectResolution; namespace Umbraco.Core.Persistence.Migrations @@ -9,16 +10,17 @@ namespace Umbraco.Core.Persistence.Migrations /// internal class MigrationResolver : LazyManyObjectsResolverBase { - - /// - /// Constructor - /// - /// - /// - /// Use transient objects as we don't want these as singletons and take up memory that is not required - /// - public MigrationResolver(Func> migrations) - : base(migrations, ObjectLifetimeScope.Transient) + /// + /// Constructor + /// + /// + /// + /// + /// + /// Use transient objects as we don't want these as singletons and take up memory that is not required + /// + public MigrationResolver(IServiceProvider serviceProvider, ILogger logger, Func> migrations) + : base(serviceProvider, logger, migrations, ObjectLifetimeScope.Transient) { } diff --git a/src/Umbraco.Core/Persistence/Migrations/MigrationRunner.cs b/src/Umbraco.Core/Persistence/Migrations/MigrationRunner.cs index 6c077dd987..beacd2014d 100644 --- a/src/Umbraco.Core/Persistence/Migrations/MigrationRunner.cs +++ b/src/Umbraco.Core/Persistence/Migrations/MigrationRunner.cs @@ -13,12 +13,25 @@ namespace Umbraco.Core.Persistence.Migrations /// public class MigrationRunner { + private readonly ILogger _logger; private readonly Version _currentVersion; private readonly Version _targetVersion; private readonly string _productName; + [Obsolete("Use the ctor that specifies all dependencies instead")] public MigrationRunner(Version currentVersion, Version targetVersion, string productName) + : this(LoggerResolver.Current.Logger, currentVersion, targetVersion, productName) { + } + + public MigrationRunner(ILogger logger, Version currentVersion, Version targetVersion, string productName) + { + if (logger == null) throw new ArgumentNullException("logger"); + if (currentVersion == null) throw new ArgumentNullException("currentVersion"); + if (targetVersion == null) throw new ArgumentNullException("targetVersion"); + Mandate.ParameterNotNullOrEmpty(productName, "productName"); + + _logger = logger; _currentVersion = currentVersion; _targetVersion = targetVersion; _productName = productName; @@ -44,7 +57,7 @@ namespace Umbraco.Core.Persistence.Migrations /// True if migrations were applied, otherwise False public virtual bool Execute(Database database, DatabaseProviders databaseProvider, bool isUpgrade = true) { - LogHelper.Info("Initializing database migrations"); + _logger.Info("Initializing database migrations"); var foundMigrations = FindMigrations(); @@ -142,7 +155,7 @@ namespace Umbraco.Core.Persistence.Migrations internal MigrationContext InitializeMigrations(List migrations, Database database, DatabaseProviders databaseProvider, bool isUpgrade = true) { //Loop through migrations to generate sql - var context = new MigrationContext(databaseProvider, database); + var context = new MigrationContext(databaseProvider, database, _logger); foreach (var migration in migrations) { @@ -152,12 +165,12 @@ namespace Umbraco.Core.Persistence.Migrations if (isUpgrade) { baseMigration.GetUpExpressions(context); - LogHelper.Info(string.Format("Added UPGRADE migration '{0}' to context", baseMigration.GetType().Name)); + _logger.Info(string.Format("Added UPGRADE migration '{0}' to context", baseMigration.GetType().Name)); } else { baseMigration.GetDownExpressions(context); - LogHelper.Info(string.Format("Added DOWNGRADE migration '{0}' to context", baseMigration.GetType().Name)); + _logger.Info(string.Format("Added DOWNGRADE migration '{0}' to context", baseMigration.GetType().Name)); } } else @@ -166,12 +179,12 @@ namespace Umbraco.Core.Persistence.Migrations if (isUpgrade) { migration.Up(); - LogHelper.Info(string.Format("Added UPGRADE migration '{0}' to context", migration.GetType().Name)); + _logger.Info(string.Format("Added UPGRADE migration '{0}' to context", migration.GetType().Name)); } else { migration.Down(); - LogHelper.Info(string.Format("Added DOWNGRADE migration '{0}' to context", migration.GetType().Name)); + _logger.Info(string.Format("Added DOWNGRADE migration '{0}' to context", migration.GetType().Name)); } } } @@ -194,7 +207,7 @@ namespace Umbraco.Core.Persistence.Migrations continue; } - LogHelper.Info("Executing sql statement " + i + ": " + sql); + _logger.Info("Executing sql statement " + i + ": " + sql); database.Execute(sql); i++; } diff --git a/src/Umbraco.Core/Persistence/Migrations/Syntax/Alter/Expressions/AlterColumnExpression.cs b/src/Umbraco.Core/Persistence/Migrations/Syntax/Alter/Expressions/AlterColumnExpression.cs index 3119c55df6..43be956440 100644 --- a/src/Umbraco.Core/Persistence/Migrations/Syntax/Alter/Expressions/AlterColumnExpression.cs +++ b/src/Umbraco.Core/Persistence/Migrations/Syntax/Alter/Expressions/AlterColumnExpression.cs @@ -1,20 +1,37 @@ -using Umbraco.Core.Persistence.DatabaseModelDefinitions; +using System; +using Umbraco.Core.Persistence.DatabaseModelDefinitions; using Umbraco.Core.Persistence.SqlSyntax; namespace Umbraco.Core.Persistence.Migrations.Syntax.Alter.Expressions { public class AlterColumnExpression : MigrationExpressionBase { - public AlterColumnExpression() + public AlterColumnExpression(ISqlSyntaxProvider sqlSyntax) + : base(sqlSyntax) { Column = new ColumnDefinition() { ModificationType = ModificationType.Alter }; } - public AlterColumnExpression(DatabaseProviders current, DatabaseProviders[] databaseProviders) : base(current, databaseProviders) + public AlterColumnExpression(DatabaseProviders current, DatabaseProviders[] databaseProviders, ISqlSyntaxProvider sqlSyntax) + : base(current, databaseProviders, sqlSyntax) { Column = new ColumnDefinition() { ModificationType = ModificationType.Alter }; } + [Obsolete("Use the constructor specifying an ISqlSyntaxProvider instead")] + public AlterColumnExpression() + : this(SqlSyntaxContext.SqlSyntaxProvider) + { + } + + [Obsolete("Use the constructor specifying an ISqlSyntaxProvider instead")] + public AlterColumnExpression(DatabaseProviders current, DatabaseProviders[] databaseProviders) + : this(current, databaseProviders, SqlSyntaxContext.SqlSyntaxProvider) + { + } + + + public virtual string SchemaName { get; set; } public virtual string TableName { get; set; } public virtual ColumnDefinition Column { get; set; } @@ -25,7 +42,7 @@ namespace Umbraco.Core.Persistence.Migrations.Syntax.Alter.Expressions // SqlSyntaxContext.SqlSyntaxProvider.GetQuotedColumnName(Column.Name), // SqlSyntaxContext.SqlSyntaxProvider.Format(Column)); - return string.Format(SqlSyntaxContext.SqlSyntaxProvider.AlterColumn, + return string.Format(SqlSyntaxContext.SqlSyntaxProvider.AlterColumn, SqlSyntaxContext.SqlSyntaxProvider.GetQuotedTableName(TableName), SqlSyntaxContext.SqlSyntaxProvider.Format(Column)); diff --git a/src/Umbraco.Core/Persistence/Migrations/Syntax/Create/CreateBuilder.cs b/src/Umbraco.Core/Persistence/Migrations/Syntax/Create/CreateBuilder.cs index 590995188f..4f2666d032 100644 --- a/src/Umbraco.Core/Persistence/Migrations/Syntax/Create/CreateBuilder.cs +++ b/src/Umbraco.Core/Persistence/Migrations/Syntax/Create/CreateBuilder.cs @@ -1,4 +1,5 @@ -using Umbraco.Core.Persistence.DatabaseModelDefinitions; +using System; +using Umbraco.Core.Persistence.DatabaseModelDefinitions; using Umbraco.Core.Persistence.Migrations.Syntax.Create.Column; using Umbraco.Core.Persistence.Migrations.Syntax.Create.Constraint; using Umbraco.Core.Persistence.Migrations.Syntax.Create.Expressions; @@ -6,20 +7,29 @@ using Umbraco.Core.Persistence.Migrations.Syntax.Create.ForeignKey; using Umbraco.Core.Persistence.Migrations.Syntax.Create.Index; using Umbraco.Core.Persistence.Migrations.Syntax.Create.Table; using Umbraco.Core.Persistence.Migrations.Syntax.Expressions; +using Umbraco.Core.Persistence.SqlSyntax; namespace Umbraco.Core.Persistence.Migrations.Syntax.Create { public class CreateBuilder : ICreateBuilder { private readonly IMigrationContext _context; + private readonly ISqlSyntaxProvider _sqlSyntax; private readonly DatabaseProviders[] _databaseProviders; - public CreateBuilder(IMigrationContext context, params DatabaseProviders[] databaseProviders) + public CreateBuilder(IMigrationContext context, ISqlSyntaxProvider sqlSyntax, params DatabaseProviders[] databaseProviders) { _context = context; + _sqlSyntax = sqlSyntax; _databaseProviders = databaseProviders; } + [Obsolete("Use alternate ctor specifying ISqlSyntaxProvider instead")] + public CreateBuilder(IMigrationContext context, params DatabaseProviders[] databaseProviders) + :this(context, SqlSyntaxContext.SqlSyntaxProvider, databaseProviders) + { + } + public ICreateTableWithColumnSyntax Table(string tableName) { var expression = new CreateTableExpression { TableName = tableName }; @@ -56,14 +66,14 @@ namespace Umbraco.Core.Persistence.Migrations.Syntax.Create public ICreateIndexForTableSyntax Index() { - var expression = new CreateIndexExpression(); + var expression = new CreateIndexExpression(_sqlSyntax); _context.Expressions.Add(expression); return new CreateIndexBuilder(expression); } public ICreateIndexForTableSyntax Index(string indexName) { - var expression = new CreateIndexExpression { Index = { Name = indexName } }; + var expression = new CreateIndexExpression(_sqlSyntax) { Index = { Name = indexName } }; _context.Expressions.Add(expression); return new CreateIndexBuilder(expression); } diff --git a/src/Umbraco.Core/Persistence/Migrations/Syntax/Delete/DeleteBuilder.cs b/src/Umbraco.Core/Persistence/Migrations/Syntax/Delete/DeleteBuilder.cs index 4865182134..f70de5b548 100644 --- a/src/Umbraco.Core/Persistence/Migrations/Syntax/Delete/DeleteBuilder.cs +++ b/src/Umbraco.Core/Persistence/Migrations/Syntax/Delete/DeleteBuilder.cs @@ -1,24 +1,34 @@ -using Umbraco.Core.Persistence.DatabaseModelDefinitions; +using System; +using Umbraco.Core.Persistence.DatabaseModelDefinitions; using Umbraco.Core.Persistence.Migrations.Syntax.Delete.Column; using Umbraco.Core.Persistence.Migrations.Syntax.Delete.Constraint; using Umbraco.Core.Persistence.Migrations.Syntax.Delete.DefaultConstraint; using Umbraco.Core.Persistence.Migrations.Syntax.Delete.Expressions; using Umbraco.Core.Persistence.Migrations.Syntax.Delete.ForeignKey; using Umbraco.Core.Persistence.Migrations.Syntax.Delete.Index; +using Umbraco.Core.Persistence.SqlSyntax; namespace Umbraco.Core.Persistence.Migrations.Syntax.Delete { public class DeleteBuilder : IDeleteBuilder { private readonly IMigrationContext _context; + private readonly ISqlSyntaxProvider _sqlSyntax; private readonly DatabaseProviders[] _databaseProviders; - public DeleteBuilder(IMigrationContext context, params DatabaseProviders[] databaseProviders) + public DeleteBuilder(IMigrationContext context, ISqlSyntaxProvider sqlSyntax, params DatabaseProviders[] databaseProviders) { _context = context; + _sqlSyntax = sqlSyntax; _databaseProviders = databaseProviders; } + [Obsolete("Use the other constructor specifying an ISqlSyntaxProvider instead")] + public DeleteBuilder(IMigrationContext context, params DatabaseProviders[] databaseProviders) + : this(context, SqlSyntaxContext.SqlSyntaxProvider, databaseProviders) + { + } + public void Table(string tableName) { var expression = new DeleteTableExpression { TableName = tableName }; @@ -37,8 +47,8 @@ namespace Umbraco.Core.Persistence.Migrations.Syntax.Delete public IDeleteForeignKeyFromTableSyntax ForeignKey() { var expression = _databaseProviders == null - ? new DeleteForeignKeyExpression() - : new DeleteForeignKeyExpression(_context.CurrentDatabaseProvider, _databaseProviders); + ? new DeleteForeignKeyExpression(_sqlSyntax) + : new DeleteForeignKeyExpression(_context.CurrentDatabaseProvider, _databaseProviders, _sqlSyntax); _context.Expressions.Add(expression); return new DeleteForeignKeyBuilder(expression); } @@ -46,8 +56,8 @@ namespace Umbraco.Core.Persistence.Migrations.Syntax.Delete public IDeleteForeignKeyOnTableSyntax ForeignKey(string foreignKeyName) { var expression = _databaseProviders == null - ? new DeleteForeignKeyExpression { ForeignKey = { Name = foreignKeyName } } - : new DeleteForeignKeyExpression(_context.CurrentDatabaseProvider, _databaseProviders) { ForeignKey = { Name = foreignKeyName } }; + ? new DeleteForeignKeyExpression(_sqlSyntax) { ForeignKey = { Name = foreignKeyName } } + : new DeleteForeignKeyExpression(_context.CurrentDatabaseProvider, _databaseProviders, _sqlSyntax) { ForeignKey = { Name = foreignKeyName } }; _context.Expressions.Add(expression); return new DeleteForeignKeyBuilder(expression); } diff --git a/src/Umbraco.Core/Persistence/Migrations/Syntax/Delete/Expressions/DeleteForeignKeyExpression.cs b/src/Umbraco.Core/Persistence/Migrations/Syntax/Delete/Expressions/DeleteForeignKeyExpression.cs index 76a6a35db3..34e3bd65c5 100644 --- a/src/Umbraco.Core/Persistence/Migrations/Syntax/Delete/Expressions/DeleteForeignKeyExpression.cs +++ b/src/Umbraco.Core/Persistence/Migrations/Syntax/Delete/Expressions/DeleteForeignKeyExpression.cs @@ -1,5 +1,6 @@ using System; using System.Linq; +using Umbraco.Core.Logging; using Umbraco.Core.Persistence.DatabaseModelDefinitions; using Umbraco.Core.Persistence.SqlSyntax; @@ -7,17 +8,31 @@ namespace Umbraco.Core.Persistence.Migrations.Syntax.Delete.Expressions { public class DeleteForeignKeyExpression : MigrationExpressionBase { + [Obsolete("Use the other constructors specifying an ILogger instead")] public DeleteForeignKeyExpression() { ForeignKey = new ForeignKeyDefinition(); } + [Obsolete("Use the other constructors specifying an ILogger instead")] public DeleteForeignKeyExpression(DatabaseProviders current, DatabaseProviders[] databaseProviders) : base(current, databaseProviders) { ForeignKey = new ForeignKeyDefinition(); } + public DeleteForeignKeyExpression(ISqlSyntaxProvider sqlSyntax) + : base(sqlSyntax) + { + ForeignKey = new ForeignKeyDefinition(); + } + + public DeleteForeignKeyExpression(DatabaseProviders current, DatabaseProviders[] databaseProviders, ISqlSyntaxProvider sqlSyntax) + : base(current, databaseProviders, sqlSyntax) + { + ForeignKey = new ForeignKeyDefinition(); + } + public virtual ForeignKeyDefinition ForeignKey { get; set; } public override string ToString() @@ -34,10 +49,10 @@ namespace Umbraco.Core.Persistence.Migrations.Syntax.Delete.Expressions if (string.IsNullOrEmpty(ForeignKey.Name)) ForeignKey.Name = string.Format("{0}_ibfk_1", ForeignKey.ForeignTable.ToLower()); - return string.Format(SqlSyntaxContext.SqlSyntaxProvider.DeleteConstraint, - SqlSyntaxContext.SqlSyntaxProvider.GetQuotedTableName(ForeignKey.ForeignTable), + return string.Format(SqlSyntax.DeleteConstraint, + SqlSyntax.GetQuotedTableName(ForeignKey.ForeignTable), "FOREIGN KEY", - SqlSyntaxContext.SqlSyntaxProvider.GetQuotedName(ForeignKey.Name)); + SqlSyntax.GetQuotedName(ForeignKey.Name)); } if (string.IsNullOrEmpty(ForeignKey.Name)) @@ -45,9 +60,9 @@ namespace Umbraco.Core.Persistence.Migrations.Syntax.Delete.Expressions ForeignKey.Name = string.Format("FK_{0}_{1}_{2}", ForeignKey.ForeignTable, ForeignKey.PrimaryTable, ForeignKey.PrimaryColumns.First()); } - return string.Format(SqlSyntaxContext.SqlSyntaxProvider.DeleteConstraint, - SqlSyntaxContext.SqlSyntaxProvider.GetQuotedTableName(ForeignKey.ForeignTable), - SqlSyntaxContext.SqlSyntaxProvider.GetQuotedName(ForeignKey.Name)); + return string.Format(SqlSyntax.DeleteConstraint, + SqlSyntax.GetQuotedTableName(ForeignKey.ForeignTable), + SqlSyntax.GetQuotedName(ForeignKey.Name)); } } } \ No newline at end of file diff --git a/src/Umbraco.Core/Persistence/Migrations/Syntax/Expressions/CreateIndexExpression.cs b/src/Umbraco.Core/Persistence/Migrations/Syntax/Expressions/CreateIndexExpression.cs index aa33263346..eadb30cd9e 100644 --- a/src/Umbraco.Core/Persistence/Migrations/Syntax/Expressions/CreateIndexExpression.cs +++ b/src/Umbraco.Core/Persistence/Migrations/Syntax/Expressions/CreateIndexExpression.cs @@ -1,25 +1,41 @@ -using Umbraco.Core.Persistence.DatabaseModelDefinitions; +using System; +using Umbraco.Core.Persistence.DatabaseModelDefinitions; using Umbraco.Core.Persistence.SqlSyntax; namespace Umbraco.Core.Persistence.Migrations.Syntax.Expressions { public class CreateIndexExpression : MigrationExpressionBase { - public CreateIndexExpression() + public CreateIndexExpression(ISqlSyntaxProvider sqlSyntax) + : base(sqlSyntax) + { + Index = new IndexDefinition(); + } + + public CreateIndexExpression(DatabaseProviders current, DatabaseProviders[] databaseProviders, ISqlSyntaxProvider sqlSyntax) + : base(current, databaseProviders, sqlSyntax) { Index = new IndexDefinition(); } - public CreateIndexExpression(DatabaseProviders current, DatabaseProviders[] databaseProviders) : base(current, databaseProviders) + [Obsolete("Use alternate ctor specifying ISqlSyntaxProvider instead")] + public CreateIndexExpression() + : this(SqlSyntaxContext.SqlSyntaxProvider) + { + + } + + [Obsolete("Use alternate ctor specifying ISqlSyntaxProvider instead")] + public CreateIndexExpression(DatabaseProviders current, DatabaseProviders[] databaseProviders) + : this(current, databaseProviders, SqlSyntaxContext.SqlSyntaxProvider) { - Index = new IndexDefinition(); } public virtual IndexDefinition Index { get; set; } public override string ToString() { - return SqlSyntaxContext.SqlSyntaxProvider.Format(Index); + return SqlSyntax.Format(Index); } } } \ No newline at end of file diff --git a/src/Umbraco.Core/Persistence/Migrations/Syntax/Insert/Expressions/InsertDataExpression.cs b/src/Umbraco.Core/Persistence/Migrations/Syntax/Insert/Expressions/InsertDataExpression.cs index dcc58c60bc..b9f076ac7f 100644 --- a/src/Umbraco.Core/Persistence/Migrations/Syntax/Insert/Expressions/InsertDataExpression.cs +++ b/src/Umbraco.Core/Persistence/Migrations/Syntax/Insert/Expressions/InsertDataExpression.cs @@ -1,4 +1,5 @@ -using System.Collections.Generic; +using System; +using System.Collections.Generic; using Umbraco.Core.Persistence.DatabaseModelDefinitions; using Umbraco.Core.Persistence.SqlSyntax; @@ -43,7 +44,7 @@ namespace Umbraco.Core.Persistence.Migrations.Syntax.Insert.Expressions foreach (var keyVal in item) { cols += keyVal.Key + ","; - vals += keyVal.Value + ","; + vals += GetQuotedValue(keyVal.Value) + ","; } cols = cols.TrimEnd(','); vals = vals.TrimEnd(','); @@ -58,5 +59,29 @@ namespace Umbraco.Core.Persistence.Migrations.Syntax.Insert.Expressions return string.Join(",", insertItems); } + + private string GetQuotedValue(object val) + { + var type = val.GetType(); + switch (Type.GetTypeCode(type)) + { + case TypeCode.Boolean: + return ((bool) val) ? "1" : "0"; + case TypeCode.Single: + case TypeCode.Double: + case TypeCode.Decimal: + case TypeCode.SByte: + case TypeCode.Int16: + case TypeCode.Int32: + case TypeCode.Int64: + case TypeCode.Byte: + case TypeCode.UInt16: + case TypeCode.UInt32: + case TypeCode.UInt64: + return val.ToString(); + default: + return SqlSyntaxContext.SqlSyntaxProvider.GetQuotedValue(val.ToString()); + } + } } } \ No newline at end of file diff --git a/src/Umbraco.Core/Persistence/Migrations/Upgrades/TargetVersionFourNineZero/RemoveUmbracoAppConstraints.cs b/src/Umbraco.Core/Persistence/Migrations/Upgrades/TargetVersionFourNineZero/RemoveUmbracoAppConstraints.cs index eac7ef7c9a..38cc00e48e 100644 --- a/src/Umbraco.Core/Persistence/Migrations/Upgrades/TargetVersionFourNineZero/RemoveUmbracoAppConstraints.cs +++ b/src/Umbraco.Core/Persistence/Migrations/Upgrades/TargetVersionFourNineZero/RemoveUmbracoAppConstraints.cs @@ -21,7 +21,7 @@ namespace Umbraco.Core.Persistence.Migrations.Upgrades.TargetVersionFourNineZero else { //These are the old aliases, before removing them, check they exist - var constraints = SqlSyntaxContext.SqlSyntaxProvider.GetConstraintsPerColumn(Context.Database).Distinct().ToArray(); + var constraints = SqlSyntax.GetConstraintsPerColumn(Context.Database).Distinct().ToArray(); if (constraints.Any(x => x.Item1.InvariantEquals("umbracoUser2app") && x.Item3.InvariantEquals("FK_umbracoUser2app_umbracoApp"))) { diff --git a/src/Umbraco.Core/Persistence/Migrations/Upgrades/TargetVersionSeven/AddIndexToCmsMacroPropertyTable.cs b/src/Umbraco.Core/Persistence/Migrations/Upgrades/TargetVersionSeven/AddIndexToCmsMacroPropertyTable.cs index 20480ad534..96c902884c 100644 --- a/src/Umbraco.Core/Persistence/Migrations/Upgrades/TargetVersionSeven/AddIndexToCmsMacroPropertyTable.cs +++ b/src/Umbraco.Core/Persistence/Migrations/Upgrades/TargetVersionSeven/AddIndexToCmsMacroPropertyTable.cs @@ -1,6 +1,7 @@ using System; using System.Linq; using Umbraco.Core.Configuration; +using Umbraco.Core.Logging; using Umbraco.Core.Persistence.DatabaseModelDefinitions; using Umbraco.Core.Persistence.SqlSyntax; @@ -14,7 +15,8 @@ namespace Umbraco.Core.Persistence.Migrations.Upgrades.TargetVersionSeven { private readonly bool _skipIndexCheck; - internal AddIndexToCmsMacroPropertyTable(bool skipIndexCheck) + internal AddIndexToCmsMacroPropertyTable(bool skipIndexCheck, ISqlSyntaxProvider sqlSyntax, ILogger logger) + : base(sqlSyntax, logger) { _skipIndexCheck = skipIndexCheck; } @@ -26,7 +28,7 @@ namespace Umbraco.Core.Persistence.Migrations.Upgrades.TargetVersionSeven public override void Up() { - var dbIndexes = _skipIndexCheck ? new DbIndexDefinition[]{} : SqlSyntaxContext.SqlSyntaxProvider.GetDefinedIndexes(Context.Database) + var dbIndexes = _skipIndexCheck ? new DbIndexDefinition[]{} : SqlSyntax.GetDefinedIndexes(Context.Database) .Select(x => new DbIndexDefinition() { TableName = x.Item1, diff --git a/src/Umbraco.Core/Persistence/Migrations/Upgrades/TargetVersionSeven/AddIndexToCmsMacroTable.cs b/src/Umbraco.Core/Persistence/Migrations/Upgrades/TargetVersionSeven/AddIndexToCmsMacroTable.cs index 1be642b9d1..704d09dd15 100644 --- a/src/Umbraco.Core/Persistence/Migrations/Upgrades/TargetVersionSeven/AddIndexToCmsMacroTable.cs +++ b/src/Umbraco.Core/Persistence/Migrations/Upgrades/TargetVersionSeven/AddIndexToCmsMacroTable.cs @@ -2,6 +2,7 @@ using System.CodeDom; using System.Linq; using Umbraco.Core.Configuration; +using Umbraco.Core.Logging; using Umbraco.Core.Persistence.DatabaseModelDefinitions; using Umbraco.Core.Persistence.SqlSyntax; @@ -15,7 +16,8 @@ namespace Umbraco.Core.Persistence.Migrations.Upgrades.TargetVersionSeven { private readonly bool _skipIndexCheck; - internal AddIndexToCmsMacroTable(bool skipIndexCheck) + internal AddIndexToCmsMacroTable(bool skipIndexCheck, ISqlSyntaxProvider sqlSyntax, ILogger logger) + : base(sqlSyntax, logger) { _skipIndexCheck = skipIndexCheck; } @@ -27,7 +29,7 @@ namespace Umbraco.Core.Persistence.Migrations.Upgrades.TargetVersionSeven public override void Up() { - var dbIndexes = _skipIndexCheck ? new DbIndexDefinition[] { } : SqlSyntaxContext.SqlSyntaxProvider.GetDefinedIndexes(Context.Database) + var dbIndexes = _skipIndexCheck ? new DbIndexDefinition[] { } : SqlSyntax.GetDefinedIndexes(Context.Database) .Select(x => new DbIndexDefinition() { TableName = x.Item1, diff --git a/src/Umbraco.Core/Persistence/Migrations/Upgrades/TargetVersionSeven/AlterCmsMacroPropertyTable.cs b/src/Umbraco.Core/Persistence/Migrations/Upgrades/TargetVersionSeven/AlterCmsMacroPropertyTable.cs index 60828c5a5c..87289bdd9d 100644 --- a/src/Umbraco.Core/Persistence/Migrations/Upgrades/TargetVersionSeven/AlterCmsMacroPropertyTable.cs +++ b/src/Umbraco.Core/Persistence/Migrations/Upgrades/TargetVersionSeven/AlterCmsMacroPropertyTable.cs @@ -59,8 +59,8 @@ namespace Umbraco.Core.Persistence.Migrations.Upgrades.TargetVersionSeven { //Before we try to delete this constraint, we'll see if it exists first, some older schemas never had it and some older schema's had this named // differently than the default. - - var keyConstraints = SqlSyntaxContext.SqlSyntaxProvider.GetConstraintsPerColumn(Context.Database).Distinct(); + + var keyConstraints = SqlSyntax.GetConstraintsPerColumn(Context.Database).Distinct(); var constraint = keyConstraints .SingleOrDefault(x => x.Item1 == "cmsMacroProperty" && x.Item2 == "macroPropertyType" && x.Item3.InvariantStartsWith("PK_") == false); if (constraint != null) diff --git a/src/Umbraco.Core/Persistence/Migrations/Upgrades/TargetVersionSeven/AlterTagRelationsTable.cs b/src/Umbraco.Core/Persistence/Migrations/Upgrades/TargetVersionSeven/AlterTagRelationsTable.cs index 31cfeb7997..f9a8f3951c 100644 --- a/src/Umbraco.Core/Persistence/Migrations/Upgrades/TargetVersionSeven/AlterTagRelationsTable.cs +++ b/src/Umbraco.Core/Persistence/Migrations/Upgrades/TargetVersionSeven/AlterTagRelationsTable.cs @@ -25,7 +25,7 @@ namespace Umbraco.Core.Persistence.Migrations.Upgrades.TargetVersionSeven private void Initial() { - var constraints = SqlSyntaxContext.SqlSyntaxProvider.GetConstraintsPerColumn(Context.Database).Distinct().ToArray(); + var constraints = SqlSyntax.GetConstraintsPerColumn(Context.Database).Distinct().ToArray(); //create a new col which we will make a foreign key, but first needs to be populated with data. Alter.Table("cmsTagRelationship").AddColumn("propertyTypeId").AsInt32().Nullable(); @@ -95,7 +95,7 @@ namespace Umbraco.Core.Persistence.Migrations.Upgrades.TargetVersionSeven var propertyTypes = propertyTypeIdRef.Where(x => x.NodeId == tr.NodeId).ToArray(); if (propertyTypes.Length == 0) { - LogHelper.Warn("There was no cmsContent reference for cmsTagRelationship for nodeId " + Logger.Warn("There was no cmsContent reference for cmsTagRelationship for nodeId " + tr.NodeId + ". The new tag system only supports tags with references to content in the cmsContent and cmsPropertyType tables. This row will be deleted: " + string.Format("nodeId: {0}, tagId: {1}", tr.NodeId, tr.TagId)); diff --git a/src/Umbraco.Core/Persistence/Migrations/Upgrades/TargetVersionSeven/AlterTagsTable.cs b/src/Umbraco.Core/Persistence/Migrations/Upgrades/TargetVersionSeven/AlterTagsTable.cs index b52dd4baed..da3bfa9a7b 100644 --- a/src/Umbraco.Core/Persistence/Migrations/Upgrades/TargetVersionSeven/AlterTagsTable.cs +++ b/src/Umbraco.Core/Persistence/Migrations/Upgrades/TargetVersionSeven/AlterTagsTable.cs @@ -12,7 +12,7 @@ namespace Umbraco.Core.Persistence.Migrations.Upgrades.TargetVersionSeven { public override void Up() { - var dbIndexes = SqlSyntaxContext.SqlSyntaxProvider.GetDefinedIndexes(Context.Database) + var dbIndexes = SqlSyntax.GetDefinedIndexes(Context.Database) .Select(x => new DbIndexDefinition() { TableName = x.Item1, diff --git a/src/Umbraco.Core/Persistence/Migrations/Upgrades/TargetVersionSeven/AssignMissingKeysAndIndexes.cs b/src/Umbraco.Core/Persistence/Migrations/Upgrades/TargetVersionSeven/AssignMissingKeysAndIndexes.cs index 7be58853c9..577ce1dc66 100644 --- a/src/Umbraco.Core/Persistence/Migrations/Upgrades/TargetVersionSeven/AssignMissingKeysAndIndexes.cs +++ b/src/Umbraco.Core/Persistence/Migrations/Upgrades/TargetVersionSeven/AssignMissingKeysAndIndexes.cs @@ -20,7 +20,7 @@ namespace Umbraco.Core.Persistence.Migrations.Upgrades.TargetVersionSeven //Some very old schemas don't have an index on the cmsContent.nodeId column, I'm not actually sure when it was added but // it is absolutely required to exist in order to have it as a foreign key reference, so we'll need to check it's existence // this came to light from this issue: http://issues.umbraco.org/issue/U4-4133 - var dbIndexes = SqlSyntaxContext.SqlSyntaxProvider.GetDefinedIndexes(Context.Database) + var dbIndexes = SqlSyntax.GetDefinedIndexes(Context.Database) .Select(x => new DbIndexDefinition() { TableName = x.Item1, @@ -36,7 +36,7 @@ namespace Umbraco.Core.Persistence.Migrations.Upgrades.TargetVersionSeven if (Context.CurrentDatabaseProvider == DatabaseProviders.SqlServer || Context.CurrentDatabaseProvider == DatabaseProviders.SqlServerCE) { - var constraints = SqlSyntaxContext.SqlSyntaxProvider.GetConstraintsPerColumn(Context.Database).Distinct().ToArray(); + var constraints = SqlSyntax.GetConstraintsPerColumn(Context.Database).Distinct().ToArray(); //This should be 2 because this table has 2 keys if (constraints.Count(x => x.Item1.InvariantEquals("cmsPreviewXml") && x.Item3.InvariantStartsWith("PK_")) == 0) diff --git a/src/Umbraco.Core/Persistence/Migrations/Upgrades/TargetVersionSeven/UpdateRelatedLinksData.cs b/src/Umbraco.Core/Persistence/Migrations/Upgrades/TargetVersionSeven/UpdateRelatedLinksData.cs index 89630c7ab5..218724e053 100644 --- a/src/Umbraco.Core/Persistence/Migrations/Upgrades/TargetVersionSeven/UpdateRelatedLinksData.cs +++ b/src/Umbraco.Core/Persistence/Migrations/Upgrades/TargetVersionSeven/UpdateRelatedLinksData.cs @@ -23,7 +23,7 @@ namespace Umbraco.Core.Persistence.Migrations.Upgrades.TargetVersionSeven Execute.Code(UpdateRelatedLinksDataDo); } - public static string UpdateRelatedLinksDataDo(Database database) + public string UpdateRelatedLinksDataDo(Database database) { if (database != null) { @@ -66,7 +66,7 @@ namespace Umbraco.Core.Persistence.Migrations.Upgrades.TargetVersionSeven } catch (Exception ex) { - LogHelper.Error("The data stored for property id " + data.Id + " on document " + data.NodeId + + Logger.Error("The data stored for property id " + data.Id + " on document " + data.NodeId + " is not valid XML, the data will be removed because it cannot be converted to the new format. The value was: " + data.Text, ex); data.Text = ""; diff --git a/src/Umbraco.Core/Persistence/Migrations/Upgrades/TargetVersionSevenOneZero/AssignMissingPrimaryForMySqlKeys.cs b/src/Umbraco.Core/Persistence/Migrations/Upgrades/TargetVersionSevenOneZero/AssignMissingPrimaryForMySqlKeys.cs index bb5bf56386..b26ecca330 100644 --- a/src/Umbraco.Core/Persistence/Migrations/Upgrades/TargetVersionSevenOneZero/AssignMissingPrimaryForMySqlKeys.cs +++ b/src/Umbraco.Core/Persistence/Migrations/Upgrades/TargetVersionSevenOneZero/AssignMissingPrimaryForMySqlKeys.cs @@ -17,7 +17,7 @@ namespace Umbraco.Core.Persistence.Migrations.Upgrades.TargetVersionSevenOneZero { if (Context.CurrentDatabaseProvider == DatabaseProviders.MySql) { - var constraints = SqlSyntaxContext.SqlSyntaxProvider.GetConstraintsPerColumn(Context.Database).Distinct().ToArray(); + var constraints = SqlSyntax.GetConstraintsPerColumn(Context.Database).Distinct().ToArray(); //This should be 3 because this table has 3 keys if (constraints.Count(x => x.Item1.InvariantEquals("cmsTagRelationship") && x.Item3.InvariantEquals("PRIMARY")) == 0) diff --git a/src/Umbraco.Core/Persistence/Migrations/Upgrades/TargetVersionSevenThreeZero/AddRelationTypeForDocumentOnDelete.cs b/src/Umbraco.Core/Persistence/Migrations/Upgrades/TargetVersionSevenThreeZero/AddRelationTypeForDocumentOnDelete.cs new file mode 100644 index 0000000000..c656376a9f --- /dev/null +++ b/src/Umbraco.Core/Persistence/Migrations/Upgrades/TargetVersionSevenThreeZero/AddRelationTypeForDocumentOnDelete.cs @@ -0,0 +1,27 @@ +using System; +using Umbraco.Core.Configuration; +using Umbraco.Core.Models.Rdbms; + +namespace Umbraco.Core.Persistence.Migrations.Upgrades.TargetVersionSevenThreeZero +{ + [Migration("7.3.0", 0, GlobalSettings.UmbracoMigrationName)] + public class AddRelationTypeForDocumentOnDelete : MigrationBase + { + public override void Up() + { + Insert.IntoTable("umbracoRelationType").Row(new + { + dual = false, + parentObjectType = Guid.Parse(Constants.ObjectTypes.Document), + childObjectType = Guid.Parse(Constants.ObjectTypes.Document), + name = Constants.Conventions.RelationTypes.RelateParentDocumentOnDeleteName, + alias = Constants.Conventions.RelationTypes.RelateParentDocumentOnDeleteAlias + }); + + } + + public override void Down() + { + } + } +} \ No newline at end of file diff --git a/src/Umbraco.Core/Persistence/Migrations/Upgrades/TargetVersionSevenThreeZero/MigrateAndRemoveTemplateMasterColumn.cs b/src/Umbraco.Core/Persistence/Migrations/Upgrades/TargetVersionSevenThreeZero/MigrateAndRemoveTemplateMasterColumn.cs new file mode 100644 index 0000000000..0fe8c3c36c --- /dev/null +++ b/src/Umbraco.Core/Persistence/Migrations/Upgrades/TargetVersionSevenThreeZero/MigrateAndRemoveTemplateMasterColumn.cs @@ -0,0 +1,88 @@ +using System.Collections.Generic; +using System.Linq; +using Umbraco.Core.Configuration; +using Umbraco.Core.Models.Rdbms; +using Umbraco.Core.Persistence.SqlSyntax; + +namespace Umbraco.Core.Persistence.Migrations.Upgrades.TargetVersionSevenThreeZero +{ + /// + /// Remove the master column after we've migrated all of the values into the 'ParentId' and Path column of Umbraco node + /// + [Migration("7.3.0", 1, GlobalSettings.UmbracoMigrationName)] + public class MigrateAndRemoveTemplateMasterColumn : MigrationBase + { + public override void Up() + { + + //Don't execute anything if there is no 'master' column - this might occur if the db is already upgraded + var cols = SqlSyntax.GetColumnsInSchema(Context.Database); + if (cols.Any(x => x.ColumnName.InvariantEquals("master") && x.TableName.InvariantEquals("cmsTemplate")) == false) + { + return; + } + + //update the parentId column for all templates to be correct so it matches the current 'master' template + //NOTE: we are using dynamic because we need to get the data in a column that no longer exists in the schema + var templates = Context.Database.Fetch(new Sql().Select("*").From()); + foreach (var template in templates) + { + Update.Table("umbracoNode").Set(new {parentID = template.master ?? -1}).Where(new {id = template.nodeId}); + + //now build the correct path for the template + Update.Table("umbracoNode").Set(new { path = BuildPath (template, templates)}).Where(new { id = template.nodeId }); + + } + + //now remove the master column and key + if (this.Context.CurrentDatabaseProvider == DatabaseProviders.MySql) + { + Delete.ForeignKey().FromTable("cmsTemplate").ForeignColumn("master").ToTable("umbracoUser").PrimaryColumn("id"); + } + else + { + //These are the old aliases, before removing them, check they exist + var constraints = SqlSyntax.GetConstraintsPerColumn(Context.Database).Distinct().ToArray(); + + if (constraints.Any(x => x.Item1.InvariantEquals("cmsTemplate") && x.Item3.InvariantEquals("FK_cmsTemplate_cmsTemplate"))) + { + Delete.ForeignKey("FK_cmsTemplate_cmsTemplate").OnTable("cmsTemplate"); + } + + //TODO: Hopefully it's not named something else silly in some crazy old versions + } + + var columns = SqlSyntax.GetColumnsInSchema(Context.Database).Distinct().ToArray(); + if (columns.Any(x => x.ColumnName.InvariantEquals("master") && x.TableName.InvariantEquals("cmsTemplate"))) + { + Delete.Column("master").FromTable("cmsTemplate"); + } + } + + public override void Down() + { + } + + private string BuildPath(dynamic template, IEnumerable allTemplates) + { + if (template.master == null) + { + return string.Format("-1,{0}", template.nodeId); + } + + var parent = allTemplates.FirstOrDefault(x => x.nodeId == template.master); + + if (parent == null) + { + //this shouldn't happen but i suppose it could if people have bad data + return string.Format("-1,{0}", template.nodeId); + } + + //recurse + var parentPath = BuildPath(parent, allTemplates); + + var path = parentPath + string.Format(",{0}", template.nodeId); + return path; + } + } +} \ No newline at end of file diff --git a/src/Umbraco.Core/Persistence/Migrations/Upgrades/TargetVersionSevenThreeZero/MigrateStylesheetDataToFile.cs b/src/Umbraco.Core/Persistence/Migrations/Upgrades/TargetVersionSevenThreeZero/MigrateStylesheetDataToFile.cs new file mode 100644 index 0000000000..1b169d8e68 --- /dev/null +++ b/src/Umbraco.Core/Persistence/Migrations/Upgrades/TargetVersionSevenThreeZero/MigrateStylesheetDataToFile.cs @@ -0,0 +1,132 @@ +using System; +using System.IO; +using System.Linq; +using System.Text; +using Umbraco.Core.Configuration; +using Umbraco.Core.IO; +using Umbraco.Core.Models; +using File = System.IO.File; + +namespace Umbraco.Core.Persistence.Migrations.Upgrades.TargetVersionSevenThreeZero +{ + /// + /// Ensures that any stylesheets that have properties defined at the db level have the correct new syntax + /// in their files before we remove the stylesheet db tables + /// + /// + /// Instead of modifying the files directly (since we cannot roll them back) we will create temporary migrated files. + /// These files will then be copied over once the entire migration is complete so that if any migration fails and the db changes are + /// rolled back, the original files won't be affected. + /// + [Migration("7.3.0", 2, GlobalSettings.UmbracoMigrationName)] + public class MigrateStylesheetDataToFile : MigrationBase + { + public override void Up() + { + //This is all rather nasty but it's how stylesheets used to work in the 2 various ugly ways so we just have to + // deal with that to get this migration done + + + var tempFolder = IOHelper.MapPath("~/App_Data/TEMP/CssMigration/"); + if (Directory.Exists(tempFolder)) + { + //clear any existing css files (we back the real ones up so if this migration is run again for whatever reason anything that + // was previously backed up is still there, backup happens in a post migration: OverwriteStylesheetFilesFromTempFiles class) + var files = Directory.GetFiles(tempFolder, "*.css", SearchOption.AllDirectories); + foreach (var file in files) + { + File.Delete(file); + } + } + //create the temp folder + var tempDir = Directory.CreateDirectory(IOHelper.MapPath("~/App_Data/TEMP/CssMigration/")); + + + var sheets = Context.Database.Fetch("SELECT * FROM cmsStylesheet INNER JOIN umbracoNode on cmsStylesheet.nodeId = umbracoNode.id"); + foreach (var sheet in sheets) + { + var fileName = sheet.text; + + string dbContent; + //we will always use the file content over the db content if there is any + using (var memStream = new MemoryStream(Encoding.UTF8.GetBytes(sheet.content))) + { + dbContent = GetContentAboveUmbracoProps(memStream); + } + + var fileContent = string.Empty; + + //check for file and read in it's data - umbraco properties will only be kept that are in the db, + // anything below the infamous: /* EDITOR PROPERTIES - PLEASE DON'T DELETE THIS LINE TO AVOID DUPLICATE PROPERTIES */ + // line is an Umbraco property and therefore anything that is there that is not in the db will be cleared. + + var filePath = IOHelper.MapPath(string.Format("{0}/{1}.css", SystemDirectories.Css, fileName)); + if (File.Exists(filePath)) + { + using (var stream = File.OpenRead(filePath)) + { + fileContent = GetContentAboveUmbracoProps(stream); + } + } + + var props = Context.Database.Fetch("SELECT * FROM cmsStylesheetProperty INNER JOIN umbracoNode ON cmsStylesheetProperty.nodeId = umbracoNode.id WHere umbracoNode.parentID = @id", new { id = sheet.nodeId }); + + var cssFolderPath = IOHelper.MapPath(SystemDirectories.Css); + var relativeFsPath = StringExtensions.TrimStart(StringExtensions.TrimStart(filePath, cssFolderPath), "\\"); + var stylesheetInstance = new Stylesheet(relativeFsPath) + { + Content = fileContent.IsNullOrWhiteSpace() ? dbContent : fileContent + }; + + foreach (var prop in props) + { + if (stylesheetInstance.Properties.Any(x => x.Name == prop.text) == false) + { + stylesheetInstance.AddProperty(new StylesheetProperty(prop.text, prop.stylesheetPropertyAlias, prop.stylesheetPropertyValue)); + } + } + + //Save to temp folder + + //ensure the folder for the file exists since it could be in a sub folder + var tempFilePath = Path.Combine(tempDir.FullName, relativeFsPath); + Directory.CreateDirectory(Path.GetDirectoryName(tempFilePath)); + + File.WriteAllText(tempFilePath, stylesheetInstance.Content, Encoding.UTF8); + + } + } + + public override void Down() + { + throw new NotSupportedException("Cannot downgrade from 7.3 as there are database table deletions"); + } + + private string GetContentAboveUmbracoProps(Stream stream) + { + var content = string.Empty; + using (var re = new StreamReader(stream)) + { + string input; + var readingProperties = false; + + while ((input = re.ReadLine()) != null) + { + //This is that line that was in there before that was delimiting umb props from normal css: + // /* EDITOR PROPERTIES - PLEASE DON'T DELETE THIS LINE TO AVOID DUPLICATE PROPERTIES */ + if (input.Contains("EDITOR PROPERTIES")) + { + readingProperties = true; + continue; + } + + if (readingProperties == false) + { + content += input; + } + } + } + return content; + } + } +} \ No newline at end of file diff --git a/src/Umbraco.Core/Persistence/Migrations/Upgrades/TargetVersionSevenThreeZero/RemoveStylesheetDataAndTables.cs b/src/Umbraco.Core/Persistence/Migrations/Upgrades/TargetVersionSevenThreeZero/RemoveStylesheetDataAndTables.cs new file mode 100644 index 0000000000..a47c00c501 --- /dev/null +++ b/src/Umbraco.Core/Persistence/Migrations/Upgrades/TargetVersionSevenThreeZero/RemoveStylesheetDataAndTables.cs @@ -0,0 +1,35 @@ +using System; +using System.Linq; +using Umbraco.Core.Configuration; + +namespace Umbraco.Core.Persistence.Migrations.Upgrades.TargetVersionSevenThreeZero +{ + [Migration("7.3.0", 3, GlobalSettings.UmbracoMigrationName)] + public class RemoveStylesheetDataAndTables : MigrationBase + { + public override void Up() + { + //Clear all stylesheet data if the tables exist + var tables = SqlSyntax.GetTablesInSchema(Context.Database).ToArray(); + if (tables.InvariantContains("cmsStylesheetProperty")) + { + Delete.FromTable("cmsStylesheetProperty").AllRows(); + Delete.FromTable("umbracoNode").Row(new { nodeObjectType = new Guid(Constants.ObjectTypes.StylesheetProperty) }); + + Delete.Table("cmsStylesheetProperty"); + } + if (tables.InvariantContains("cmsStylesheet")) + { + Delete.FromTable("cmsStylesheet").AllRows(); + Delete.FromTable("umbracoNode").Row(new { nodeObjectType = new Guid(Constants.ObjectTypes.Stylesheet) }); + + Delete.Table("cmsStylesheet"); + } + } + + public override void Down() + { + throw new NotSupportedException("Cannot downgrade from 7.3 as there are database table deletions"); + } + } +} \ No newline at end of file diff --git a/src/Umbraco.Core/Persistence/Migrations/Upgrades/TargetVersionSevenTwoZero/AddIndexToUmbracoNodeTable.cs b/src/Umbraco.Core/Persistence/Migrations/Upgrades/TargetVersionSevenTwoZero/AddIndexToUmbracoNodeTable.cs index 90cd2be8c2..24affa73a4 100644 --- a/src/Umbraco.Core/Persistence/Migrations/Upgrades/TargetVersionSevenTwoZero/AddIndexToUmbracoNodeTable.cs +++ b/src/Umbraco.Core/Persistence/Migrations/Upgrades/TargetVersionSevenTwoZero/AddIndexToUmbracoNodeTable.cs @@ -21,7 +21,7 @@ namespace Umbraco.Core.Persistence.Migrations.Upgrades.TargetVersionSevenTwoZero public override void Up() { - var dbIndexes = _skipIndexCheck ? new DbIndexDefinition[] { } : SqlSyntaxContext.SqlSyntaxProvider.GetDefinedIndexes(Context.Database) + var dbIndexes = _skipIndexCheck ? new DbIndexDefinition[] { } : SqlSyntax.GetDefinedIndexes(Context.Database) .Select(x => new DbIndexDefinition { TableName = x.Item1, diff --git a/src/Umbraco.Core/Persistence/Migrations/Upgrades/TargetVersionSevenTwoZero/AddMissingForeignKeyForContentType.cs b/src/Umbraco.Core/Persistence/Migrations/Upgrades/TargetVersionSevenTwoZero/AddMissingForeignKeyForContentType.cs index 438909e8f9..0f5cc7da72 100644 --- a/src/Umbraco.Core/Persistence/Migrations/Upgrades/TargetVersionSevenTwoZero/AddMissingForeignKeyForContentType.cs +++ b/src/Umbraco.Core/Persistence/Migrations/Upgrades/TargetVersionSevenTwoZero/AddMissingForeignKeyForContentType.cs @@ -13,7 +13,7 @@ namespace Umbraco.Core.Persistence.Migrations.Upgrades.TargetVersionSevenTwoZero public override void Up() { - var constraints = SqlSyntaxContext.SqlSyntaxProvider.GetConstraintsPerColumn(Context.Database).Distinct().ToArray(); + var constraints = SqlSyntax.GetConstraintsPerColumn(Context.Database).Distinct().ToArray(); //if the FK doesn't exist if (constraints.Any(x => x.Item1.InvariantEquals("cmsContent") && x.Item2.InvariantEquals("contentType") && x.Item3.InvariantEquals("FK_cmsContent_cmsContentType_nodeId")) == false) diff --git a/src/Umbraco.Core/Persistence/Migrations/Upgrades/TargetVersionSevenTwoZero/AlterDataTypePreValueTable.cs b/src/Umbraco.Core/Persistence/Migrations/Upgrades/TargetVersionSevenTwoZero/AlterDataTypePreValueTable.cs index b15f5eba58..47a1189b3a 100644 --- a/src/Umbraco.Core/Persistence/Migrations/Upgrades/TargetVersionSevenTwoZero/AlterDataTypePreValueTable.cs +++ b/src/Umbraco.Core/Persistence/Migrations/Upgrades/TargetVersionSevenTwoZero/AlterDataTypePreValueTable.cs @@ -13,7 +13,7 @@ namespace Umbraco.Core.Persistence.Migrations.Upgrades.TargetVersionSevenTwoZero { public override void Up() { - var columns = SqlSyntaxContext.SqlSyntaxProvider.GetColumnsInSchema(Context.Database).Distinct().ToArray(); + var columns = SqlSyntax.GetColumnsInSchema(Context.Database).Distinct().ToArray(); //Check if it's already text if (columns.Any(x => x.ColumnName.InvariantEquals("value") && x.TableName.InvariantEquals("cmsDataTypePreValues") @@ -23,7 +23,7 @@ namespace Umbraco.Core.Persistence.Migrations.Upgrades.TargetVersionSevenTwoZero && x.DataType.InvariantEquals("ntext") == false))) { //To text - var textType = SqlSyntaxContext.SqlSyntaxProvider.GetSpecialDbType(SpecialDbTypes.NTEXT); + var textType = SqlSyntax.GetSpecialDbType(SpecialDbTypes.NTEXT); Alter.Table("cmsDataTypePreValues").AlterColumn("value").AsCustom(textType).Nullable(); } diff --git a/src/Umbraco.Core/Persistence/Migrations/Upgrades/TargetVersionSevenTwoZero/RemoveCmsDocumentAliasColumn.cs b/src/Umbraco.Core/Persistence/Migrations/Upgrades/TargetVersionSevenTwoZero/RemoveCmsDocumentAliasColumn.cs index e17824b5ae..a6a41387fc 100644 --- a/src/Umbraco.Core/Persistence/Migrations/Upgrades/TargetVersionSevenTwoZero/RemoveCmsDocumentAliasColumn.cs +++ b/src/Umbraco.Core/Persistence/Migrations/Upgrades/TargetVersionSevenTwoZero/RemoveCmsDocumentAliasColumn.cs @@ -9,7 +9,7 @@ namespace Umbraco.Core.Persistence.Migrations.Upgrades.TargetVersionSevenTwoZero { public override void Up() { - var columns = SqlSyntaxContext.SqlSyntaxProvider.GetColumnsInSchema(Context.Database).Distinct().ToArray(); + var columns = SqlSyntax.GetColumnsInSchema(Context.Database).Distinct().ToArray(); if (columns.Any(x => x.ColumnName.InvariantEquals("alias") && x.TableName.InvariantEquals("cmsDocument"))) { diff --git a/src/Umbraco.Core/Persistence/Migrations/Upgrades/TargetVersionSix/DeleteAppTables.cs b/src/Umbraco.Core/Persistence/Migrations/Upgrades/TargetVersionSix/DeleteAppTables.cs index 2b5f65e716..52fdf0281d 100644 --- a/src/Umbraco.Core/Persistence/Migrations/Upgrades/TargetVersionSix/DeleteAppTables.cs +++ b/src/Umbraco.Core/Persistence/Migrations/Upgrades/TargetVersionSix/DeleteAppTables.cs @@ -26,7 +26,7 @@ namespace Umbraco.Core.Persistence.Migrations.Upgrades.TargetVersionSix }) == false) { //These are the old aliases, before removing them, check they exist - var constraints = SqlSyntaxContext.SqlSyntaxProvider.GetConstraintsPerColumn(Context.Database).Distinct().ToArray(); + var constraints = SqlSyntax.GetConstraintsPerColumn(Context.Database).Distinct().ToArray(); if (constraints.Any(x => x.Item1.InvariantEquals("umbracoUser2app") && x.Item3.InvariantEquals("FK_umbracoUser2app_umbracoApp"))) { Delete.ForeignKey("FK_umbracoUser2app_umbracoApp").OnTable("umbracoUser2app"); diff --git a/src/Umbraco.Core/Persistence/Migrations/Upgrades/TargetVersionSixOneZero/CreateServerRegistryTable.cs b/src/Umbraco.Core/Persistence/Migrations/Upgrades/TargetVersionSixOneZero/CreateServerRegistryTable.cs index 5c39f92b21..b9ab37e4b7 100644 --- a/src/Umbraco.Core/Persistence/Migrations/Upgrades/TargetVersionSixOneZero/CreateServerRegistryTable.cs +++ b/src/Umbraco.Core/Persistence/Migrations/Upgrades/TargetVersionSixOneZero/CreateServerRegistryTable.cs @@ -4,6 +4,7 @@ using System.Linq; using System.Text; using Umbraco.Core.Configuration; using Umbraco.Core.Models.Rdbms; +using Umbraco.Core.Persistence.SqlSyntax; namespace Umbraco.Core.Persistence.Migrations.Upgrades.TargetVersionSixOneZero { @@ -13,8 +14,10 @@ namespace Umbraco.Core.Persistence.Migrations.Upgrades.TargetVersionSixOneZero { public override void Up() { + var schemaHelper = new DatabaseSchemaHelper(Context.Database, Logger, SqlSyntax); + //NOTE: This isn't the correct way to do this but to manually create this table with the Create syntax is a pain in the arse - Context.Database.CreateTable(); + schemaHelper.CreateTable(); } public override void Down() diff --git a/src/Umbraco.Core/Persistence/Migrations/Upgrades/TargetVersionSixTwoZero/AdditionalIndexesAndKeys.cs b/src/Umbraco.Core/Persistence/Migrations/Upgrades/TargetVersionSixTwoZero/AdditionalIndexesAndKeys.cs index 198e8307eb..561cd04a53 100644 --- a/src/Umbraco.Core/Persistence/Migrations/Upgrades/TargetVersionSixTwoZero/AdditionalIndexesAndKeys.cs +++ b/src/Umbraco.Core/Persistence/Migrations/Upgrades/TargetVersionSixTwoZero/AdditionalIndexesAndKeys.cs @@ -14,7 +14,7 @@ namespace Umbraco.Core.Persistence.Migrations.Upgrades.TargetVersionSixTwoZero public override void Up() { - var dbIndexes = SqlSyntaxContext.SqlSyntaxProvider.GetDefinedIndexes(Context.Database) + var dbIndexes = SqlSyntax.GetDefinedIndexes(Context.Database) .Select(x => new DbIndexDefinition() { TableName = x.Item1, diff --git a/src/Umbraco.Core/Persistence/Migrations/Upgrades/TargetVersionSixTwoZero/AssignMissingPrimaryForMySqlKeys.cs b/src/Umbraco.Core/Persistence/Migrations/Upgrades/TargetVersionSixTwoZero/AssignMissingPrimaryForMySqlKeys.cs index 027cecca9d..b7aa05c366 100644 --- a/src/Umbraco.Core/Persistence/Migrations/Upgrades/TargetVersionSixTwoZero/AssignMissingPrimaryForMySqlKeys.cs +++ b/src/Umbraco.Core/Persistence/Migrations/Upgrades/TargetVersionSixTwoZero/AssignMissingPrimaryForMySqlKeys.cs @@ -15,7 +15,7 @@ namespace Umbraco.Core.Persistence.Migrations.Upgrades.TargetVersionSixTwoZero { if (Context.CurrentDatabaseProvider == DatabaseProviders.MySql) { - var constraints = SqlSyntaxContext.SqlSyntaxProvider.GetConstraintsPerColumn(Context.Database).Distinct().ToArray(); + var constraints = SqlSyntax.GetConstraintsPerColumn(Context.Database).Distinct().ToArray(); //This should be 2 because this table has 2 keys if (constraints.Count(x => x.Item1.InvariantEquals("cmsContentTypeAllowedContentType") && x.Item3.InvariantEquals("PRIMARY")) == 0) diff --git a/src/Umbraco.Core/Persistence/Migrations/Upgrades/TargetVersionSixTwoZero/AssignMissingPrimaryForMySqlKeys2.cs b/src/Umbraco.Core/Persistence/Migrations/Upgrades/TargetVersionSixTwoZero/AssignMissingPrimaryForMySqlKeys2.cs index 65e440a1da..bbb51ea73f 100644 --- a/src/Umbraco.Core/Persistence/Migrations/Upgrades/TargetVersionSixTwoZero/AssignMissingPrimaryForMySqlKeys2.cs +++ b/src/Umbraco.Core/Persistence/Migrations/Upgrades/TargetVersionSixTwoZero/AssignMissingPrimaryForMySqlKeys2.cs @@ -14,7 +14,7 @@ namespace Umbraco.Core.Persistence.Migrations.Upgrades.TargetVersionSixTwoZero { if (Context.CurrentDatabaseProvider == DatabaseProviders.MySql) { - var constraints = SqlSyntaxContext.SqlSyntaxProvider.GetConstraintsPerColumn(Context.Database).Distinct().ToArray(); + var constraints = SqlSyntax.GetConstraintsPerColumn(Context.Database).Distinct().ToArray(); //This should be 2 because this table has 2 keys if (constraints.Count(x => x.Item1.InvariantEquals("cmsContentType2ContentType") && x.Item3.InvariantEquals("PRIMARY")) == 0) diff --git a/src/Umbraco.Core/Persistence/Migrations/Upgrades/TargetVersionSixTwoZero/UpdateToNewMemberPropertyAliases.cs b/src/Umbraco.Core/Persistence/Migrations/Upgrades/TargetVersionSixTwoZero/UpdateToNewMemberPropertyAliases.cs index 555c0bcdf1..127aa92d22 100644 --- a/src/Umbraco.Core/Persistence/Migrations/Upgrades/TargetVersionSixTwoZero/UpdateToNewMemberPropertyAliases.cs +++ b/src/Umbraco.Core/Persistence/Migrations/Upgrades/TargetVersionSixTwoZero/UpdateToNewMemberPropertyAliases.cs @@ -15,7 +15,7 @@ namespace Umbraco.Core.Persistence.Migrations.Upgrades.TargetVersionSixTwoZero Execute.Code(Update); } - internal static string Update(Database database) + internal string Update(Database database) { if (database != null) { @@ -75,7 +75,7 @@ WHERE umbracoNode.nodeObjectType = @objectType"; } catch (Exception ex) { - LogHelper.Error("Exception was thrown when trying to upgrade old member aliases to the new ones", ex); + Logger.Error("Exception was thrown when trying to upgrade old member aliases to the new ones", ex); throw; } } diff --git a/src/Umbraco.Core/Persistence/PetaPocoExtensions.cs b/src/Umbraco.Core/Persistence/PetaPocoExtensions.cs index faa247d4a9..4b882b9b6c 100644 --- a/src/Umbraco.Core/Persistence/PetaPocoExtensions.cs +++ b/src/Umbraco.Core/Persistence/PetaPocoExtensions.cs @@ -4,9 +4,6 @@ using System.Data; using System.Linq; using System.Text.RegularExpressions; using Umbraco.Core.Logging; -using Umbraco.Core.Models.Rdbms; -using Umbraco.Core.Persistence.DatabaseModelDefinitions; -using Umbraco.Core.Persistence.Migrations.Initial; using Umbraco.Core.Persistence.Querying; using Umbraco.Core.Persistence.SqlSyntax; @@ -14,9 +11,7 @@ namespace Umbraco.Core.Persistence { public static class PetaPocoExtensions { - internal delegate void CreateTableEventHandler(string tableName, Database db, TableCreationEventArgs e); - - internal static event CreateTableEventHandler NewTable; + /// /// This will escape single @ symbols for peta poco values so it doesn't think it's a parameter @@ -35,18 +30,20 @@ namespace Umbraco.Core.Persistence } + [Obsolete("Use the DatabaseSchemaHelper instead")] public static void CreateTable(this Database db) - where T : new() + where T : new() { - var tableType = typeof(T); - CreateTable(db, false, tableType); + var creator = new DatabaseSchemaHelper(db, LoggerResolver.Current.Logger, SqlSyntaxContext.SqlSyntaxProvider); + creator.CreateTable(); } + [Obsolete("Use the DatabaseSchemaHelper instead")] public static void CreateTable(this Database db, bool overwrite) where T : new() { - var tableType = typeof(T); - CreateTable(db, overwrite, tableType); + var creator = new DatabaseSchemaHelper(db, LoggerResolver.Current.Logger, SqlSyntaxContext.SqlSyntaxProvider); + creator.CreateTable(overwrite); } public static void BulkInsertRecords(this Database db, IEnumerable collection) @@ -207,103 +204,26 @@ namespace Umbraco.Core.Persistence return commands.ToArray(); } + [Obsolete("Use the DatabaseSchemaHelper instead")] public static void CreateTable(this Database db, bool overwrite, Type modelType) { - var tableDefinition = DefinitionFactory.GetTableDefinition(modelType); - var tableName = tableDefinition.Name; - - string createSql = SqlSyntaxContext.SqlSyntaxProvider.Format(tableDefinition); - string createPrimaryKeySql = SqlSyntaxContext.SqlSyntaxProvider.FormatPrimaryKey(tableDefinition); - var foreignSql = SqlSyntaxContext.SqlSyntaxProvider.Format(tableDefinition.ForeignKeys); - var indexSql = SqlSyntaxContext.SqlSyntaxProvider.Format(tableDefinition.Indexes); - - var tableExist = db.TableExist(tableName); - if (overwrite && tableExist) - { - db.DropTable(tableName); - tableExist = false; - } - - if (tableExist == false) - { - using (var transaction = db.GetTransaction()) - { - //Execute the Create Table sql - int created = db.Execute(new Sql(createSql)); - LogHelper.Info(string.Format("Create Table sql {0}:\n {1}", created, createSql)); - - //If any statements exists for the primary key execute them here - if (!string.IsNullOrEmpty(createPrimaryKeySql)) - { - int createdPk = db.Execute(new Sql(createPrimaryKeySql)); - LogHelper.Info(string.Format("Primary Key sql {0}:\n {1}", createdPk, createPrimaryKeySql)); - } - - //Fires the NewTable event, which is used internally to insert base data before adding constrants to the schema - if (NewTable != null) - { - var e = new TableCreationEventArgs(); - - //Turn on identity insert if db provider is not mysql - if (SqlSyntaxContext.SqlSyntaxProvider.SupportsIdentityInsert() && tableDefinition.Columns.Any(x => x.IsIdentity)) - db.Execute(new Sql(string.Format("SET IDENTITY_INSERT {0} ON ", SqlSyntaxContext.SqlSyntaxProvider.GetQuotedTableName(tableName)))); - - //Call the NewTable-event to trigger the insert of base/default data - NewTable(tableName, db, e); - - //Turn off identity insert if db provider is not mysql - if (SqlSyntaxContext.SqlSyntaxProvider.SupportsIdentityInsert() && tableDefinition.Columns.Any(x => x.IsIdentity)) - db.Execute(new Sql(string.Format("SET IDENTITY_INSERT {0} OFF;", SqlSyntaxContext.SqlSyntaxProvider.GetQuotedTableName(tableName)))); - - //Special case for MySql - if (SqlSyntaxContext.SqlSyntaxProvider is MySqlSyntaxProvider && tableName.Equals("umbracoUser")) - { - db.Update("SET id = @IdAfter WHERE id = @IdBefore AND userLogin = @Login", new { IdAfter = 0, IdBefore = 1, Login = "admin" }); - } - } - - //Loop through foreignkey statements and execute sql - foreach (var sql in foreignSql) - { - int createdFk = db.Execute(new Sql(sql)); - LogHelper.Info(string.Format("Create Foreign Key sql {0}:\n {1}", createdFk, sql)); - } - - //Loop through index statements and execute sql - foreach (var sql in indexSql) - { - int createdIndex = db.Execute(new Sql(sql)); - LogHelper.Info(string.Format("Create Index sql {0}:\n {1}", createdIndex, sql)); - } - - transaction.Complete(); - } - } - - LogHelper.Info(string.Format("New table '{0}' was created", tableName)); + var creator = new DatabaseSchemaHelper(db, LoggerResolver.Current.Logger, SqlSyntaxContext.SqlSyntaxProvider); + creator.CreateTable(overwrite, modelType); } + [Obsolete("Use the DatabaseSchemaHelper instead")] public static void DropTable(this Database db) where T : new() { - Type type = typeof(T); - var tableNameAttribute = type.FirstAttribute(); - if (tableNameAttribute == null) - throw new Exception( - string.Format( - "The Type '{0}' does not contain a TableNameAttribute, which is used to find the name of the table to drop. The operation could not be completed.", - type.Name)); - - string tableName = tableNameAttribute.Value; - DropTable(db, tableName); + var helper = new DatabaseSchemaHelper(db, LoggerResolver.Current.Logger, SqlSyntaxContext.SqlSyntaxProvider); + helper.DropTable(); } + [Obsolete("Use the DatabaseSchemaHelper instead")] public static void DropTable(this Database db, string tableName) { - var sql = new Sql(string.Format( - SqlSyntaxContext.SqlSyntaxProvider.DropTable, - SqlSyntaxContext.SqlSyntaxProvider.GetQuotedTableName(tableName))); - db.Execute(sql); + var helper = new DatabaseSchemaHelper(db, LoggerResolver.Current.Logger, SqlSyntaxContext.SqlSyntaxProvider); + helper.DropTable(tableName); } public static void TruncateTable(this Database db, string tableName) @@ -314,11 +234,13 @@ namespace Umbraco.Core.Persistence db.Execute(sql); } + [Obsolete("Use the DatabaseSchemaHelper instead")] public static bool TableExist(this Database db, string tableName) { return SqlSyntaxContext.SqlSyntaxProvider.DoesTableExist(db, tableName); } + [Obsolete("Use the DatabaseSchemaHelper instead")] public static bool TableExist(this UmbracoDatabase db, string tableName) { return SqlSyntaxContext.SqlSyntaxProvider.DoesTableExist(db, tableName); @@ -330,6 +252,7 @@ namespace Umbraco.Core.Persistence /// umbraco instances. /// /// Current PetaPoco object + [Obsolete("Use the DatabaseSchemaHelper instead")] public static void CreateDatabaseSchema(this Database db) { CreateDatabaseSchema(db, true); @@ -342,53 +265,21 @@ namespace Umbraco.Core.Persistence /// /// /// + [Obsolete("Use the DatabaseSchemaHelper instead")] public static void CreateDatabaseSchema(this Database db, bool guardConfiguration) { - if (guardConfiguration && ApplicationContext.Current.IsConfigured) - throw new Exception("Umbraco is already configured!"); - - CreateDatabaseSchemaDo(db); - } - - internal static void UninstallDatabaseSchema(this Database db) - { - var creation = new DatabaseSchemaCreation(db); - creation.UninstallDatabaseSchema(); - } - - internal static void CreateDatabaseSchemaDo(this Database db, bool guardConfiguration) - { - if (guardConfiguration && ApplicationContext.Current.IsConfigured) - throw new Exception("Umbraco is already configured!"); - - CreateDatabaseSchemaDo(db); - } - - internal static void CreateDatabaseSchemaDo(this Database db) - { - NewTable += PetaPocoExtensions_NewTable; - - LogHelper.Info("Initializing database schema creation"); - - var creation = new DatabaseSchemaCreation(db); - creation.InitializeDatabaseSchema(); - - LogHelper.Info("Finalized database schema creation"); - - NewTable -= PetaPocoExtensions_NewTable; + var helper = new DatabaseSchemaHelper(db, LoggerResolver.Current.Logger, SqlSyntaxContext.SqlSyntaxProvider); + helper.CreateDatabaseSchema(guardConfiguration, ApplicationContext.Current); } + //TODO: What the heck? This makes no sense at all public static DatabaseProviders GetDatabaseProvider(this Database db) { return ApplicationContext.Current.DatabaseContext.DatabaseProvider; } - private static void PetaPocoExtensions_NewTable(string tableName, Database db, TableCreationEventArgs e) - { - var baseDataCreation = new BaseDataCreation(db); - baseDataCreation.InitializeBaseData(tableName); - } + } - internal class TableCreationEventArgs : System.ComponentModel.CancelEventArgs { } + } \ No newline at end of file diff --git a/src/Umbraco.Core/Persistence/PetaPocoSqlExtensions.cs b/src/Umbraco.Core/Persistence/PetaPocoSqlExtensions.cs index a02ef07510..3cbd70803d 100644 --- a/src/Umbraco.Core/Persistence/PetaPocoSqlExtensions.cs +++ b/src/Umbraco.Core/Persistence/PetaPocoSqlExtensions.cs @@ -13,13 +13,19 @@ namespace Umbraco.Core.Persistence /// public static class PetaPocoSqlExtensions { + [Obsolete("Use the overload specifying ISqlSyntaxProvider instead")] public static Sql From(this Sql sql) { - var type = typeof (T); + return From(sql, SqlSyntaxContext.SqlSyntaxProvider); + } + + 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(SqlSyntaxContext.SqlSyntaxProvider.GetQuotedTableName(tableName)); + return sql.From(sqlSyntax.GetQuotedTableName(tableName)); } public static Sql Where(this Sql sql, Expression> predicate) @@ -36,7 +42,13 @@ namespace Umbraco.Core.Persistence return sql.Where(fieldExpression + " IN (@values)", new {@values = values}); } + [Obsolete("Use the overload specifying ISqlSyntaxProvider instead")] public static Sql OrderBy(this Sql sql, Expression> columnMember) + { + return OrderBy(sql, columnMember, SqlSyntaxContext.SqlSyntaxProvider); + } + + public static Sql OrderBy(this Sql sql, Expression> columnMember, ISqlSyntaxProvider sqlSyntax) { var column = ExpressionHelper.FindProperty(columnMember) as PropertyInfo; var columnName = column.FirstAttribute().Name; @@ -47,13 +59,19 @@ namespace Umbraco.Core.Persistence //need to ensure the order by is in brackets, see: https://github.com/toptensoftware/PetaPoco/issues/177 var syntax = string.Format("({0}.{1})", - SqlSyntaxContext.SqlSyntaxProvider.GetQuotedTableName(tableName), - SqlSyntaxContext.SqlSyntaxProvider.GetQuotedColumnName(columnName)); + sqlSyntax.GetQuotedTableName(tableName), + sqlSyntax.GetQuotedColumnName(columnName)); return sql.OrderBy(syntax); } + [Obsolete("Use the overload specifying ISqlSyntaxProvider instead")] public static Sql OrderByDescending(this Sql sql, Expression> columnMember) + { + return OrderByDescending(sql, columnMember, SqlSyntaxContext.SqlSyntaxProvider); + } + + public static Sql OrderByDescending(this Sql sql, Expression> columnMember, ISqlSyntaxProvider sqlSyntax) { var column = ExpressionHelper.FindProperty(columnMember) as PropertyInfo; var columnName = column.FirstAttribute().Name; @@ -63,61 +81,98 @@ namespace Umbraco.Core.Persistence string tableName = tableNameAttribute == null ? string.Empty : tableNameAttribute.Value; var syntax = string.Format("{0}.{1} DESC", - SqlSyntaxContext.SqlSyntaxProvider.GetQuotedTableName(tableName), - SqlSyntaxContext.SqlSyntaxProvider.GetQuotedColumnName(columnName)); + sqlSyntax.GetQuotedTableName(tableName), + sqlSyntax.GetQuotedColumnName(columnName)); return sql.OrderBy(syntax); } + [Obsolete("Use the overload specifying ISqlSyntaxProvider instead")] public static Sql GroupBy(this Sql sql, Expression> columnMember) + { + return GroupBy(sql, columnMember, SqlSyntaxContext.SqlSyntaxProvider); + } + + public static Sql GroupBy(this Sql sql, Expression> columnMember, ISqlSyntaxProvider sqlProvider) { var column = ExpressionHelper.FindProperty(columnMember) as PropertyInfo; var columnName = column.FirstAttribute().Name; - return sql.GroupBy(SqlSyntaxContext.SqlSyntaxProvider.GetQuotedColumnName(columnName)); + return sql.GroupBy(sqlProvider.GetQuotedColumnName(columnName)); } + [Obsolete("Use the overload specifying ISqlSyntaxProvider instead")] public static Sql.SqlJoinClause InnerJoin(this Sql sql) { - var type = typeof (T); - var tableNameAttribute = type.FirstAttribute(); - string tableName = tableNameAttribute == null ? string.Empty : tableNameAttribute.Value; - - return sql.InnerJoin(SqlSyntaxContext.SqlSyntaxProvider.GetQuotedTableName(tableName)); + return InnerJoin(sql, SqlSyntaxContext.SqlSyntaxProvider); } - public static Sql.SqlJoinClause LeftJoin(this Sql sql) - { - var type = typeof (T); - var tableNameAttribute = type.FirstAttribute(); - string tableName = tableNameAttribute == null ? string.Empty : tableNameAttribute.Value; - - return sql.LeftJoin(SqlSyntaxContext.SqlSyntaxProvider.GetQuotedTableName(tableName)); - } - - public static Sql.SqlJoinClause LeftOuterJoin(this Sql sql) + 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.LeftOuterJoin(SqlSyntaxContext.SqlSyntaxProvider.GetQuotedTableName(tableName)); + return sql.InnerJoin(sqlSyntax.GetQuotedTableName(tableName)); } - public static Sql.SqlJoinClause RightJoin(this Sql sql) + [Obsolete("Use the overload specifying ISqlSyntaxProvider instead")] + public static Sql.SqlJoinClause LeftJoin(this Sql sql) { - var type = typeof (T); + return LeftJoin(sql, SqlSyntaxContext.SqlSyntaxProvider); + } + + 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.RightJoin(SqlSyntaxContext.SqlSyntaxProvider.GetQuotedTableName(tableName)); + return sql.LeftJoin(sqlSyntax.GetQuotedTableName(tableName)); } + [Obsolete("Use the overload specifying ISqlSyntaxProvider instead")] + public static Sql.SqlJoinClause LeftOuterJoin(this Sql sql) + { + return LeftOuterJoin(sql, SqlSyntaxContext.SqlSyntaxProvider); + } + + 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)); + } + + [Obsolete("Use the overload specifying ISqlSyntaxProvider instead")] + public static Sql.SqlJoinClause RightJoin(this Sql sql) + { + return RightJoin(sql, SqlSyntaxContext.SqlSyntaxProvider); + } + + 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)); + } + + [Obsolete("Use the overload specifying ISqlSyntaxProvider instead")] public static Sql On(this Sql.SqlJoinClause sql, Expression> leftMember, Expression> rightMember, params object[] args) { - var leftType = typeof (TLeft); - var rightType = typeof (TRight); + return On(sql, SqlSyntaxContext.SqlSyntaxProvider, leftMember, rightMember, args); + } + + 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; @@ -126,11 +181,11 @@ namespace Umbraco.Core.Persistence var leftColumnName = left.FirstAttribute().Name; var rightColumnName = right.FirstAttribute().Name; - string onClause = string.Format("{0}.{1} = {2}.{3}", - SqlSyntaxContext.SqlSyntaxProvider.GetQuotedTableName(leftTableName), - SqlSyntaxContext.SqlSyntaxProvider.GetQuotedColumnName(leftColumnName), - SqlSyntaxContext.SqlSyntaxProvider.GetQuotedTableName(rightTableName), - SqlSyntaxContext.SqlSyntaxProvider.GetQuotedColumnName(rightColumnName)); + string onClause = string.Format("{0}.{1} = {2}.{3}", + sqlSyntax.GetQuotedTableName(leftTableName), + sqlSyntax.GetQuotedColumnName(leftColumnName), + sqlSyntax.GetQuotedTableName(rightTableName), + sqlSyntax.GetQuotedColumnName(rightColumnName)); return sql.On(onClause); } diff --git a/src/Umbraco.Core/Persistence/Repositories/ContentPreviewRepository.cs b/src/Umbraco.Core/Persistence/Repositories/ContentPreviewRepository.cs index c749dc1204..9eee7d6788 100644 --- a/src/Umbraco.Core/Persistence/Repositories/ContentPreviewRepository.cs +++ b/src/Umbraco.Core/Persistence/Repositories/ContentPreviewRepository.cs @@ -1,10 +1,12 @@ using System; using System.Collections.Generic; using System.Xml.Linq; +using Umbraco.Core.Logging; using Umbraco.Core.Models; using Umbraco.Core.Models.Rdbms; -using Umbraco.Core.Persistence.Caching; + using Umbraco.Core.Persistence.Querying; +using Umbraco.Core.Persistence.SqlSyntax; using Umbraco.Core.Persistence.UnitOfWork; namespace Umbraco.Core.Persistence.Repositories @@ -15,8 +17,8 @@ namespace Umbraco.Core.Persistence.Repositories internal class ContentPreviewRepository : PetaPocoRepositoryBase> where TContent : IContentBase { - public ContentPreviewRepository(IDatabaseUnitOfWork work, IRepositoryCacheProvider cache) - : base(work, cache) + public ContentPreviewRepository(IDatabaseUnitOfWork work, CacheHelper cache, ILogger logger, ISqlSyntaxProvider sqlSyntax) + : base(work, cache, logger, sqlSyntax) { } diff --git a/src/Umbraco.Core/Persistence/Repositories/ContentRepository.cs b/src/Umbraco.Core/Persistence/Repositories/ContentRepository.cs index d89fc79dbe..5a09d95c49 100644 --- a/src/Umbraco.Core/Persistence/Repositories/ContentRepository.cs +++ b/src/Umbraco.Core/Persistence/Repositories/ContentRepository.cs @@ -10,14 +10,16 @@ using System.Xml.Linq; using Umbraco.Core.Configuration; using Umbraco.Core.Dynamics; using Umbraco.Core.IO; +using Umbraco.Core.Logging; using Umbraco.Core.Models; using Umbraco.Core.Models.EntityBase; using Umbraco.Core.Models.Membership; using Umbraco.Core.Models.Rdbms; -using Umbraco.Core.Persistence.Caching; + using Umbraco.Core.Persistence.DatabaseModelDefinitions; using Umbraco.Core.Persistence.Factories; using Umbraco.Core.Persistence.Querying; +using Umbraco.Core.Cache; using Umbraco.Core.Persistence.SqlSyntax; using Umbraco.Core.Persistence.UnitOfWork; @@ -34,25 +36,9 @@ namespace Umbraco.Core.Persistence.Repositories private readonly CacheHelper _cacheHelper; private readonly ContentPreviewRepository _contentPreviewRepository; private readonly ContentXmlRepository _contentXmlRepository; - - public ContentRepository(IDatabaseUnitOfWork work, IContentTypeRepository contentTypeRepository, ITemplateRepository templateRepository, ITagRepository tagRepository, CacheHelper cacheHelper) - : base(work) - { - if (contentTypeRepository == null) throw new ArgumentNullException("contentTypeRepository"); - if (templateRepository == null) throw new ArgumentNullException("templateRepository"); - if (tagRepository == null) throw new ArgumentNullException("tagRepository"); - _contentTypeRepository = contentTypeRepository; - _templateRepository = templateRepository; - _tagRepository = tagRepository; - _cacheHelper = cacheHelper; - _contentPreviewRepository = new ContentPreviewRepository(work, NullCacheProvider.Current); - _contentXmlRepository = new ContentXmlRepository(work, NullCacheProvider.Current); - EnsureUniqueNaming = true; - } - - public ContentRepository(IDatabaseUnitOfWork work, IRepositoryCacheProvider cache, IContentTypeRepository contentTypeRepository, ITemplateRepository templateRepository, ITagRepository tagRepository, CacheHelper cacheHelper) - : base(work, cache) + public ContentRepository(IDatabaseUnitOfWork work, CacheHelper cacheHelper, ILogger logger, ISqlSyntaxProvider syntaxProvider, IContentTypeRepository contentTypeRepository, ITemplateRepository templateRepository, ITagRepository tagRepository) + : base(work, cacheHelper, logger, syntaxProvider) { if (contentTypeRepository == null) throw new ArgumentNullException("contentTypeRepository"); if (templateRepository == null) throw new ArgumentNullException("templateRepository"); @@ -61,8 +47,8 @@ namespace Umbraco.Core.Persistence.Repositories _templateRepository = templateRepository; _tagRepository = tagRepository; _cacheHelper = cacheHelper; - _contentPreviewRepository = new ContentPreviewRepository(work, NullCacheProvider.Current); - _contentXmlRepository = new ContentXmlRepository(work, NullCacheProvider.Current); + _contentPreviewRepository = new ContentPreviewRepository(work, CacheHelper.CreateDisabledCacheHelper(), logger, syntaxProvider); + _contentXmlRepository = new ContentXmlRepository(work, CacheHelper.CreateDisabledCacheHelper(), logger, syntaxProvider); EnsureUniqueNaming = true; } @@ -184,7 +170,7 @@ namespace Umbraco.Core.Persistence.Repositories .InnerJoin() .On(left => left.NodeId, right => right.NodeId); - var deleteSql = SqlSyntaxContext.SqlSyntaxProvider.GetDeleteSubquery("cmsContentXml", "nodeId", subQuery); + var deleteSql = SqlSyntaxProvider.GetDeleteSubquery("cmsContentXml", "nodeId", subQuery); Database.Execute(deleteSql); } else @@ -200,7 +186,7 @@ namespace Umbraco.Core.Persistence.Repositories .Where(dto => dto.Published) .Where(dto => dto.ContentTypeId == id1); - var deleteSql = SqlSyntaxContext.SqlSyntaxProvider.GetDeleteSubquery("cmsContentXml", "nodeId", subQuery); + var deleteSql = SqlSyntaxProvider.GetDeleteSubquery("cmsContentXml", "nodeId", subQuery); Database.Execute(deleteSql); } } @@ -360,7 +346,7 @@ namespace Umbraco.Core.Persistence.Repositories //Assign the same permissions to it as the parent node // http://issues.umbraco.org/issue/U4-2161 - var permissionsRepo = new PermissionRepository(UnitOfWork, _cacheHelper); + var permissionsRepo = new PermissionRepository(UnitOfWork, _cacheHelper, SqlSyntaxProvider); var parentPermissions = permissionsRepo.GetPermissionsForEntity(entity.ParentId).ToArray(); //if there are parent permissions then assign them, otherwise leave null and permissions will become the // user's default permissions. @@ -605,10 +591,11 @@ namespace Umbraco.Core.Persistence.Repositories // then we can use that entity. Otherwise if it is not published (which can be the case // because we only store the 'latest' entries in the cache which might not be the published // version) - var fromCache = TryGetFromCache(dto.NodeId); - if (fromCache.Success && fromCache.Result.Published) + var fromCache = RepositoryCache.RuntimeCache.GetCacheItem(GetCacheIdKey(dto.NodeId)); + //var fromCache = TryGetFromCache(dto.NodeId); + if (fromCache != null && fromCache.Published) { - yield return fromCache.Result; + yield return fromCache; } else { @@ -627,7 +614,7 @@ namespace Umbraco.Core.Persistence.Repositories public void ReplaceContentPermissions(EntityPermissionSet permissionSet) { - var repo = new PermissionRepository(UnitOfWork, _cacheHelper); + var repo = new PermissionRepository(UnitOfWork, _cacheHelper, SqlSyntaxProvider); repo.ReplaceEntityPermissions(permissionSet); } @@ -654,13 +641,13 @@ namespace Umbraco.Core.Persistence.Repositories /// public void AssignEntityPermission(IContent entity, char permission, IEnumerable userIds) { - var repo = new PermissionRepository(UnitOfWork, _cacheHelper); + var repo = new PermissionRepository(UnitOfWork, _cacheHelper, SqlSyntaxProvider); repo.AssignEntityPermission(entity, permission, userIds); } public IEnumerable GetPermissionsForEntity(int entityId) { - var repo = new PermissionRepository(UnitOfWork, _cacheHelper); + var repo = new PermissionRepository(UnitOfWork, _cacheHelper, SqlSyntaxProvider); return repo.GetPermissionsForEntity(entityId); } @@ -722,7 +709,7 @@ namespace Umbraco.Core.Persistence.Repositories if (filter.IsNullOrWhiteSpace() == false) { - sbWhere.Append(" AND (cmsDocument." + SqlSyntaxContext.SqlSyntaxProvider.GetQuotedColumnName("text") + " LIKE @" + args.Count + ")"); + sbWhere.Append(" AND (cmsDocument." + SqlSyntaxProvider.GetQuotedColumnName("text") + " LIKE @" + args.Count + ")"); args.Add("%" + filter + "%"); } diff --git a/src/Umbraco.Core/Persistence/Repositories/ContentTypeBaseRepository.cs b/src/Umbraco.Core/Persistence/Repositories/ContentTypeBaseRepository.cs index 8c1b24329c..250c3f4da4 100644 --- a/src/Umbraco.Core/Persistence/Repositories/ContentTypeBaseRepository.cs +++ b/src/Umbraco.Core/Persistence/Repositories/ContentTypeBaseRepository.cs @@ -10,7 +10,7 @@ using Umbraco.Core.Logging; using Umbraco.Core.Models; using Umbraco.Core.Models.EntityBase; using Umbraco.Core.Models.Rdbms; -using Umbraco.Core.Persistence.Caching; + using Umbraco.Core.Persistence.Factories; using Umbraco.Core.Persistence.Querying; using Umbraco.Core.Persistence.Relators; @@ -27,13 +27,9 @@ namespace Umbraco.Core.Persistence.Repositories internal abstract class ContentTypeBaseRepository : PetaPocoRepositoryBase where TEntity : class, IContentTypeComposition { - protected ContentTypeBaseRepository(IDatabaseUnitOfWork work) - : base(work) - { - } - protected ContentTypeBaseRepository(IDatabaseUnitOfWork work, IRepositoryCacheProvider cache) - : base(work, cache) + protected ContentTypeBaseRepository(IDatabaseUnitOfWork work, CacheHelper cache, ILogger logger, ISqlSyntaxProvider sqlSyntaxProvider) + : base(work, cache, logger, sqlSyntaxProvider) { } @@ -74,7 +70,7 @@ namespace Umbraco.Core.Persistence.Repositories //Cannot add a duplicate content type type var exists = Database.ExecuteScalar(@"SELECT COUNT(*) FROM cmsContentType INNER JOIN umbracoNode ON cmsContentType.nodeId = umbracoNode.id -WHERE cmsContentType." + SqlSyntaxContext.SqlSyntaxProvider.GetQuotedColumnName("alias") + @"= @alias +WHERE cmsContentType." + SqlSyntaxProvider.GetQuotedColumnName("alias") + @"= @alias AND umbracoNode.nodeObjectType = @objectType", new { alias = entity.Alias, objectType = NodeObjectTypeId }); if (exists > 0) @@ -188,7 +184,7 @@ AND umbracoNode.nodeObjectType = @objectType", //Cannot update to a duplicate alias var exists = Database.ExecuteScalar(@"SELECT COUNT(*) FROM cmsContentType INNER JOIN umbracoNode ON cmsContentType.nodeId = umbracoNode.id -WHERE cmsContentType." + SqlSyntaxContext.SqlSyntaxProvider.GetQuotedColumnName("alias") + @"= @alias +WHERE cmsContentType." + SqlSyntaxProvider.GetQuotedColumnName("alias") + @"= @alias AND umbracoNode.nodeObjectType = @objectType AND umbracoNode.id <> @id", new { id = dto.NodeId, alias = entity.Alias, objectType = NodeObjectTypeId }); @@ -483,7 +479,7 @@ AND umbracoNode.id <> @id", pt.Name); var exception = new InvalidOperationException(message); - LogHelper.Error>(message, exception); + Logger.Error>(message, exception); throw exception; }); } @@ -500,7 +496,7 @@ AND umbracoNode.id <> @id", entity.Name); var exception = new InvalidOperationException(message); - LogHelper.Error>(message, exception); + Logger.Error>(message, exception); throw exception; }); } @@ -527,7 +523,7 @@ AND umbracoNode.id <> @id", } else { - LogHelper.Warn>("Could not assign a data type for the property type " + propertyType.Alias + " since no data type was found with a property editor " + propertyType.PropertyEditorAlias); + Logger.Warn>("Could not assign a data type for the property type " + propertyType.Alias + " since no data type was found with a property editor " + propertyType.PropertyEditorAlias); } } } @@ -568,28 +564,28 @@ AND umbracoNode.id <> @id", } public static IEnumerable GetMediaTypes( - int[] mediaTypeIds, Database db, + int[] mediaTypeIds, Database db, ISqlSyntaxProvider sqlSyntax, TRepo contentTypeRepository) where TRepo : IRepositoryQueryable { IDictionary> allParentMediaTypeIds; - var mediaTypes = MapMediaTypes(mediaTypeIds, db, out allParentMediaTypeIds) + var mediaTypes = MapMediaTypes(mediaTypeIds, db, sqlSyntax, out allParentMediaTypeIds) .ToArray(); - MapContentTypeChildren(mediaTypes, db, contentTypeRepository, allParentMediaTypeIds); + MapContentTypeChildren(mediaTypes, db, sqlSyntax, contentTypeRepository, allParentMediaTypeIds); return mediaTypes; } public static IEnumerable GetContentTypes( - int[] contentTypeIds, Database db, + int[] contentTypeIds, Database db, ISqlSyntaxProvider sqlSyntax, TRepo contentTypeRepository, ITemplateRepository templateRepository) where TRepo : IRepositoryQueryable { IDictionary> allAssociatedTemplates; IDictionary> allParentContentTypeIds; - var contentTypes = MapContentTypes(contentTypeIds, db, out allAssociatedTemplates, out allParentContentTypeIds) + var contentTypes = MapContentTypes(contentTypeIds, db, sqlSyntax, out allAssociatedTemplates, out allParentContentTypeIds) .ToArray(); if (contentTypes.Any()) @@ -598,14 +594,14 @@ AND umbracoNode.id <> @id", contentTypes, db, contentTypeRepository, templateRepository, allAssociatedTemplates); MapContentTypeChildren( - contentTypes, db, contentTypeRepository, allParentContentTypeIds); + contentTypes, db, sqlSyntax, contentTypeRepository, allParentContentTypeIds); } return contentTypes; } internal static void MapContentTypeChildren(IContentTypeComposition[] contentTypes, - Database db, + Database db, ISqlSyntaxProvider sqlSyntax, TRepo contentTypeRepository, IDictionary> allParentContentTypeIds) where TRepo : IRepositoryQueryable @@ -615,7 +611,7 @@ AND umbracoNode.id <> @id", var ids = contentTypes.Select(x => x.Id).ToArray(); IDictionary allPropGroups; IDictionary allPropTypes; - MapGroupsAndProperties(ids, db, out allPropTypes, out allPropGroups); + MapGroupsAndProperties(ids, db, sqlSyntax, out allPropTypes, out allPropGroups); foreach (var contentType in contentTypes) { @@ -684,7 +680,7 @@ AND umbracoNode.id <> @id", } - internal static IEnumerable MapMediaTypes(int[] mediaTypeIds, Database db, + internal static IEnumerable MapMediaTypes(int[] mediaTypeIds, Database db, ISqlSyntaxProvider sqlSyntax, out IDictionary> parentMediaTypeIds) { Mandate.That(mediaTypeIds.Any(), () => new InvalidOperationException("must be at least one content type id specified")); @@ -697,8 +693,8 @@ AND umbracoNode.id <> @id", cmsContentType.icon as ctIcon, cmsContentType.isContainer as ctIsContainer, cmsContentType.nodeId as ctId, cmsContentType.thumbnail as ctThumb, AllowedTypes.allowedId as ctaAllowedId, AllowedTypes.SortOrder as ctaSortOrder, AllowedTypes.alias as ctaAlias, ParentTypes.parentContentTypeId as chtParentId, - umbracoNode.createDate as nCreateDate, umbracoNode." + SqlSyntaxContext.SqlSyntaxProvider.GetQuotedColumnName("level") + @" as nLevel, umbracoNode.nodeObjectType as nObjectType, umbracoNode.nodeUser as nUser, - umbracoNode.parentID as nParentId, umbracoNode." + SqlSyntaxContext.SqlSyntaxProvider.GetQuotedColumnName("path") + @" as nPath, umbracoNode.sortOrder as nSortOrder, umbracoNode." + SqlSyntaxContext.SqlSyntaxProvider.GetQuotedColumnName("text") + @" as nName, umbracoNode.trashed as nTrashed, + umbracoNode.createDate as nCreateDate, umbracoNode." + sqlSyntax.GetQuotedColumnName("level") + @" as nLevel, umbracoNode.nodeObjectType as nObjectType, umbracoNode.nodeUser as nUser, + umbracoNode.parentID as nParentId, umbracoNode." + sqlSyntax.GetQuotedColumnName("path") + @" as nPath, umbracoNode.sortOrder as nSortOrder, umbracoNode." + sqlSyntax.GetQuotedColumnName("text") + @" as nName, umbracoNode.trashed as nTrashed, umbracoNode.uniqueID as nUniqueId FROM cmsContentType INNER JOIN umbracoNode @@ -791,7 +787,7 @@ AND umbracoNode.id <> @id", return mappedMediaTypes; } - internal static IEnumerable MapContentTypes(int[] contentTypeIds, Database db, + internal static IEnumerable MapContentTypes(int[] contentTypeIds, Database db, ISqlSyntaxProvider sqlSyntax, out IDictionary> associatedTemplates, out IDictionary> parentContentTypeIds) { @@ -805,8 +801,8 @@ AND umbracoNode.id <> @id", cmsContentType.icon as ctIcon, cmsContentType.isContainer as ctIsContainer, cmsContentType.nodeId as ctId, cmsContentType.thumbnail as ctThumb, AllowedTypes.allowedId as ctaAllowedId, AllowedTypes.SortOrder as ctaSortOrder, AllowedTypes.alias as ctaAlias, ParentTypes.parentContentTypeId as chtParentId, - umbracoNode.createDate as nCreateDate, umbracoNode." + SqlSyntaxContext.SqlSyntaxProvider.GetQuotedColumnName("level") + @" as nLevel, umbracoNode.nodeObjectType as nObjectType, umbracoNode.nodeUser as nUser, - umbracoNode.parentID as nParentId, umbracoNode." + SqlSyntaxContext.SqlSyntaxProvider.GetQuotedColumnName("path") + @" as nPath, umbracoNode.sortOrder as nSortOrder, umbracoNode." + SqlSyntaxContext.SqlSyntaxProvider.GetQuotedColumnName("text") + @" as nName, umbracoNode.trashed as nTrashed, + umbracoNode.createDate as nCreateDate, umbracoNode." + sqlSyntax.GetQuotedColumnName("level") + @" as nLevel, umbracoNode.nodeObjectType as nObjectType, umbracoNode.nodeUser as nUser, + umbracoNode.parentID as nParentId, umbracoNode." + sqlSyntax.GetQuotedColumnName("path") + @" as nPath, umbracoNode.sortOrder as nSortOrder, umbracoNode." + sqlSyntax.GetQuotedColumnName("text") + @" as nName, umbracoNode.trashed as nTrashed, umbracoNode.uniqueID as nUniqueId, Template.alias as tAlias, Template.nodeId as tId,Template.text as tText FROM cmsContentType @@ -962,7 +958,7 @@ AND umbracoNode.id <> @id", .Select(x => x.Value).ToList()); } - internal static void MapGroupsAndProperties(int[] contentTypeIds, Database db, + internal static void MapGroupsAndProperties(int[] contentTypeIds, Database db, ISqlSyntaxProvider sqlSyntax, out IDictionary allPropertyTypeCollection, out IDictionary allPropertyGroupCollection) { @@ -975,11 +971,11 @@ AND umbracoNode.id <> @id", var sqlBuilder = new StringBuilder(@"SELECT PG.contenttypeNodeId as contentTypeId, PT.ptId, PT.ptAlias, PT.ptDesc,PT.ptHelpText,PT.ptMandatory,PT.ptName,PT.ptSortOrder,PT.ptRegExp, PT.dtId,PT.dtDbType,PT.dtPropEdAlias, - PG.id as pgId, PG.parentGroupId as pgParentGroupId, PG.sortorder as pgSortOrder, PG." + SqlSyntaxContext.SqlSyntaxProvider.GetQuotedColumnName("text") + @" as pgText + PG.id as pgId, PG.parentGroupId as pgParentGroupId, PG.sortorder as pgSortOrder, PG." + sqlSyntax.GetQuotedColumnName("text") + @" as pgText FROM cmsPropertyTypeGroup as PG LEFT JOIN ( - SELECT PT.id as ptId, PT.Alias as ptAlias, PT." + SqlSyntaxContext.SqlSyntaxProvider.GetQuotedColumnName("Description") + @" as ptDesc, PT.helpText as ptHelpText, + SELECT PT.id as ptId, PT.Alias as ptAlias, PT." + sqlSyntax.GetQuotedColumnName("Description") + @" as ptDesc, PT.helpText as ptHelpText, PT.mandatory as ptMandatory, PT.Name as ptName, PT.sortOrder as ptSortOrder, PT.validationRegExp as ptRegExp, PT.propertyTypeGroupId as ptGroupId, DT.dbType as dtDbType, DT.nodeId as dtId, DT.propertyEditorAlias as dtPropEdAlias @@ -993,10 +989,10 @@ AND umbracoNode.id <> @id", UNION SELECT PT.contentTypeId as contentTypeId, - PT.id as ptId, PT.Alias as ptAlias, PT." + SqlSyntaxContext.SqlSyntaxProvider.GetQuotedColumnName("Description") + @" as ptDesc, PT.helpText as ptHelpText, + PT.id as ptId, PT.Alias as ptAlias, PT." + sqlSyntax.GetQuotedColumnName("Description") + @" as ptDesc, PT.helpText as ptHelpText, PT.mandatory as ptMandatory, PT.Name as ptName, PT.sortOrder as ptSortOrder, PT.validationRegExp as ptRegExp, DT.nodeId as dtId, DT.dbType as dtDbType, DT.propertyEditorAlias as dtPropEdAlias, - PG.id as pgId, PG.parentGroupId as pgParentGroupId, PG.sortorder as pgSortOrder, PG." + SqlSyntaxContext.SqlSyntaxProvider.GetQuotedColumnName("text") + @" as pgText + PG.id as pgId, PG.parentGroupId as pgParentGroupId, PG.sortorder as pgSortOrder, PG." + sqlSyntax.GetQuotedColumnName("text") + @" as pgText FROM cmsPropertyType as PT INNER JOIN cmsDataType as DT ON PT.dataTypeId = DT.nodeId diff --git a/src/Umbraco.Core/Persistence/Repositories/ContentTypeRepository.cs b/src/Umbraco.Core/Persistence/Repositories/ContentTypeRepository.cs index 898cf904ee..8218f67cf7 100644 --- a/src/Umbraco.Core/Persistence/Repositories/ContentTypeRepository.cs +++ b/src/Umbraco.Core/Persistence/Repositories/ContentTypeRepository.cs @@ -5,7 +5,7 @@ using Umbraco.Core.Logging; using Umbraco.Core.Models; using Umbraco.Core.Models.EntityBase; using Umbraco.Core.Models.Rdbms; -using Umbraco.Core.Persistence.Caching; + using Umbraco.Core.Persistence.Factories; using Umbraco.Core.Persistence.Querying; using Umbraco.Core.Persistence.Relators; @@ -21,14 +21,8 @@ namespace Umbraco.Core.Persistence.Repositories { private readonly ITemplateRepository _templateRepository; - public ContentTypeRepository(IDatabaseUnitOfWork work, ITemplateRepository templateRepository) - : base(work) - { - _templateRepository = templateRepository; - } - - public ContentTypeRepository(IDatabaseUnitOfWork work, IRepositoryCacheProvider cache, ITemplateRepository templateRepository) - : base(work, cache) + public ContentTypeRepository(IDatabaseUnitOfWork work, CacheHelper cache, ILogger logger, ISqlSyntaxProvider sqlSyntax, ITemplateRepository templateRepository) + : base(work, cache, logger, sqlSyntax) { _templateRepository = templateRepository; } @@ -38,7 +32,7 @@ namespace Umbraco.Core.Persistence.Repositories protected override IContentType PerformGet(int id) { var contentTypes = ContentTypeQueryMapper.GetContentTypes( - new[] {id}, Database, this, _templateRepository); + new[] {id}, Database, SqlSyntaxProvider, this, _templateRepository); var contentType = contentTypes.SingleOrDefault(); return contentType; @@ -48,13 +42,13 @@ namespace Umbraco.Core.Persistence.Repositories { if (ids.Any()) { - return ContentTypeQueryMapper.GetContentTypes(ids, Database, this, _templateRepository); + return ContentTypeQueryMapper.GetContentTypes(ids, Database, SqlSyntaxProvider, this, _templateRepository); } else { var sql = new Sql().Select("id").From().Where(dto => dto.NodeObjectType == NodeObjectTypeId); var allIds = Database.Fetch(sql).ToArray(); - return ContentTypeQueryMapper.GetContentTypes(allIds, Database, this, _templateRepository); + return ContentTypeQueryMapper.GetContentTypes(allIds, Database, SqlSyntaxProvider, this, _templateRepository); } } @@ -178,7 +172,7 @@ namespace Umbraco.Core.Persistence.Repositories entity.Name); var exception = new Exception(message); - LogHelper.Error(message, exception); + Logger.Error(message, exception); throw exception; }); diff --git a/src/Umbraco.Core/Persistence/Repositories/ContentXmlRepository.cs b/src/Umbraco.Core/Persistence/Repositories/ContentXmlRepository.cs index da076506a6..eb55d68bf8 100644 --- a/src/Umbraco.Core/Persistence/Repositories/ContentXmlRepository.cs +++ b/src/Umbraco.Core/Persistence/Repositories/ContentXmlRepository.cs @@ -1,10 +1,12 @@ using System; using System.Collections.Generic; using System.Xml.Linq; +using Umbraco.Core.Logging; using Umbraco.Core.Models; using Umbraco.Core.Models.Rdbms; -using Umbraco.Core.Persistence.Caching; + using Umbraco.Core.Persistence.Querying; +using Umbraco.Core.Persistence.SqlSyntax; using Umbraco.Core.Persistence.UnitOfWork; namespace Umbraco.Core.Persistence.Repositories @@ -15,8 +17,8 @@ namespace Umbraco.Core.Persistence.Repositories internal class ContentXmlRepository : PetaPocoRepositoryBase> where TContent : IContentBase { - public ContentXmlRepository(IDatabaseUnitOfWork work, IRepositoryCacheProvider cache) - : base(work, cache) + public ContentXmlRepository(IDatabaseUnitOfWork work, CacheHelper cache, ILogger logger, ISqlSyntaxProvider sqlSyntax) + : base(work, cache, logger, sqlSyntax) { } diff --git a/src/Umbraco.Core/Persistence/Repositories/DataTypeDefinitionRepository.cs b/src/Umbraco.Core/Persistence/Repositories/DataTypeDefinitionRepository.cs index 7c64620434..fba2e9f459 100644 --- a/src/Umbraco.Core/Persistence/Repositories/DataTypeDefinitionRepository.cs +++ b/src/Umbraco.Core/Persistence/Repositories/DataTypeDefinitionRepository.cs @@ -5,16 +5,16 @@ using System.Globalization; using System.Linq; using System.Threading; using Umbraco.Core.Cache; +using Umbraco.Core.Logging; using Umbraco.Core.Models; using Umbraco.Core.Models.EntityBase; using Umbraco.Core.Models.Rdbms; -using Umbraco.Core.Persistence.Caching; + using Umbraco.Core.Persistence.Factories; using Umbraco.Core.Persistence.Querying; using Umbraco.Core.Persistence.SqlSyntax; using Umbraco.Core.Persistence.UnitOfWork; using Umbraco.Core.Services; -using NullCacheProvider = Umbraco.Core.Persistence.Caching.NullCacheProvider; namespace Umbraco.Core.Persistence.Repositories { @@ -27,22 +27,13 @@ namespace Umbraco.Core.Persistence.Repositories private readonly IContentTypeRepository _contentTypeRepository; private readonly DataTypePreValueRepository _preValRepository; - public DataTypeDefinitionRepository(IDatabaseUnitOfWork work, CacheHelper cacheHelper, + public DataTypeDefinitionRepository(IDatabaseUnitOfWork work, CacheHelper cache, CacheHelper cacheHelper, ILogger logger, ISqlSyntaxProvider sqlSyntax, IContentTypeRepository contentTypeRepository) - : base(work) + : base(work, cache, logger, sqlSyntax) { _cacheHelper = cacheHelper; _contentTypeRepository = contentTypeRepository; - _preValRepository = new DataTypePreValueRepository(work, NullCacheProvider.Current); - } - - public DataTypeDefinitionRepository(IDatabaseUnitOfWork work, IRepositoryCacheProvider cache, CacheHelper cacheHelper, - IContentTypeRepository contentTypeRepository) - : base(work, cache) - { - _cacheHelper = cacheHelper; - _contentTypeRepository = contentTypeRepository; - _preValRepository = new DataTypePreValueRepository(work, NullCacheProvider.Current); + _preValRepository = new DataTypePreValueRepository(work, CacheHelper.CreateDisabledCacheHelper(), logger, sqlSyntax); } private readonly ReaderWriterLockSlim _locker = new ReaderWriterLockSlim(); @@ -159,7 +150,7 @@ namespace Umbraco.Core.Persistence.Repositories //Cannot add a duplicate data type var exists = Database.ExecuteScalar(@"SELECT COUNT(*) FROM cmsDataType INNER JOIN umbracoNode ON cmsDataType.nodeId = umbracoNode.id -WHERE umbracoNode." + SqlSyntaxContext.SqlSyntaxProvider.GetQuotedColumnName("text") + "= @name", new {name = entity.Name}); +WHERE umbracoNode." + SqlSyntaxProvider.GetQuotedColumnName("text") + "= @name", new {name = entity.Name}); if (exists > 0) { throw new DuplicateNameException("A data type with the name " + entity.Name + " already exists"); @@ -204,7 +195,7 @@ WHERE umbracoNode." + SqlSyntaxContext.SqlSyntaxProvider.GetQuotedColumnName("te //Cannot change to a duplicate alias var exists = Database.ExecuteScalar(@"SELECT COUNT(*) FROM cmsDataType INNER JOIN umbracoNode ON cmsDataType.nodeId = umbracoNode.id -WHERE umbracoNode." + SqlSyntaxContext.SqlSyntaxProvider.GetQuotedColumnName("text") + @"= @name +WHERE umbracoNode." + SqlSyntaxProvider.GetQuotedColumnName("text") + @"= @name AND umbracoNode.id <> @id", new { id = entity.Id, name = entity.Name }); if (exists > 0) @@ -446,7 +437,8 @@ AND umbracoNode.id <> @id", /// private class DataTypePreValueRepository : PetaPocoRepositoryBase { - public DataTypePreValueRepository(IDatabaseUnitOfWork work, IRepositoryCacheProvider cache) : base(work, cache) + public DataTypePreValueRepository(IDatabaseUnitOfWork work, CacheHelper cache, ILogger logger, ISqlSyntaxProvider sqlSyntax) + : base(work, cache, logger, sqlSyntax) { } diff --git a/src/Umbraco.Core/Persistence/Repositories/DictionaryRepository.cs b/src/Umbraco.Core/Persistence/Repositories/DictionaryRepository.cs index e29d24db32..241deaf05a 100644 --- a/src/Umbraco.Core/Persistence/Repositories/DictionaryRepository.cs +++ b/src/Umbraco.Core/Persistence/Repositories/DictionaryRepository.cs @@ -1,13 +1,15 @@ using System; using System.Collections.Generic; using System.Linq; +using Umbraco.Core.Logging; using Umbraco.Core.Models; using Umbraco.Core.Models.EntityBase; using Umbraco.Core.Models.Rdbms; -using Umbraco.Core.Persistence.Caching; + 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; namespace Umbraco.Core.Persistence.Repositories @@ -19,17 +21,11 @@ namespace Umbraco.Core.Persistence.Repositories { private readonly ILanguageRepository _languageRepository; - public DictionaryRepository(IDatabaseUnitOfWork work, ILanguageRepository languageRepository) - : base(work) - { - _languageRepository = languageRepository; - } - - public DictionaryRepository(IDatabaseUnitOfWork work, IRepositoryCacheProvider cache, ILanguageRepository languageRepository) - : base(work, cache) - { - _languageRepository = languageRepository; - } + public DictionaryRepository(IDatabaseUnitOfWork work, CacheHelper cache, ILogger logger, ISqlSyntaxProvider syntaxProvider, ILanguageRepository languageRepository) + : base(work, cache, logger, syntaxProvider) + { + _languageRepository = languageRepository; + } #region Overrides of RepositoryBase @@ -43,19 +39,7 @@ namespace Umbraco.Core.Persistence.Repositories if (dto == null) return null; - var factory = new DictionaryItemFactory(); - var entity = factory.BuildEntity(dto); - - var list = new List(); - foreach (var textDto in dto.LanguageTextDtos) - { - var language = _languageRepository.Get(textDto.LanguageId); - if (language == null) - continue; - var translationFactory = new DictionaryTranslationFactory(dto.UniqueId, language); - list.Add(translationFactory.BuildEntity(textDto)); - } - entity.Translations = list; + var entity = ConvertFromDto(dto); //on initial construction we don't want to have dirty properties tracked // http://issues.umbraco.org/issue/U4-1946 @@ -66,21 +50,14 @@ namespace Umbraco.Core.Persistence.Repositories protected override IEnumerable PerformGetAll(params int[] ids) { + var sql = GetBaseQuery(false).Where("cmsDictionary.pk > 0"); if (ids.Any()) { - foreach (var id in ids) - { - yield return Get(id); - } - } - else - { - var dtos = Database.Fetch("WHERE pk > 0"); - foreach (var dto in dtos) - { - yield return Get(dto.PrimaryKey); - } + sql.Where("cmsDictionary.pk in (@ids)", new { ids = ids }); } + + return Database.Fetch(new DictionaryLanguageTextRelator().Map, sql) + .Select(ConvertFromDto); } protected override IEnumerable PerformGetByQuery(IQuery query) @@ -90,12 +67,8 @@ namespace Umbraco.Core.Persistence.Repositories var sql = translator.Translate(); sql.OrderBy(x => x.UniqueId); - var dtos = Database.Fetch(new DictionaryLanguageTextRelator().Map, sql); - - foreach (var dto in dtos) - { - yield return Get(dto.PrimaryKey); - } + return Database.Fetch(new DictionaryLanguageTextRelator().Map, sql) + .Select(ConvertFromDto); } #endregion @@ -114,7 +87,7 @@ namespace Umbraco.Core.Persistence.Repositories { sql.Select("*") .From() - .InnerJoin() + .LeftJoin() .On(left => left.UniqueId, right => right.UniqueId); } return sql; @@ -135,7 +108,7 @@ namespace Umbraco.Core.Persistence.Repositories /// protected override Guid NodeObjectTypeId { - get { return new Guid("41c7638d-f529-4bff-853e-59a0c2fb1bde"); } + get { return new Guid(Constants.Conventions.Localization.DictionaryItemRootId); } } #endregion @@ -194,6 +167,10 @@ namespace Umbraco.Core.Persistence.Repositories } entity.ResetDirtyProperties(); + + //Clear the cache entries that exist by uniqueid/item key + RepositoryCache.RuntimeCache.ClearCacheItem(GetCacheIdKey(entity.ItemKey)); + RepositoryCache.RuntimeCache.ClearCacheItem(GetCacheIdKey(entity.Key)); } protected override void PersistDeletedItem(IDictionaryItem entity) @@ -201,8 +178,11 @@ namespace Umbraco.Core.Persistence.Repositories RecursiveDelete(entity.Key); Database.Delete("WHERE UniqueId = @Id", new { Id = entity.Key}); - Database.Delete("WHERE id = @Id", new { Id = entity.Key }); + + //Clear the cache entries that exist by uniqueid/item key + RepositoryCache.RuntimeCache.ClearCacheItem(GetCacheIdKey(entity.ItemKey)); + RepositoryCache.RuntimeCache.ClearCacheItem(GetCacheIdKey(entity.Key)); } private void RecursiveDelete(Guid parentId) @@ -214,9 +194,126 @@ namespace Umbraco.Core.Persistence.Repositories Database.Delete("WHERE UniqueId = @Id", new { Id = dto.UniqueId }); Database.Delete("WHERE id = @Id", new { Id = dto.UniqueId }); + + //Clear the cache entries that exist by uniqueid/item key + RepositoryCache.RuntimeCache.ClearCacheItem(GetCacheIdKey(dto.Key)); + RepositoryCache.RuntimeCache.ClearCacheItem(GetCacheIdKey(dto.UniqueId)); } } #endregion + + protected IDictionaryItem ConvertFromDto(DictionaryDto dto) + { + var factory = new DictionaryItemFactory(); + var entity = factory.BuildEntity(dto); + + var list = new List(); + foreach (var textDto in dto.LanguageTextDtos) + { + var language = _languageRepository.Get(textDto.LanguageId); + if (language == null) + continue; + var translationFactory = new DictionaryTranslationFactory(dto.UniqueId, language); + list.Add(translationFactory.BuildEntity(textDto)); + } + entity.Translations = list; + + return entity; + } + + public IDictionaryItem Get(Guid uniqueId) + { + var uniqueIdRepo = new DictionaryByUniqueIdRepository(this, UnitOfWork, RepositoryCache, Logger, SqlSyntaxProvider); + return uniqueIdRepo.Get(uniqueId); + } + + public IDictionaryItem Get(string key) + { + var keyRepo = new DictionaryByKeyRepository(this, UnitOfWork, RepositoryCache, Logger, SqlSyntaxProvider); + return keyRepo.Get(key); + } + + private class DictionaryByUniqueIdRepository : SimpleGetRepository + { + private readonly DictionaryRepository _dictionaryRepository; + + public DictionaryByUniqueIdRepository(DictionaryRepository dictionaryRepository, IDatabaseUnitOfWork work, CacheHelper cache, ILogger logger, ISqlSyntaxProvider sqlSyntax) + : base(work, cache, logger, sqlSyntax) + { + _dictionaryRepository = dictionaryRepository; + } + + protected override IEnumerable PerformFetch(Sql sql) + { + return Database.Fetch(new DictionaryLanguageTextRelator().Map, sql); + } + + protected override Sql GetBaseQuery(bool isCount) + { + return _dictionaryRepository.GetBaseQuery(isCount); + } + + protected override string GetBaseWhereClause() + { + return "cmsDictionary." + SqlSyntaxProvider.GetQuotedColumnName("id") + " = @Id"; + } + + protected override IDictionaryItem ConvertToEntity(DictionaryDto dto) + { + return _dictionaryRepository.ConvertFromDto(dto); + } + + protected override object GetBaseWhereClauseArguments(Guid id) + { + return new {Id = id}; + } + + protected override string GetWhereInClauseForGetAll() + { + return "cmsDictionary." + SqlSyntaxProvider.GetQuotedColumnName("id") + " in (@ids)"; + } + } + + private class DictionaryByKeyRepository : SimpleGetRepository + { + private readonly DictionaryRepository _dictionaryRepository; + + public DictionaryByKeyRepository(DictionaryRepository dictionaryRepository, IDatabaseUnitOfWork work, CacheHelper cache, ILogger logger, ISqlSyntaxProvider sqlSyntax) + : base(work, cache, logger, sqlSyntax) + { + _dictionaryRepository = dictionaryRepository; + } + + protected override IEnumerable PerformFetch(Sql sql) + { + return Database.Fetch(new DictionaryLanguageTextRelator().Map, sql); + } + + protected override Sql GetBaseQuery(bool isCount) + { + return _dictionaryRepository.GetBaseQuery(isCount); + } + + protected override string GetBaseWhereClause() + { + return "cmsDictionary." + SqlSyntaxProvider.GetQuotedColumnName("key") + " = @Id"; + } + + protected override IDictionaryItem ConvertToEntity(DictionaryDto dto) + { + return _dictionaryRepository.ConvertFromDto(dto); + } + + protected override object GetBaseWhereClauseArguments(string id) + { + return new { Id = id }; + } + + protected override string GetWhereInClauseForGetAll() + { + return "cmsDictionary." + SqlSyntaxProvider.GetQuotedColumnName("key") + " in (@ids)"; + } + } } } \ No newline at end of file diff --git a/src/Umbraco.Core/Persistence/Repositories/FileRepository.cs b/src/Umbraco.Core/Persistence/Repositories/FileRepository.cs index 4020dbb713..391a777e5e 100644 --- a/src/Umbraco.Core/Persistence/Repositories/FileRepository.cs +++ b/src/Umbraco.Core/Persistence/Repositories/FileRepository.cs @@ -1,5 +1,6 @@ using System.Collections.Generic; using System.IO; +using System.Linq; using System.Text; using Umbraco.Core.IO; using Umbraco.Core.Models; @@ -47,7 +48,7 @@ namespace Umbraco.Core.Persistence.Repositories public virtual void AddOrUpdate(TEntity entity) { - if (FileSystem.FileExists(entity.Path) == false) + if (FileSystem.FileExists(entity.OriginalPath) == false) { _work.RegisterAdded(entity, this); } @@ -146,6 +147,10 @@ namespace Umbraco.Core.Persistence.Repositories protected virtual void PersistUpdatedItem(TEntity entity) { + //TODO: A big problem here is if the entities 'Path' changes, if that is the case then + // we'd need to rename the underlying file, BUT how would we do this since we aren't storing an + // original path property. + using (var stream = GetContentStream(entity.Content)) { FileSystem.AddFile(entity.Path, stream, true); @@ -156,6 +161,15 @@ namespace Umbraco.Core.Persistence.Repositories entity.Key = entity.Path.EncodeAsGuid(); entity.VirtualPath = FileSystem.GetUrl(entity.Path); } + + //now that the file has been written, we need to check if the path had been changed + if (entity.Path.InvariantEquals(entity.OriginalPath) == false) + { + //delete the original file + FileSystem.DeleteFile(entity.OriginalPath); + //reset the original path on the file + entity.ResetOriginalPath(); + } } protected virtual void PersistDeletedItem(TEntity entity) @@ -178,15 +192,28 @@ namespace Umbraco.Core.Persistence.Repositories return new MemoryStream(Encoding.UTF8.GetBytes(content)); } - protected IEnumerable FindAllFiles(string path) + /// + /// Returns all files in the file system + /// + /// + /// + /// + /// Returns a list of all files with their paths. For example: + /// + /// \hello.txt + /// \folder1\test.txt + /// \folder1\blah.csv + /// \folder1\folder2\blahhhhh.svg + /// + protected IEnumerable FindAllFiles(string path, string filter) { var list = new List(); - list.AddRange(FileSystem.GetFiles(path, "*")); + list.AddRange(FileSystem.GetFiles(path, filter)); var directories = FileSystem.GetDirectories(path); foreach (var directory in directories) { - list.AddRange(FindAllFiles(directory)); + list.AddRange(FindAllFiles(directory, filter)); } return list; diff --git a/src/Umbraco.Core/Persistence/Repositories/Interfaces/IDictionaryRepository.cs b/src/Umbraco.Core/Persistence/Repositories/Interfaces/IDictionaryRepository.cs index b74dd08477..3a0328294a 100644 --- a/src/Umbraco.Core/Persistence/Repositories/Interfaces/IDictionaryRepository.cs +++ b/src/Umbraco.Core/Persistence/Repositories/Interfaces/IDictionaryRepository.cs @@ -1,9 +1,11 @@ -using Umbraco.Core.Models; +using System; +using Umbraco.Core.Models; namespace Umbraco.Core.Persistence.Repositories { public interface IDictionaryRepository : IRepositoryQueryable { - + IDictionaryItem Get(Guid uniqueId); + IDictionaryItem Get(string key); } } \ No newline at end of file diff --git a/src/Umbraco.Core/Persistence/Repositories/Interfaces/ILanguageRepository.cs b/src/Umbraco.Core/Persistence/Repositories/Interfaces/ILanguageRepository.cs index 01af81f1b7..f927cb433a 100644 --- a/src/Umbraco.Core/Persistence/Repositories/Interfaces/ILanguageRepository.cs +++ b/src/Umbraco.Core/Persistence/Repositories/Interfaces/ILanguageRepository.cs @@ -4,6 +4,7 @@ namespace Umbraco.Core.Persistence.Repositories { public interface ILanguageRepository : IRepositoryQueryable { - + ILanguage GetByCultureName(string cultureName); + ILanguage GetByIsoCode(string isoCode); } } \ No newline at end of file diff --git a/src/Umbraco.Core/Persistence/Repositories/Interfaces/IScriptRepository.cs b/src/Umbraco.Core/Persistence/Repositories/Interfaces/IScriptRepository.cs index 8c675a7d3a..9d7bfd2e36 100644 --- a/src/Umbraco.Core/Persistence/Repositories/Interfaces/IScriptRepository.cs +++ b/src/Umbraco.Core/Persistence/Repositories/Interfaces/IScriptRepository.cs @@ -4,6 +4,6 @@ namespace Umbraco.Core.Persistence.Repositories { public interface IScriptRepository : IRepository { - + bool ValidateScript(Script script); } } \ No newline at end of file diff --git a/src/Umbraco.Core/Persistence/Repositories/Interfaces/IStylesheetRepository.cs b/src/Umbraco.Core/Persistence/Repositories/Interfaces/IStylesheetRepository.cs index e0888a873d..1b2bcbe3eb 100644 --- a/src/Umbraco.Core/Persistence/Repositories/Interfaces/IStylesheetRepository.cs +++ b/src/Umbraco.Core/Persistence/Repositories/Interfaces/IStylesheetRepository.cs @@ -1,8 +1,10 @@ +using System.Collections.Generic; using Umbraco.Core.Models; namespace Umbraco.Core.Persistence.Repositories { public interface IStylesheetRepository : IRepository { + bool ValidateStylesheet(Stylesheet stylesheet); } } \ No newline at end of file diff --git a/src/Umbraco.Core/Persistence/Repositories/Interfaces/ITemplateRepository.cs b/src/Umbraco.Core/Persistence/Repositories/Interfaces/ITemplateRepository.cs index 318b840819..4366aaa4a6 100644 --- a/src/Umbraco.Core/Persistence/Repositories/Interfaces/ITemplateRepository.cs +++ b/src/Umbraco.Core/Persistence/Repositories/Interfaces/ITemplateRepository.cs @@ -6,8 +6,11 @@ namespace Umbraco.Core.Persistence.Repositories public interface ITemplateRepository : IRepositoryQueryable { ITemplate Get(string alias); + IEnumerable GetAll(params string[] aliases); + IEnumerable GetChildren(int masterTemplateId); + /// /// Returns a template as a template node which can be traversed (parent, children) /// @@ -22,5 +25,27 @@ namespace Umbraco.Core.Persistence.Repositories /// /// TemplateNode FindTemplateInTree(TemplateNode anyNode, string alias); + + /// + /// 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 + /// templates in business logic. Without this, it could cause the wrong rendering engine to be used for a package. + /// + RenderingEngine DetermineTemplateRenderingEngine(ITemplate template); + + /// + /// Validates a + /// + /// to validate + /// True if Script is valid, otherwise false + bool ValidateTemplate(ITemplate template); } } \ No newline at end of file diff --git a/src/Umbraco.Core/Persistence/Repositories/LanguageRepository.cs b/src/Umbraco.Core/Persistence/Repositories/LanguageRepository.cs index affe05e805..3b2e17e5bc 100644 --- a/src/Umbraco.Core/Persistence/Repositories/LanguageRepository.cs +++ b/src/Umbraco.Core/Persistence/Repositories/LanguageRepository.cs @@ -1,12 +1,14 @@ using System; using System.Collections.Generic; using System.Linq; +using Umbraco.Core.Logging; using Umbraco.Core.Models; using Umbraco.Core.Models.EntityBase; using Umbraco.Core.Models.Rdbms; -using Umbraco.Core.Persistence.Caching; + using Umbraco.Core.Persistence.Factories; using Umbraco.Core.Persistence.Querying; +using Umbraco.Core.Persistence.SqlSyntax; using Umbraco.Core.Persistence.UnitOfWork; namespace Umbraco.Core.Persistence.Repositories @@ -16,13 +18,8 @@ namespace Umbraco.Core.Persistence.Repositories /// internal class LanguageRepository : PetaPocoRepositoryBase, ILanguageRepository { - public LanguageRepository(IDatabaseUnitOfWork work) - : base(work) - { - } - - public LanguageRepository(IDatabaseUnitOfWork work, IRepositoryCacheProvider cache) - : base(work, cache) + public LanguageRepository(IDatabaseUnitOfWork work, CacheHelper cache, ILogger logger, ISqlSyntaxProvider sqlSyntax) + : base(work, cache, logger, sqlSyntax) { } @@ -37,8 +34,7 @@ namespace Umbraco.Core.Persistence.Repositories if (languageDto == null) return null; - var factory = new LanguageFactory(); - var entity = factory.BuildEntity(languageDto); + var entity = ConvertFromDto(languageDto); //on initial construction we don't want to have dirty properties tracked // http://issues.umbraco.org/issue/U4-1946 @@ -49,21 +45,13 @@ namespace Umbraco.Core.Persistence.Repositories protected override IEnumerable PerformGetAll(params int[] ids) { + var sql = GetBaseQuery(false).Where("umbracoLanguage.id > 0"); if (ids.Any()) { - foreach (var id in ids) - { - yield return Get(id); - } - } - else - { - var dtos = Database.Fetch("WHERE id > 0"); - foreach (var dto in dtos) - { - yield return Get(dto.Id); - } + sql.Where("umbracoLanguage.id in (@ids)", new { ids = ids }); } + + return Database.Fetch(sql).Select(ConvertFromDto); } protected override IEnumerable PerformGetByQuery(IQuery query) @@ -71,13 +59,7 @@ namespace Umbraco.Core.Persistence.Repositories var sqlClause = GetBaseQuery(false); var translator = new SqlTranslator(sqlClause, query); var sql = translator.Translate(); - - var dtos = Database.Fetch(sql); - - foreach (var dto in dtos) - { - yield return Get(dto.Id); - } + return Database.Fetch(sql).Select(ConvertFromDto); } #endregion @@ -99,9 +81,12 @@ namespace Umbraco.Core.Persistence.Repositories protected override IEnumerable GetDeleteClauses() { - //NOTE: There is no constraint between the Language and cmsDictionary/cmsLanguageText tables (?) + var list = new List { + //NOTE: There is no constraint between the Language and cmsDictionary/cmsLanguageText tables (?) + // but we still need to remove them + "DELETE FROM cmsLanguageText WHERE languageId = @Id", "DELETE FROM umbracoLanguage WHERE id = @Id" }; return list; @@ -139,8 +124,117 @@ namespace Umbraco.Core.Persistence.Repositories Database.Update(dto); entity.ResetDirtyProperties(); + + //Clear the cache entries that exist by key/iso + RepositoryCache.RuntimeCache.ClearCacheItem(GetCacheIdKey(entity.IsoCode)); + RepositoryCache.RuntimeCache.ClearCacheItem(GetCacheIdKey(entity.CultureName)); + } + + protected override void PersistDeletedItem(ILanguage entity) + { + base.PersistDeletedItem(entity); + + //Clear the cache entries that exist by key/iso + RepositoryCache.RuntimeCache.ClearCacheItem(GetCacheIdKey(entity.IsoCode)); + RepositoryCache.RuntimeCache.ClearCacheItem(GetCacheIdKey(entity.CultureName)); } #endregion + + protected ILanguage ConvertFromDto(LanguageDto dto) + { + var factory = new LanguageFactory(); + var entity = factory.BuildEntity(dto); + return entity; + } + + public ILanguage GetByCultureName(string cultureName) + { + var cultureNameRepo = new LanguageByCultureNameRepository(this, UnitOfWork, RepositoryCache, Logger, SqlSyntaxProvider); + return cultureNameRepo.Get(cultureName); + } + + public ILanguage GetByIsoCode(string isoCode) + { + var isoRepo = new LanguageByIsoCodeRepository(this, UnitOfWork, RepositoryCache, Logger, SqlSyntaxProvider); + return isoRepo.Get(isoCode); + } + + /// + /// Inner repository for looking up languages by ISO code, this deals with caching by a string key + /// + private class LanguageByIsoCodeRepository : SimpleGetRepository + { + private readonly LanguageRepository _languageRepository; + + public LanguageByIsoCodeRepository(LanguageRepository languageRepository, IDatabaseUnitOfWork work, CacheHelper cache, ILogger logger, ISqlSyntaxProvider sqlSyntax) + : base(work, cache, logger, sqlSyntax) + { + _languageRepository = languageRepository; + } + + protected override Sql GetBaseQuery(bool isCount) + { + return _languageRepository.GetBaseQuery(isCount); + } + + protected override string GetBaseWhereClause() + { + return "umbracoLanguage.languageISOCode = @Id"; + } + + protected override ILanguage ConvertToEntity(LanguageDto dto) + { + var factory = new LanguageFactory(); + return factory.BuildEntity(dto); + } + + protected override object GetBaseWhereClauseArguments(string id) + { + return new {Id = id}; + } + + protected override string GetWhereInClauseForGetAll() + { + return "umbracoLanguage.languageISOCode in (@ids)"; + } + } + + private class LanguageByCultureNameRepository : SimpleGetRepository + { + private readonly LanguageRepository _languageRepository; + + public LanguageByCultureNameRepository(LanguageRepository languageRepository, IDatabaseUnitOfWork work, CacheHelper cache, ILogger logger, ISqlSyntaxProvider sqlSyntax) + : base(work, cache, logger, sqlSyntax) + { + _languageRepository = languageRepository; + } + + protected override Sql GetBaseQuery(bool isCount) + { + return _languageRepository.GetBaseQuery(isCount); + } + + protected override string GetBaseWhereClause() + { + return "umbracoLanguage.languageCultureName = @Id"; + } + + protected override ILanguage ConvertToEntity(LanguageDto dto) + { + var factory = new LanguageFactory(); + return factory.BuildEntity(dto); + } + + protected override object GetBaseWhereClauseArguments(string id) + { + return new {Id = id}; + } + + protected override string GetWhereInClauseForGetAll() + { + return "umbracoLanguage.languageCultureName in (@ids)"; + } + } } } \ 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 1e05d88f2c..4d21059758 100644 --- a/src/Umbraco.Core/Persistence/Repositories/MacroRepository.cs +++ b/src/Umbraco.Core/Persistence/Repositories/MacroRepository.cs @@ -1,10 +1,11 @@ using System; using System.Collections.Generic; using System.Linq; +using Umbraco.Core.Logging; using Umbraco.Core.Models; using Umbraco.Core.Models.EntityBase; using Umbraco.Core.Models.Rdbms; -using Umbraco.Core.Persistence.Caching; + using Umbraco.Core.Persistence.Factories; using Umbraco.Core.Persistence.Querying; using Umbraco.Core.Persistence.Relators; @@ -15,11 +16,9 @@ namespace Umbraco.Core.Persistence.Repositories { internal class MacroRepository : PetaPocoRepositoryBase, IMacroRepository { - public MacroRepository(IDatabaseUnitOfWork work) : base(work) - { - } - public MacroRepository(IDatabaseUnitOfWork work, IRepositoryCacheProvider cache) : base(work, cache) + public MacroRepository(IDatabaseUnitOfWork work, CacheHelper cache, ILogger logger, ISqlSyntaxProvider sqlSyntax) + : base(work, cache, logger, sqlSyntax) { } diff --git a/src/Umbraco.Core/Persistence/Repositories/MediaRepository.cs b/src/Umbraco.Core/Persistence/Repositories/MediaRepository.cs index 7a487acaf4..426a2055eb 100644 --- a/src/Umbraco.Core/Persistence/Repositories/MediaRepository.cs +++ b/src/Umbraco.Core/Persistence/Repositories/MediaRepository.cs @@ -7,10 +7,11 @@ using System.Xml.Linq; using Umbraco.Core.Configuration; using Umbraco.Core.Dynamics; using Umbraco.Core.IO; +using Umbraco.Core.Logging; using Umbraco.Core.Models; using Umbraco.Core.Models.EntityBase; using Umbraco.Core.Models.Rdbms; -using Umbraco.Core.Persistence.Caching; + using Umbraco.Core.Persistence.DatabaseModelDefinitions; using Umbraco.Core.Persistence.Factories; using Umbraco.Core.Persistence.Querying; @@ -30,27 +31,15 @@ namespace Umbraco.Core.Persistence.Repositories private readonly ContentXmlRepository _contentXmlRepository; private readonly ContentPreviewRepository _contentPreviewRepository; - public MediaRepository(IDatabaseUnitOfWork work, IMediaTypeRepository mediaTypeRepository, ITagRepository tagRepository) - : base(work) + public MediaRepository(IDatabaseUnitOfWork work, CacheHelper cache, ILogger logger, ISqlSyntaxProvider sqlSyntax, IMediaTypeRepository mediaTypeRepository, ITagRepository tagRepository) + : base(work, cache, logger, sqlSyntax) { if (mediaTypeRepository == null) throw new ArgumentNullException("mediaTypeRepository"); if (tagRepository == null) throw new ArgumentNullException("tagRepository"); _mediaTypeRepository = mediaTypeRepository; _tagRepository = tagRepository; - _contentXmlRepository = new ContentXmlRepository(work, NullCacheProvider.Current); - _contentPreviewRepository = new ContentPreviewRepository(work, NullCacheProvider.Current); - EnsureUniqueNaming = true; - } - - public MediaRepository(IDatabaseUnitOfWork work, IRepositoryCacheProvider cache, IMediaTypeRepository mediaTypeRepository, ITagRepository tagRepository) - : base(work, cache) - { - if (mediaTypeRepository == null) throw new ArgumentNullException("mediaTypeRepository"); - if (tagRepository == null) throw new ArgumentNullException("tagRepository"); - _mediaTypeRepository = mediaTypeRepository; - _tagRepository = tagRepository; - _contentXmlRepository = new ContentXmlRepository(work, NullCacheProvider.Current); - _contentPreviewRepository = new ContentPreviewRepository(work, NullCacheProvider.Current); + _contentXmlRepository = new ContentXmlRepository(work, CacheHelper.CreateDisabledCacheHelper(), logger, sqlSyntax); + _contentPreviewRepository = new ContentPreviewRepository(work, CacheHelper.CreateDisabledCacheHelper(), logger, sqlSyntax); EnsureUniqueNaming = true; } @@ -190,7 +179,7 @@ namespace Umbraco.Core.Persistence.Repositories .On(left => left.NodeId, right => right.NodeId) .Where(dto => dto.NodeObjectType == mediaObjectType); - var deleteSql = SqlSyntaxContext.SqlSyntaxProvider.GetDeleteSubquery("cmsContentXml", "nodeId", subQuery); + var deleteSql = SqlSyntaxProvider.GetDeleteSubquery("cmsContentXml", "nodeId", subQuery); Database.Execute(deleteSql); } else @@ -209,7 +198,7 @@ namespace Umbraco.Core.Persistence.Repositories .Where(dto => dto.NodeObjectType == mediaObjectType) .Where(dto => dto.ContentTypeId == id1); - var deleteSql = SqlSyntaxContext.SqlSyntaxProvider.GetDeleteSubquery("cmsContentXml", "nodeId", subQuery); + var deleteSql = SqlSyntaxProvider.GetDeleteSubquery("cmsContentXml", "nodeId", subQuery); Database.Execute(deleteSql); } } @@ -467,7 +456,7 @@ namespace Umbraco.Core.Persistence.Repositories Func> filterCallback = null; if (filter.IsNullOrWhiteSpace() == false) { - sbWhere.Append("AND (umbracoNode." + SqlSyntaxContext.SqlSyntaxProvider.GetQuotedColumnName("text") + " LIKE @" + args.Count + ")"); + sbWhere.Append("AND (umbracoNode." + SqlSyntaxProvider.GetQuotedColumnName("text") + " LIKE @" + args.Count + ")"); args.Add("%" + filter + "%"); filterCallback = () => new Tuple(sbWhere.ToString().Trim(), args.ToArray()); } diff --git a/src/Umbraco.Core/Persistence/Repositories/MediaTypeRepository.cs b/src/Umbraco.Core/Persistence/Repositories/MediaTypeRepository.cs index 812db11462..3b98c43079 100644 --- a/src/Umbraco.Core/Persistence/Repositories/MediaTypeRepository.cs +++ b/src/Umbraco.Core/Persistence/Repositories/MediaTypeRepository.cs @@ -5,9 +5,10 @@ using Umbraco.Core.Logging; using Umbraco.Core.Models; using Umbraco.Core.Models.EntityBase; using Umbraco.Core.Models.Rdbms; -using Umbraco.Core.Persistence.Caching; + using Umbraco.Core.Persistence.Factories; using Umbraco.Core.Persistence.Querying; +using Umbraco.Core.Persistence.SqlSyntax; using Umbraco.Core.Persistence.UnitOfWork; namespace Umbraco.Core.Persistence.Repositories @@ -17,13 +18,9 @@ namespace Umbraco.Core.Persistence.Repositories /// internal class MediaTypeRepository : ContentTypeBaseRepository, IMediaTypeRepository { - public MediaTypeRepository(IDatabaseUnitOfWork work) - : base(work) - { - } - public MediaTypeRepository(IDatabaseUnitOfWork work, IRepositoryCacheProvider cache) - : base(work, cache) + public MediaTypeRepository(IDatabaseUnitOfWork work, CacheHelper cache, ILogger logger, ISqlSyntaxProvider sqlSyntax) + : base(work, cache, logger, sqlSyntax) { } @@ -63,13 +60,13 @@ namespace Umbraco.Core.Persistence.Repositories { if (ids.Any()) { - return ContentTypeQueryMapper.GetMediaTypes(ids, Database, this); + return ContentTypeQueryMapper.GetMediaTypes(ids, Database, SqlSyntaxProvider, this); } else { var sql = new Sql().Select("id").From().Where(dto => dto.NodeObjectType == NodeObjectTypeId); var allIds = Database.Fetch(sql).ToArray(); - return ContentTypeQueryMapper.GetMediaTypes(allIds, Database, this); + return ContentTypeQueryMapper.GetMediaTypes(allIds, Database, SqlSyntaxProvider, this); } } diff --git a/src/Umbraco.Core/Persistence/Repositories/MemberGroupRepository.cs b/src/Umbraco.Core/Persistence/Repositories/MemberGroupRepository.cs index 55af5552cd..6008cc1d07 100644 --- a/src/Umbraco.Core/Persistence/Repositories/MemberGroupRepository.cs +++ b/src/Umbraco.Core/Persistence/Repositories/MemberGroupRepository.cs @@ -2,10 +2,11 @@ using System.Collections.Generic; using System.Linq; using Umbraco.Core.Events; +using Umbraco.Core.Logging; using Umbraco.Core.Models; using Umbraco.Core.Models.EntityBase; using Umbraco.Core.Models.Rdbms; -using Umbraco.Core.Persistence.Caching; + using Umbraco.Core.Persistence.Factories; using Umbraco.Core.Persistence.Querying; using Umbraco.Core.Persistence.SqlSyntax; @@ -21,15 +22,8 @@ namespace Umbraco.Core.Persistence.Repositories { private readonly CacheHelper _cacheHelper; - public MemberGroupRepository(IDatabaseUnitOfWork work, CacheHelper cacheHelper) - : base(work) - { - if (cacheHelper == null) throw new ArgumentNullException("cacheHelper"); - _cacheHelper = cacheHelper; - } - - public MemberGroupRepository(IDatabaseUnitOfWork work, IRepositoryCacheProvider cache, CacheHelper cacheHelper) - : base(work, cache) + public MemberGroupRepository(IDatabaseUnitOfWork work, CacheHelper cache, ILogger logger, ISqlSyntaxProvider sqlSyntax, CacheHelper cacheHelper) + : base(work, cache, logger, sqlSyntax) { if (cacheHelper == null) throw new ArgumentNullException("cacheHelper"); _cacheHelper = cacheHelper; @@ -289,7 +283,7 @@ namespace Umbraco.Core.Persistence.Repositories .Select("*") .From() .Where(dto => dto.NodeObjectType == NodeObjectTypeId) - .Where("umbracoNode." + SqlSyntaxContext.SqlSyntaxProvider.GetQuotedColumnName("text") + " in (@names)", new { names = roleNames }); + .Where("umbracoNode." + SqlSyntaxProvider.GetQuotedColumnName("text") + " in (@names)", new { names = roleNames }); var existingRoles = Database.Fetch(existingSql).Select(x => x.Text); var missingRoles = roleNames.Except(existingRoles); var missingGroups = missingRoles.Select(x => new MemberGroup {Name = x}).ToArray(); @@ -312,9 +306,9 @@ namespace Umbraco.Core.Persistence.Repositories var assignedSql = new Sql(); assignedSql.Select(string.Format( "{0},{1},{2}", - SqlSyntaxContext.SqlSyntaxProvider.GetQuotedColumnName("text"), - SqlSyntaxContext.SqlSyntaxProvider.GetQuotedColumnName("Member"), - SqlSyntaxContext.SqlSyntaxProvider.GetQuotedColumnName("MemberGroup"))) + SqlSyntaxProvider.GetQuotedColumnName("text"), + SqlSyntaxProvider.GetQuotedColumnName("Member"), + SqlSyntaxProvider.GetQuotedColumnName("MemberGroup"))) .From() .InnerJoin() .On(dto => dto.NodeId, dto => dto.MemberGroup) @@ -356,7 +350,7 @@ namespace Umbraco.Core.Persistence.Repositories .Select("*") .From() .Where(dto => dto.NodeObjectType == NodeObjectTypeId) - .Where("umbracoNode." + SqlSyntaxContext.SqlSyntaxProvider.GetQuotedColumnName("text") + " in (@names)", new { names = roleNames }); + .Where("umbracoNode." + SqlSyntaxProvider.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)", diff --git a/src/Umbraco.Core/Persistence/Repositories/MemberRepository.cs b/src/Umbraco.Core/Persistence/Repositories/MemberRepository.cs index d5c65bd85b..92d1758bae 100644 --- a/src/Umbraco.Core/Persistence/Repositories/MemberRepository.cs +++ b/src/Umbraco.Core/Persistence/Repositories/MemberRepository.cs @@ -7,10 +7,11 @@ using System.Text; using System.Xml.Linq; using Umbraco.Core.Configuration; using Umbraco.Core.IO; +using Umbraco.Core.Logging; using Umbraco.Core.Models.EntityBase; using Umbraco.Core.Models; using Umbraco.Core.Models.Rdbms; -using Umbraco.Core.Persistence.Caching; + using Umbraco.Core.Persistence.DatabaseModelDefinitions; using Umbraco.Core.Persistence.Factories; using Umbraco.Core.Persistence.Querying; @@ -32,28 +33,16 @@ namespace Umbraco.Core.Persistence.Repositories private readonly ContentXmlRepository _contentXmlRepository; private readonly ContentPreviewRepository _contentPreviewRepository; - public MemberRepository(IDatabaseUnitOfWork work, IMemberTypeRepository memberTypeRepository, IMemberGroupRepository memberGroupRepository, ITagRepository tagRepository) - : base(work) + public MemberRepository(IDatabaseUnitOfWork work, CacheHelper cache, ILogger logger, ISqlSyntaxProvider sqlSyntax, IMemberTypeRepository memberTypeRepository, IMemberGroupRepository memberGroupRepository, ITagRepository tagRepository) + : base(work, cache, logger, sqlSyntax) { if (memberTypeRepository == null) throw new ArgumentNullException("memberTypeRepository"); if (tagRepository == null) throw new ArgumentNullException("tagRepository"); _memberTypeRepository = memberTypeRepository; _tagRepository = tagRepository; _memberGroupRepository = memberGroupRepository; - _contentXmlRepository = new ContentXmlRepository(work, NullCacheProvider.Current); - _contentPreviewRepository = new ContentPreviewRepository(work, NullCacheProvider.Current); - } - - public MemberRepository(IDatabaseUnitOfWork work, IRepositoryCacheProvider cache, IMemberTypeRepository memberTypeRepository, IMemberGroupRepository memberGroupRepository, ITagRepository tagRepository) - : base(work, cache) - { - if (memberTypeRepository == null) throw new ArgumentNullException("memberTypeRepository"); - if (tagRepository == null) throw new ArgumentNullException("tagRepository"); - _memberTypeRepository = memberTypeRepository; - _tagRepository = tagRepository; - _memberGroupRepository = memberGroupRepository; - _contentXmlRepository = new ContentXmlRepository(work, NullCacheProvider.Current); - _contentPreviewRepository = new ContentPreviewRepository(work, NullCacheProvider.Current); + _contentXmlRepository = new ContentXmlRepository(work, CacheHelper.CreateDisabledCacheHelper(), logger, sqlSyntax); + _contentPreviewRepository = new ContentPreviewRepository(work, CacheHelper.CreateDisabledCacheHelper(), logger, sqlSyntax); } #region Overrides of RepositoryBase @@ -435,7 +424,7 @@ namespace Umbraco.Core.Persistence.Repositories .On(left => left.NodeId, right => right.NodeId) .Where(dto => dto.NodeObjectType == memberObjectType); - var deleteSql = SqlSyntaxContext.SqlSyntaxProvider.GetDeleteSubquery("cmsContentXml", "nodeId", subQuery); + var deleteSql = SqlSyntaxProvider.GetDeleteSubquery("cmsContentXml", "nodeId", subQuery); Database.Execute(deleteSql); } else @@ -454,7 +443,7 @@ namespace Umbraco.Core.Persistence.Repositories .Where(dto => dto.NodeObjectType == memberObjectType) .Where(dto => dto.ContentTypeId == id1); - var deleteSql = SqlSyntaxContext.SqlSyntaxProvider.GetDeleteSubquery("cmsContentXml", "nodeId", subQuery); + var deleteSql = SqlSyntaxProvider.GetDeleteSubquery("cmsContentXml", "nodeId", subQuery); Database.Execute(deleteSql); } } @@ -661,7 +650,7 @@ namespace Umbraco.Core.Persistence.Repositories Func> filterCallback = null; if (filter.IsNullOrWhiteSpace() == false) { - sbWhere.Append("AND ((umbracoNode. " + SqlSyntaxContext.SqlSyntaxProvider.GetQuotedColumnName("text") + " LIKE @" + args.Count + ") " + + sbWhere.Append("AND ((umbracoNode. " + SqlSyntaxProvider.GetQuotedColumnName("text") + " LIKE @" + args.Count + ") " + "OR (cmsMember.LoginName LIKE @0" + args.Count + "))"); args.Add("%" + filter + "%"); filterCallback = () => new Tuple(sbWhere.ToString().Trim(), args.ToArray()); diff --git a/src/Umbraco.Core/Persistence/Repositories/MemberTypeRepository.cs b/src/Umbraco.Core/Persistence/Repositories/MemberTypeRepository.cs index bc79157b32..f451b3edbb 100644 --- a/src/Umbraco.Core/Persistence/Repositories/MemberTypeRepository.cs +++ b/src/Umbraco.Core/Persistence/Repositories/MemberTypeRepository.cs @@ -1,14 +1,16 @@ using System; using System.Collections.Generic; using System.Linq; +using log4net; using Umbraco.Core.Logging; using Umbraco.Core.Models.EntityBase; using Umbraco.Core.Models; using Umbraco.Core.Models.Rdbms; -using Umbraco.Core.Persistence.Caching; + 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; namespace Umbraco.Core.Persistence.Repositories @@ -18,13 +20,9 @@ namespace Umbraco.Core.Persistence.Repositories /// internal class MemberTypeRepository : ContentTypeBaseRepository, IMemberTypeRepository { - public MemberTypeRepository(IDatabaseUnitOfWork work) - : base(work) - { - } - public MemberTypeRepository(IDatabaseUnitOfWork work, IRepositoryCacheProvider cache) - : base(work, cache) + public MemberTypeRepository(IDatabaseUnitOfWork work, CacheHelper cache, ILogger logger, ISqlSyntaxProvider sqlSyntax) + : base(work, cache, logger, sqlSyntax) { } diff --git a/src/Umbraco.Core/Persistence/Repositories/PartialViewRepository.cs b/src/Umbraco.Core/Persistence/Repositories/PartialViewRepository.cs index b98b284a1f..2fd0240701 100644 --- a/src/Umbraco.Core/Persistence/Repositories/PartialViewRepository.cs +++ b/src/Umbraco.Core/Persistence/Repositories/PartialViewRepository.cs @@ -73,7 +73,7 @@ namespace Umbraco.Core.Persistence.Repositories } else { - var files = FindAllFiles(""); + var files = FindAllFiles("", "*.*"); foreach (var file in files) { yield return Get(file); diff --git a/src/Umbraco.Core/Persistence/Repositories/PermissionRepository.cs b/src/Umbraco.Core/Persistence/Repositories/PermissionRepository.cs index e28f2a0b65..8a2cd21acd 100644 --- a/src/Umbraco.Core/Persistence/Repositories/PermissionRepository.cs +++ b/src/Umbraco.Core/Persistence/Repositories/PermissionRepository.cs @@ -27,11 +27,13 @@ namespace Umbraco.Core.Persistence.Repositories { private readonly IDatabaseUnitOfWork _unitOfWork; private readonly CacheHelper _cache; + private readonly ISqlSyntaxProvider _sqlSyntax; - internal PermissionRepository(IDatabaseUnitOfWork unitOfWork, CacheHelper cache) + internal PermissionRepository(IDatabaseUnitOfWork unitOfWork, CacheHelper cache, ISqlSyntaxProvider sqlSyntax) { _unitOfWork = unitOfWork; _cache = cache; + _sqlSyntax = sqlSyntax; } /// @@ -51,7 +53,7 @@ namespace Umbraco.Core.Persistence.Repositories var whereBuilder = new StringBuilder(); //where userId = @userId AND - whereBuilder.Append(SqlSyntaxContext.SqlSyntaxProvider.GetQuotedColumnName("userId")); + whereBuilder.Append(_sqlSyntax.GetQuotedColumnName("userId")); whereBuilder.Append("="); whereBuilder.Append(userId); @@ -64,7 +66,7 @@ namespace Umbraco.Core.Persistence.Repositories for (var index = 0; index < entityIds.Length; index++) { var entityId = entityIds[index]; - whereBuilder.Append(SqlSyntaxContext.SqlSyntaxProvider.GetQuotedColumnName("nodeId")); + whereBuilder.Append(_sqlSyntax.GetQuotedColumnName("nodeId")); whereBuilder.Append("="); whereBuilder.Append(entityId); if (index < entityIds.Length - 1) diff --git a/src/Umbraco.Core/Persistence/Repositories/PetaPocoRepositoryBase.cs b/src/Umbraco.Core/Persistence/Repositories/PetaPocoRepositoryBase.cs index a08dec6c76..463630ab98 100644 --- a/src/Umbraco.Core/Persistence/Repositories/PetaPocoRepositoryBase.cs +++ b/src/Umbraco.Core/Persistence/Repositories/PetaPocoRepositoryBase.cs @@ -1,8 +1,10 @@ using System; using System.Collections.Generic; +using Umbraco.Core.Logging; using Umbraco.Core.Models.EntityBase; -using Umbraco.Core.Persistence.Caching; + using Umbraco.Core.Persistence.Querying; +using Umbraco.Core.Persistence.SqlSyntax; using Umbraco.Core.Persistence.UnitOfWork; namespace Umbraco.Core.Persistence.Repositories @@ -15,17 +17,16 @@ namespace Umbraco.Core.Persistence.Repositories internal abstract class PetaPocoRepositoryBase : RepositoryBase where TEntity : class, IAggregateRoot { - protected PetaPocoRepositoryBase(IDatabaseUnitOfWork work) - : base(work) + public ISqlSyntaxProvider SqlSyntaxProvider { get; private set; } + + protected PetaPocoRepositoryBase(IDatabaseUnitOfWork work, CacheHelper cache, ILogger logger, ISqlSyntaxProvider sqlSyntaxProvider) + : base(work, cache, logger) { + if (sqlSyntaxProvider == null) throw new ArgumentNullException("sqlSyntaxProvider"); + SqlSyntaxProvider = sqlSyntaxProvider; } - protected PetaPocoRepositoryBase(IDatabaseUnitOfWork work, IRepositoryCacheProvider cache) - : base(work, cache) - { - } - - /// + /// /// Returns the database Unit of Work added to the repository /// protected internal new IDatabaseUnitOfWork UnitOfWork diff --git a/src/Umbraco.Core/Persistence/Repositories/RecycleBinRepository.cs b/src/Umbraco.Core/Persistence/Repositories/RecycleBinRepository.cs index 02ac1035a6..0599afce82 100644 --- a/src/Umbraco.Core/Persistence/Repositories/RecycleBinRepository.cs +++ b/src/Umbraco.Core/Persistence/Repositories/RecycleBinRepository.cs @@ -7,8 +7,9 @@ using Umbraco.Core.IO; using Umbraco.Core.Logging; using Umbraco.Core.Models.EntityBase; using Umbraco.Core.Models.Rdbms; -using Umbraco.Core.Persistence.Caching; + using Umbraco.Core.Persistence.Querying; +using Umbraco.Core.Persistence.SqlSyntax; using Umbraco.Core.Persistence.UnitOfWork; namespace Umbraco.Core.Persistence.Repositories @@ -16,11 +17,8 @@ namespace Umbraco.Core.Persistence.Repositories internal abstract class RecycleBinRepository : VersionableRepositoryBase, IRecycleBinRepository where TEntity : class, IUmbracoEntity { - protected RecycleBinRepository(IDatabaseUnitOfWork work) : base(work) - { - } - - protected RecycleBinRepository(IDatabaseUnitOfWork work, IRepositoryCacheProvider cache) : base(work, cache) + protected RecycleBinRepository(IDatabaseUnitOfWork work, CacheHelper cache, ILogger logger, ISqlSyntaxProvider sqlSyntax) + : base(work, cache, logger, sqlSyntax) { } @@ -77,7 +75,7 @@ namespace Umbraco.Core.Persistence.Repositories catch (Exception ex) { trans.Dispose(); - LogHelper.Error>("An error occurred while emptying the Recycle Bin: " + ex.Message, ex); + Logger.Error>("An error occurred while emptying the Recycle Bin: " + ex.Message, ex); return false; } } @@ -120,7 +118,7 @@ namespace Umbraco.Core.Persistence.Repositories } catch (Exception e) { - LogHelper.Error>("An error occurred while deleting file attached to nodes: " + file, e); + Logger.Error>("An error occurred while deleting file attached to nodes: " + file, e); allsuccess = false; } }); diff --git a/src/Umbraco.Core/Persistence/Repositories/RelationRepository.cs b/src/Umbraco.Core/Persistence/Repositories/RelationRepository.cs index 8d5e0d7a8a..c9a6c2f96a 100644 --- a/src/Umbraco.Core/Persistence/Repositories/RelationRepository.cs +++ b/src/Umbraco.Core/Persistence/Repositories/RelationRepository.cs @@ -1,12 +1,14 @@ using System; using System.Collections.Generic; using System.Linq; +using Umbraco.Core.Logging; using Umbraco.Core.Models; using Umbraco.Core.Models.EntityBase; using Umbraco.Core.Models.Rdbms; -using Umbraco.Core.Persistence.Caching; + using Umbraco.Core.Persistence.Factories; using Umbraco.Core.Persistence.Querying; +using Umbraco.Core.Persistence.SqlSyntax; using Umbraco.Core.Persistence.UnitOfWork; namespace Umbraco.Core.Persistence.Repositories @@ -18,14 +20,8 @@ namespace Umbraco.Core.Persistence.Repositories { private readonly IRelationTypeRepository _relationTypeRepository; - public RelationRepository(IDatabaseUnitOfWork work, IRelationTypeRepository relationTypeRepository) - : base(work) - { - _relationTypeRepository = relationTypeRepository; - } - - public RelationRepository(IDatabaseUnitOfWork work, IRepositoryCacheProvider cache, IRelationTypeRepository relationTypeRepository) - : base(work, cache) + public RelationRepository(IDatabaseUnitOfWork work, CacheHelper cache, ILogger logger, ISqlSyntaxProvider sqlSyntax, IRelationTypeRepository relationTypeRepository) + : base(work, cache, logger, sqlSyntax) { _relationTypeRepository = relationTypeRepository; } @@ -55,6 +51,8 @@ namespace Umbraco.Core.Persistence.Repositories return entity; } + //TODO: Fix N+1 ! + protected override IEnumerable PerformGetAll(params int[] ids) { if (ids.Any()) diff --git a/src/Umbraco.Core/Persistence/Repositories/RelationTypeRepository.cs b/src/Umbraco.Core/Persistence/Repositories/RelationTypeRepository.cs index 8763fcddbf..228674d829 100644 --- a/src/Umbraco.Core/Persistence/Repositories/RelationTypeRepository.cs +++ b/src/Umbraco.Core/Persistence/Repositories/RelationTypeRepository.cs @@ -1,12 +1,14 @@ using System; using System.Collections.Generic; using System.Linq; +using Umbraco.Core.Logging; using Umbraco.Core.Models; using Umbraco.Core.Models.EntityBase; using Umbraco.Core.Models.Rdbms; -using Umbraco.Core.Persistence.Caching; + using Umbraco.Core.Persistence.Factories; using Umbraco.Core.Persistence.Querying; +using Umbraco.Core.Persistence.SqlSyntax; using Umbraco.Core.Persistence.UnitOfWork; namespace Umbraco.Core.Persistence.Repositories @@ -16,13 +18,9 @@ namespace Umbraco.Core.Persistence.Repositories /// internal class RelationTypeRepository : PetaPocoRepositoryBase, IRelationTypeRepository { - public RelationTypeRepository(IDatabaseUnitOfWork work) - : base(work) - { - } - public RelationTypeRepository(IDatabaseUnitOfWork work, IRepositoryCacheProvider cache) - : base(work, cache) + public RelationTypeRepository(IDatabaseUnitOfWork work, CacheHelper cache, ILogger logger, ISqlSyntaxProvider sqlSyntax) + : base(work, cache, logger, sqlSyntax) { } diff --git a/src/Umbraco.Core/Persistence/Repositories/RepositoryBase.cs b/src/Umbraco.Core/Persistence/Repositories/RepositoryBase.cs index 3d12cafc1f..ca33e16cf1 100644 --- a/src/Umbraco.Core/Persistence/Repositories/RepositoryBase.cs +++ b/src/Umbraco.Core/Persistence/Repositories/RepositoryBase.cs @@ -1,34 +1,26 @@ using System; using System.Collections.Generic; using System.Linq; +using Umbraco.Core.Cache; +using Umbraco.Core.Logging; using Umbraco.Core.Models.EntityBase; -using Umbraco.Core.Persistence.Caching; + using Umbraco.Core.Persistence.Querying; using Umbraco.Core.Persistence.UnitOfWork; namespace Umbraco.Core.Persistence.Repositories { - - /// - /// Represent an abstract Repository, which is the base of the Repository implementations - /// - /// Type of entity for which the repository is used - /// Type of the Id used for this entity - internal abstract class RepositoryBase : DisposableObject, IRepositoryQueryable, IUnitOfWorkRepository - where TEntity : class, IAggregateRoot + internal abstract class RepositoryBase : DisposableObject { private readonly IUnitOfWork _work; - private readonly IRepositoryCacheProvider _cache; + private readonly CacheHelper _cache; - protected RepositoryBase(IUnitOfWork work) - : this(work, RuntimeCacheProvider.Current) - { - } - - internal RepositoryBase(IUnitOfWork work, IRepositoryCacheProvider cache) + protected RepositoryBase(IUnitOfWork work, CacheHelper cache, ILogger logger) { if (work == null) throw new ArgumentNullException("work"); if (cache == null) throw new ArgumentNullException("cache"); + if (logger == null) throw new ArgumentNullException("logger"); + Logger = logger; _work = work; _cache = cache; } @@ -49,6 +41,37 @@ namespace Umbraco.Core.Persistence.Repositories get { return (Guid)_work.Key; } } + protected CacheHelper RepositoryCache + { + get { return _cache; } + } + + public static string GetCacheIdKey(object id) + { + return string.Format("{0}{1}", GetCacheTypeKey(), id); + } + + public static string GetCacheTypeKey() + { + return string.Format("uRepo_{0}_", typeof(T).Name); + } + + protected ILogger Logger { get; private set; } + } + + /// + /// Represent an abstract Repository, which is the base of the Repository implementations + /// + /// Type of entity for which the repository is used + /// Type of the Id used for this entity + internal abstract class RepositoryBase : RepositoryBase, IRepositoryQueryable, IUnitOfWorkRepository + where TEntity : class, IAggregateRoot + { + protected RepositoryBase(IUnitOfWork work, CacheHelper cache, ILogger logger) + : base(work, cache, logger) + { + } + #region IRepository Members /// @@ -60,11 +83,11 @@ namespace Umbraco.Core.Persistence.Repositories { if (entity.HasIdentity == false) { - _work.RegisterAdded(entity, this); + UnitOfWork.RegisterAdded(entity, this); } else { - _work.RegisterChanged(entity, this); + UnitOfWork.RegisterChanged(entity, this); } } @@ -74,9 +97,9 @@ namespace Umbraco.Core.Persistence.Repositories /// public virtual void Delete(TEntity entity) { - if (_work != null) + if (UnitOfWork != null) { - _work.RegisterRemoved(entity, this); + UnitOfWork.RegisterRemoved(entity, this); } } @@ -88,42 +111,33 @@ namespace Umbraco.Core.Persistence.Repositories /// public TEntity Get(TId id) { - var fromCache = TryGetFromCache(id); - if (fromCache.Success) - { - return fromCache.Result; - } - - var entity = PerformGet(id); - if (entity != null) - { - _cache.Save(typeof(TEntity), entity); - } - - if (entity != null) - { - //on initial construction we don't want to have dirty properties tracked - // http://issues.umbraco.org/issue/U4-1946 - var asEntity = entity as TracksChangesEntityBase; - if (asEntity != null) + return RepositoryCache.RuntimeCache.GetCacheItem( + GetCacheIdKey(id), () => { - asEntity.ResetDirtyProperties(false); - } - } - - return entity; + var entity = PerformGet(id); + if (entity == null) return null; + //on initial construction we don't want to have dirty properties tracked + // http://issues.umbraco.org/issue/U4-1946 + var asEntity = entity as TracksChangesEntityBase; + if (asEntity != null) + { + asEntity.ResetDirtyProperties(false); + } + return entity; + }); } - protected Attempt TryGetFromCache(TId id) - { - Guid key = id is int ? ConvertIdToGuid(id) : ConvertStringIdToGuid(id.ToString()); - var rEntity = _cache.GetById(typeof(TEntity), key); - if (rEntity != null) - { - return Attempt.Succeed((TEntity)rEntity); - } - return Attempt.Fail(); - } + + //protected Attempt TryGetFromCache(TId id) + //{ + // Guid key = id is int ? ConvertIdToGuid(id) : ConvertStringIdToGuid(id.ToString()); + // var rEntity = RepositoryCache.GetById(typeof(TEntity), key); + // if (rEntity != null) + // { + // return Attempt.Succeed((TEntity)rEntity); + // } + // return Attempt.Fail(); + //} protected abstract IEnumerable PerformGetAll(params TId[] ids); /// @@ -147,16 +161,20 @@ namespace Umbraco.Core.Persistence.Repositories if (ids.Any()) { - var entities = _cache.GetByIds( - typeof(TEntity), ids.Select(id => id is int ? ConvertIdToGuid(id) : ConvertStringIdToGuid(id.ToString())).ToList()) - .ToArray(); + var entities = ids.Select(x => RepositoryCache.RuntimeCache.GetCacheItem(GetCacheIdKey(x))).ToArray(); + + //var entities = RepositoryCache.GetByIds( + // typeof(TEntity), ids.Select(id => id is int ? ConvertIdToGuid(id) : ConvertStringIdToGuid(id.ToString())).ToList()) + // .ToArray(); if (ids.Count().Equals(entities.Count()) && entities.Any(x => x == null) == false) return entities.Select(x => (TEntity)x); } else { - var allEntities = _cache.GetAllByType(typeof(TEntity)).ToArray(); + var allEntities = RepositoryCache.RuntimeCache.GetCacheItemsByKeySearch(GetCacheTypeKey()).ToArray(); + + //var allEntities = RepositoryCache.GetAllByType(typeof(TEntity)).ToArray(); if (allEntities.Any()) { @@ -184,7 +202,9 @@ namespace Umbraco.Core.Persistence.Repositories { if (entity != null) { - _cache.Save(typeof(TEntity), entity); + var localCopy = entity; + RepositoryCache.RuntimeCache.InsertCacheItem(GetCacheIdKey(entity.Id), () => localCopy); + //RepositoryCache.Save(typeof(TEntity), entity); } } @@ -212,11 +232,16 @@ namespace Umbraco.Core.Persistence.Repositories /// public bool Exists(TId id) { - var fromCache = TryGetFromCache(id); - if (fromCache.Success) + var fromCache = RepositoryCache.RuntimeCache.GetCacheItem(GetCacheIdKey(id)); + if (fromCache != null) { return true; } + //var fromCache = TryGetFromCache(id); + //if (fromCache.Success) + //{ + // return true; + //} return PerformExists(id); } @@ -244,13 +269,15 @@ namespace Umbraco.Core.Persistence.Repositories try { PersistNewItem((TEntity)entity); - _cache.Save(typeof(TEntity), entity); + RepositoryCache.RuntimeCache.InsertCacheItem(GetCacheIdKey(entity.Id), () => entity); + //RepositoryCache.Save(typeof(TEntity), entity); } catch (Exception) { //if an exception is thrown we need to remove the entry from cache, this is ONLY a work around because of the way // that we cache entities: http://issues.umbraco.org/issue/U4-4259 - _cache.Delete(typeof(TEntity), entity); + //RepositoryCache.Delete(typeof(TEntity), entity); + RepositoryCache.RuntimeCache.ClearCacheItem(GetCacheIdKey(entity.Id)); throw; } @@ -265,13 +292,15 @@ namespace Umbraco.Core.Persistence.Repositories try { PersistUpdatedItem((TEntity)entity); - _cache.Save(typeof(TEntity), entity); + RepositoryCache.RuntimeCache.InsertCacheItem(GetCacheIdKey(entity.Id), () => entity); + //RepositoryCache.Save(typeof(TEntity), entity); } catch (Exception) { //if an exception is thrown we need to remove the entry from cache, this is ONLY a work around because of the way // that we cache entities: http://issues.umbraco.org/issue/U4-4259 - _cache.Delete(typeof(TEntity), entity); + //RepositoryCache.Delete(typeof(TEntity), entity); + RepositoryCache.RuntimeCache.ClearCacheItem(GetCacheIdKey(entity.Id)); throw; } @@ -284,7 +313,8 @@ namespace Umbraco.Core.Persistence.Repositories public virtual void PersistDeletedItem(IEntity entity) { PersistDeletedItem((TEntity)entity); - _cache.Delete(typeof(TEntity), entity); + //RepositoryCache.Delete(typeof(TEntity), entity); + RepositoryCache.RuntimeCache.ClearCacheItem(GetCacheIdKey(entity.Id)); } #endregion @@ -297,29 +327,29 @@ namespace Umbraco.Core.Persistence.Repositories #endregion - /// - /// Internal method that handles the convertion of an object Id - /// to an Integer and then a Guid Id. - /// - /// In the future it should be possible to change this method - /// so it converts from object to guid if/when we decide to go from - /// int to guid based ids. - /// - /// - protected virtual Guid ConvertIdToGuid(TId id) - { - int i = 0; - if (int.TryParse(id.ToString(), out i)) - { - return i.ToGuid(); - } - return ConvertStringIdToGuid(id.ToString()); - } + ///// + ///// Internal method that handles the convertion of an object Id + ///// to an Integer and then a Guid Id. + ///// + ///// In the future it should be possible to change this method + ///// so it converts from object to guid if/when we decide to go from + ///// int to guid based ids. + ///// + ///// + //protected virtual Guid ConvertIdToGuid(TId id) + //{ + // int i = 0; + // if (int.TryParse(id.ToString(), out i)) + // { + // return i.ToGuid(); + // } + // return ConvertStringIdToGuid(id.ToString()); + //} - protected virtual Guid ConvertStringIdToGuid(string id) - { - return id.EncodeAsGuid(); - } + //protected virtual Guid ConvertStringIdToGuid(string id) + //{ + // return id.EncodeAsGuid(); + //} /// /// Dispose disposable properties diff --git a/src/Umbraco.Core/Persistence/Repositories/ScriptRepository.cs b/src/Umbraco.Core/Persistence/Repositories/ScriptRepository.cs index a14507e8a4..b48e096e3f 100644 --- a/src/Umbraco.Core/Persistence/Repositories/ScriptRepository.cs +++ b/src/Umbraco.Core/Persistence/Repositories/ScriptRepository.cs @@ -1,7 +1,9 @@ -using System.Collections.Generic; +using System; +using System.Collections.Generic; using System.IO; using System.Linq; using System.Text; +using Umbraco.Core.Configuration.UmbracoSettings; using Umbraco.Core.IO; using Umbraco.Core.Models; using Umbraco.Core.Persistence.UnitOfWork; @@ -13,14 +15,13 @@ namespace Umbraco.Core.Persistence.Repositories /// internal class ScriptRepository : FileRepository, IScriptRepository { - internal ScriptRepository(IUnitOfWork work, IFileSystem fileSystem) - : base(work, fileSystem) - { - } + private readonly IContentSection _contentConfig; - public ScriptRepository(IUnitOfWork work) - : this(work, new PhysicalFileSystem(SystemDirectories.Scripts)) + public ScriptRepository(IUnitOfWork work, IFileSystem fileSystem, IContentSection contentConfig) + : base(work, fileSystem) { + if (contentConfig == null) throw new ArgumentNullException("contentConfig"); + _contentConfig = contentConfig; } #region Implementation of IRepository @@ -77,7 +78,7 @@ namespace Umbraco.Core.Persistence.Repositories } else { - var files = FindAllFiles(""); + var files = FindAllFiles("", "*.*"); foreach (var file in files) { yield return Get(file); @@ -85,6 +86,33 @@ namespace Umbraco.Core.Persistence.Repositories } } + public bool ValidateScript(Script script) + { + //NOTE Since a script file can be both JS, Razor Views, Razor Macros and Xslt + //it might be an idea to create validations for all 3 and divide the validation + //into 4 private methods. + //See codeEditorSave.asmx.cs for reference. + + var exts = _contentConfig.ScriptFileTypes.ToList(); + /*if (UmbracoSettings.DefaultRenderingEngine == RenderingEngine.Mvc) + { + exts.Add("cshtml"); + exts.Add("vbhtml"); + }*/ + + var dirs = SystemDirectories.Scripts; + /*if (UmbracoSettings.DefaultRenderingEngine == RenderingEngine.Mvc) + dirs += "," + SystemDirectories.MvcViews;*/ + + //Validate file + var validFile = IOHelper.VerifyEditPath(script.VirtualPath, dirs.Split(',')); + + //Validate extension + var validExtension = IOHelper.VerifyFileExtension(script.VirtualPath, exts); + + return validFile && validExtension; + } + #endregion } } \ No newline at end of file diff --git a/src/Umbraco.Core/Persistence/Repositories/ServerRegistrationRepository.cs b/src/Umbraco.Core/Persistence/Repositories/ServerRegistrationRepository.cs index 410bbe1585..020ae2e9cf 100644 --- a/src/Umbraco.Core/Persistence/Repositories/ServerRegistrationRepository.cs +++ b/src/Umbraco.Core/Persistence/Repositories/ServerRegistrationRepository.cs @@ -1,25 +1,22 @@ using System; using System.Collections.Generic; using System.Linq; +using Umbraco.Core.Logging; using Umbraco.Core.Models; using Umbraco.Core.Models.EntityBase; using Umbraco.Core.Models.Rdbms; -using Umbraco.Core.Persistence.Caching; + using Umbraco.Core.Persistence.Factories; using Umbraco.Core.Persistence.Querying; +using Umbraco.Core.Persistence.SqlSyntax; using Umbraco.Core.Persistence.UnitOfWork; namespace Umbraco.Core.Persistence.Repositories { internal class ServerRegistrationRepository : PetaPocoRepositoryBase { - public ServerRegistrationRepository(IDatabaseUnitOfWork work) - : base(work) - { - } - - public ServerRegistrationRepository(IDatabaseUnitOfWork work, IRepositoryCacheProvider cache) - : base(work, cache) + public ServerRegistrationRepository(IDatabaseUnitOfWork work, CacheHelper cache, ILogger logger, ISqlSyntaxProvider sqlSyntax) + : base(work, cache, logger, sqlSyntax) { } diff --git a/src/Umbraco.Core/Persistence/Repositories/SimpleGetRepository.cs b/src/Umbraco.Core/Persistence/Repositories/SimpleGetRepository.cs new file mode 100644 index 0000000000..63527c7fb9 --- /dev/null +++ b/src/Umbraco.Core/Persistence/Repositories/SimpleGetRepository.cs @@ -0,0 +1,100 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using Umbraco.Core.Logging; +using Umbraco.Core.Models.EntityBase; + +using Umbraco.Core.Persistence.Querying; +using Umbraco.Core.Persistence.SqlSyntax; +using Umbraco.Core.Persistence.UnitOfWork; + +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 + where TEntity : class, IAggregateRoot + where TDto: class + { + + protected SimpleGetRepository(IDatabaseUnitOfWork work, CacheHelper cache, ILogger logger, ISqlSyntaxProvider sqlSyntax) + : base(work, cache, logger, sqlSyntax) + { + } + + protected abstract TEntity ConvertToEntity(TDto dto); + protected abstract object GetBaseWhereClauseArguments(TId id); + protected abstract string GetWhereInClauseForGetAll(); + + protected virtual IEnumerable PerformFetch(Sql sql) + { + return Database.Fetch(sql); + } + + protected override TEntity PerformGet(TId id) + { + var sql = GetBaseQuery(false); + sql.Where(GetBaseWhereClause(), GetBaseWhereClauseArguments(id)); + + var dto = PerformFetch(sql).FirstOrDefault(); + if (dto == null) + return null; + + var entity = ConvertToEntity(dto); + + var dirtyEntity = entity as Entity; + if (dirtyEntity != null) + { + //on initial construction we don't want to have dirty properties tracked + // http://issues.umbraco.org/issue/U4-1946 + dirtyEntity.ResetDirtyProperties(false); + } + + return entity; + } + + protected override IEnumerable PerformGetAll(params TId[] ids) + { + var sql = new Sql().From(); + + if (ids.Any()) + { + sql.Where(GetWhereInClauseForGetAll(), new { ids = ids }); + } + + return Database.Fetch(sql).Select(ConvertToEntity); + } + + protected override sealed IEnumerable PerformGetByQuery(IQuery query) + { + var sqlClause = GetBaseQuery(false); + var translator = new SqlTranslator(sqlClause, query); + var sql = translator.Translate(); + return Database.Fetch(sql).Select(ConvertToEntity); + } + + #region Not implemented and not required + + protected override sealed IEnumerable GetDeleteClauses() + { + throw new NotImplementedException(); + } + + protected override sealed Guid NodeObjectTypeId + { + get { throw new NotImplementedException(); } + } + + protected override sealed void PersistNewItem(TEntity entity) + { + throw new NotImplementedException(); + } + + protected override sealed void PersistUpdatedItem(TEntity entity) + { + throw new NotImplementedException(); + } + #endregion + } +} \ No newline at end of file diff --git a/src/Umbraco.Core/Persistence/Repositories/StylesheetRepository.cs b/src/Umbraco.Core/Persistence/Repositories/StylesheetRepository.cs index 5537d65f07..67986eebcc 100644 --- a/src/Umbraco.Core/Persistence/Repositories/StylesheetRepository.cs +++ b/src/Umbraco.Core/Persistence/Repositories/StylesheetRepository.cs @@ -15,16 +15,9 @@ namespace Umbraco.Core.Persistence.Repositories /// internal class StylesheetRepository : FileRepository, IStylesheetRepository { - private readonly IDatabaseUnitOfWork _dbwork; - - internal StylesheetRepository(IUnitOfWork work, IDatabaseUnitOfWork db, IFileSystem fileSystem) + + public StylesheetRepository(IUnitOfWork work, IFileSystem fileSystem) : base(work, fileSystem) - { - _dbwork = db; - } - - public StylesheetRepository(IUnitOfWork work, IDatabaseUnitOfWork db) - : this(work, db, new PhysicalFileSystem(SystemDirectories.Css)) { } @@ -34,17 +27,15 @@ namespace Umbraco.Core.Persistence.Repositories { if (FileSystem.FileExists(id) == false) { - throw new Exception(string.Format("The file {0} was not found", id)); + return null; } - var content = string.Empty; + string content; using (var stream = FileSystem.OpenFile(id)) + using (var reader = new StreamReader(stream, Encoding.UTF8)) { - byte[] bytes = new byte[stream.Length]; - stream.Position = 0; - stream.Read(bytes, 0, (int)stream.Length); - content = Encoding.UTF8.GetString(bytes); + content = reader.ReadToEnd(); } var path = FileSystem.GetRelativePath(id); @@ -57,7 +48,7 @@ namespace Umbraco.Core.Persistence.Repositories Key = path.EncodeAsGuid(), CreateDate = created, UpdateDate = updated, - Id = GetStylesheetId(path), + Id = path.GetHashCode(), VirtualPath = FileSystem.GetUrl(id) }; @@ -69,45 +60,6 @@ namespace Umbraco.Core.Persistence.Repositories } - // Fix for missing Id's on FileService.GetStylesheets() call. This is needed as sytlesheets can only bo loaded in the editor via - // their Id so listing stylesheets needs to list there Id as well for custom plugins to render the build in editor. - // http://issues.umbraco.org/issue/U4-3258 - private int GetStylesheetId(string path) - { - var sql = new Sql() - .Select("*") - .From() - .Where("nodeObjectType = @NodeObjectType AND umbracoNode.text = @Alias", - new - { - NodeObjectType = UmbracoObjectTypes.Stylesheet.GetGuid(), - Alias = path.TrimEnd(".css").Replace("\\", "/") - }); - var nodeDto = _dbwork.Database.FirstOrDefault(sql); - return nodeDto == null ? 0 : nodeDto.NodeId; - } - - //This should be used later to do GetAll properly without individual selections - private IEnumerable> GetStylesheetIds(string[] paths) - { - var sql = new Sql() - .Select("*") - .From() - .Where("nodeObjectType = @NodeObjectType AND umbracoNode.text in (@aliases)", - new - { - NodeObjectType = UmbracoObjectTypes.Stylesheet.GetGuid(), - aliases = paths.Select(x => x.TrimEnd(".css").Replace("\\", "/")).ToArray() - }); - var dtos = _dbwork.Database.Fetch(sql); - - return dtos.Select(x => new Tuple( - //the id - x.NodeId, - //the original path requested for the id - paths.First(p => p.TrimEnd(".css").Replace("\\", "/") == x.Text))); - } - public override IEnumerable GetAll(params string[] ids) { //ensure they are de-duplicated, easy win if people don't do this as this can cause many excess queries @@ -122,7 +74,7 @@ namespace Umbraco.Core.Persistence.Repositories } else { - var files = FindAllFiles(""); + var files = FindAllFiles("", "*.css"); foreach (var file in files) { yield return Get(file); @@ -130,6 +82,33 @@ namespace Umbraco.Core.Persistence.Repositories } } + /// + /// Gets a list of all that exist at the relative path specified. + /// + /// + /// If null or not specified, will return the stylesheets at the root path relative to the IFileSystem + /// + /// + public IEnumerable GetStylesheetsAtPath(string rootPath = null) + { + return FileSystem.GetFiles(rootPath ?? string.Empty, "*.css").Select(Get); + } + + public bool ValidateStylesheet(Stylesheet stylesheet) + { + var dirs = SystemDirectories.Css; + + //Validate file + var validFile = IOHelper.VerifyEditPath(stylesheet.VirtualPath, dirs.Split(',')); + + //Validate extension + var validExtension = IOHelper.VerifyFileExtension(stylesheet.VirtualPath, new List { "css" }); + + var fileValid = validFile && validExtension; + + return fileValid; + } + #endregion } } \ No newline at end of file diff --git a/src/Umbraco.Core/Persistence/Repositories/TagRepository.cs b/src/Umbraco.Core/Persistence/Repositories/TagRepository.cs index ac39d9556e..0f0ed659e4 100644 --- a/src/Umbraco.Core/Persistence/Repositories/TagRepository.cs +++ b/src/Umbraco.Core/Persistence/Repositories/TagRepository.cs @@ -2,10 +2,11 @@ using System.Collections.Generic; using System.Linq; using System.Text; +using Umbraco.Core.Logging; using Umbraco.Core.Models; using Umbraco.Core.Models.EntityBase; using Umbraco.Core.Models.Rdbms; -using Umbraco.Core.Persistence.Caching; + using Umbraco.Core.Persistence.Factories; using Umbraco.Core.Persistence.Querying; using Umbraco.Core.Persistence.SqlSyntax; @@ -15,13 +16,8 @@ namespace Umbraco.Core.Persistence.Repositories { internal class TagRepository : PetaPocoRepositoryBase, ITagRepository { - protected TagRepository(IDatabaseUnitOfWork work) - : this(work, RuntimeCacheProvider.Current) - { - } - - internal TagRepository(IDatabaseUnitOfWork work, IRepositoryCacheProvider cache) - : base(work, cache) + internal TagRepository(IDatabaseUnitOfWork work, CacheHelper cache, ILogger logger, ISqlSyntaxProvider sqlSyntax) + : base(work, cache, logger, sqlSyntax) { } @@ -169,7 +165,7 @@ namespace Umbraco.Core.Persistence.Repositories public IEnumerable GetTaggedEntitiesByTagGroup(TaggableObjectTypes objectType, string tagGroup) { var sql = new Sql() - .Select("cmsTagRelationship.nodeId, cmsPropertyType.Alias, cmsPropertyType.id as propertyTypeId, cmsTags.tag, cmsTags.id as tagId, cmsTags." + SqlSyntaxContext.SqlSyntaxProvider.GetQuotedColumnName("group")) + .Select("cmsTagRelationship.nodeId, cmsPropertyType.Alias, cmsPropertyType.id as propertyTypeId, cmsTags.tag, cmsTags.id as tagId, cmsTags." + SqlSyntaxProvider.GetQuotedColumnName("group")) .From() .InnerJoin() .On(left => left.TagId, right => right.Id) @@ -195,7 +191,7 @@ namespace Umbraco.Core.Persistence.Repositories public IEnumerable GetTaggedEntitiesByTag(TaggableObjectTypes objectType, string tag, string tagGroup = null) { var sql = new Sql() - .Select("cmsTagRelationship.nodeId, cmsPropertyType.Alias, cmsPropertyType.id as propertyTypeId, cmsTags.tag, cmsTags.id as tagId, cmsTags." + SqlSyntaxContext.SqlSyntaxProvider.GetQuotedColumnName("group")) + .Select("cmsTagRelationship.nodeId, cmsPropertyType.Alias, cmsPropertyType.id as propertyTypeId, cmsTags.tag, cmsTags.id as tagId, cmsTags." + SqlSyntaxProvider.GetQuotedColumnName("group")) .From() .InnerJoin() .On(left => left.TagId, right => right.Id) @@ -302,7 +298,7 @@ namespace Umbraco.Core.Persistence.Repositories if (withGrouping) { - sql = sql.Select("cmsTags.Id, cmsTags.Tag, cmsTags." + SqlSyntaxContext.SqlSyntaxProvider.GetQuotedColumnName("Group") + @", Count(*) NodeCount"); + sql = sql.Select("cmsTags.Id, cmsTags.Tag, cmsTags." + SqlSyntaxProvider.GetQuotedColumnName("Group") + @", Count(*) NodeCount"); } else { @@ -332,7 +328,7 @@ namespace Umbraco.Core.Persistence.Repositories private Sql ApplyGroupByToTagsQuery(Sql sql) { - return sql.GroupBy(new string[] { "cmsTags.Id", "cmsTags.Tag", "cmsTags." + SqlSyntaxContext.SqlSyntaxProvider.GetQuotedColumnName("Group") + @"" }); + return sql.GroupBy(new string[] { "cmsTags.Id", "cmsTags.Tag", "cmsTags." + SqlSyntaxProvider.GetQuotedColumnName("Group") + @"" }); } private IEnumerable ExecuteTagsQuery(Sql sql) @@ -389,16 +385,16 @@ namespace Umbraco.Core.Persistence.Repositories //adds any tags found in the collection that aren't in cmsTag var insertTagsSql = string.Concat("insert into cmsTags (Tag,", - SqlSyntaxContext.SqlSyntaxProvider.GetQuotedColumnName("Group"), + SqlSyntaxProvider.GetQuotedColumnName("Group"), ") ", " select TagSet.Tag, TagSet.", - SqlSyntaxContext.SqlSyntaxProvider.GetQuotedColumnName("Group"), + SqlSyntaxProvider.GetQuotedColumnName("Group"), " from ", tagSetSql, " left outer join cmsTags on (TagSet.Tag = cmsTags.Tag and TagSet.", - SqlSyntaxContext.SqlSyntaxProvider.GetQuotedColumnName("Group"), + SqlSyntaxProvider.GetQuotedColumnName("Group"), " = cmsTags.", - SqlSyntaxContext.SqlSyntaxProvider.GetQuotedColumnName("Group"), + SqlSyntaxProvider.GetQuotedColumnName("Group"), ")", " where cmsTags.Id is null "); //insert the tags that don't exist @@ -417,9 +413,9 @@ namespace Umbraco.Core.Persistence.Repositories "select NewTags.Id from ", tagSetSql, " inner join cmsTags as NewTags on (TagSet.Tag = NewTags.Tag and TagSet.", - SqlSyntaxContext.SqlSyntaxProvider.GetQuotedColumnName("Group"), + SqlSyntaxProvider.GetQuotedColumnName("Group"), " = TagSet.", - SqlSyntaxContext.SqlSyntaxProvider.GetQuotedColumnName("Group"), + SqlSyntaxProvider.GetQuotedColumnName("Group"), ") ", ") as NewTagsSet ", "left outer join cmsTagRelationship ", @@ -455,7 +451,7 @@ namespace Umbraco.Core.Persistence.Repositories " AND tagId IN ", "(SELECT id FROM cmsTags INNER JOIN ", tagSetSql, - " ON (TagSet.Tag = cmsTags.Tag and TagSet." + SqlSyntaxContext.SqlSyntaxProvider.GetQuotedColumnName("Group") + @" = cmsTags." + SqlSyntaxContext.SqlSyntaxProvider.GetQuotedColumnName("Group") + @"))"); + " ON (TagSet.Tag = cmsTags.Tag and TagSet." + SqlSyntaxProvider.GetQuotedColumnName("Group") + @" = cmsTags." + SqlSyntaxProvider.GetQuotedColumnName("Group") + @"))"); Database.Execute(deleteSql); } @@ -499,7 +495,7 @@ namespace Umbraco.Core.Persistence.Repositories /// /// /// - private static string GetTagSet(IEnumerable tagsToInsert) + private string GetTagSet(IEnumerable tagsToInsert) { //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! @@ -507,7 +503,7 @@ namespace Umbraco.Core.Persistence.Repositories var array = tagsToInsert .Select(tag => - string.Format("select '{0}' as Tag, '{1}' as " + SqlSyntaxContext.SqlSyntaxProvider.GetQuotedColumnName("Group") + @"", + string.Format("select '{0}' as Tag, '{1}' as " + SqlSyntaxProvider.GetQuotedColumnName("Group") + @"", PetaPocoExtensions.EscapeAtSymbols(tag.Text.Replace("'", "''")), tag.Group)) .ToArray(); return "(" + string.Join(" union ", array).Replace(" ", " ") + ") as TagSet"; diff --git a/src/Umbraco.Core/Persistence/Repositories/TemplateRepository.cs b/src/Umbraco.Core/Persistence/Repositories/TemplateRepository.cs index 26e6ec3469..ad79cfc44a 100644 --- a/src/Umbraco.Core/Persistence/Repositories/TemplateRepository.cs +++ b/src/Umbraco.Core/Persistence/Repositories/TemplateRepository.cs @@ -4,14 +4,20 @@ using System.Globalization; using System.IO; using System.Linq; using System.Text; +using Umbraco.Core.Configuration; +using Umbraco.Core.Configuration.UmbracoSettings; using Umbraco.Core.IO; +using Umbraco.Core.Logging; using Umbraco.Core.Models; using Umbraco.Core.Models.EntityBase; using Umbraco.Core.Models.Rdbms; -using Umbraco.Core.Persistence.Caching; + using Umbraco.Core.Persistence.Factories; using Umbraco.Core.Persistence.Querying; +using Umbraco.Core.Persistence.SqlSyntax; using Umbraco.Core.Persistence.UnitOfWork; +using Umbraco.Core.Services; +using Umbraco.Core.Strings; using Umbraco.Core.Sync; namespace Umbraco.Core.Persistence.Repositories @@ -21,39 +27,28 @@ namespace Umbraco.Core.Persistence.Repositories /// internal class TemplateRepository : PetaPocoRepositoryBase, ITemplateRepository { - private IFileSystem _masterpagesFileSystem; - private IFileSystem _viewsFileSystem; + private readonly IFileSystem _masterpagesFileSystem; + private readonly IFileSystem _viewsFileSystem; + private readonly ITemplatesSection _templateConfig; + private readonly ViewHelper _viewHelper; + private readonly MasterPageHelper _masterPageHelper; - public TemplateRepository(IDatabaseUnitOfWork work) - : base(work) - { - EnsureDependencies(); - } - - public TemplateRepository(IDatabaseUnitOfWork work, IRepositoryCacheProvider cache) - : base(work, cache) - { - EnsureDependencies(); - } - - internal TemplateRepository(IDatabaseUnitOfWork work, IRepositoryCacheProvider cache, IFileSystem masterpageFileSystem, IFileSystem viewFileSystem) - : base(work, cache) + internal TemplateRepository(IDatabaseUnitOfWork work, CacheHelper cache, ILogger logger, ISqlSyntaxProvider sqlSyntax, IFileSystem masterpageFileSystem, IFileSystem viewFileSystem, ITemplatesSection templateConfig) + : base(work, cache, logger, sqlSyntax) { _masterpagesFileSystem = masterpageFileSystem; _viewsFileSystem = viewFileSystem; + _templateConfig = templateConfig; + _viewHelper = new ViewHelper(_viewsFileSystem); + _masterPageHelper = new MasterPageHelper(_masterpagesFileSystem); } - private void EnsureDependencies() - { - _masterpagesFileSystem = new PhysicalFileSystem(SystemDirectories.Masterpages); - _viewsFileSystem = new PhysicalFileSystem(SystemDirectories.MvcViews); - } - + #region Overrides of RepositoryBase protected override ITemplate PerformGet(int id) { - return GetAll(new[] {id}).FirstOrDefault(); + return GetAll(new[] { id }).FirstOrDefault(); } protected override IEnumerable PerformGetAll(params int[] ids) @@ -62,16 +57,34 @@ namespace Umbraco.Core.Persistence.Repositories if (ids.Any()) { - sql.Where("umbracoNode.id in (@ids)", new {ids = ids}); + sql.Where("umbracoNode.id in (@ids)", new { ids = ids }); } else { sql.Where(x => x.NodeObjectType == NodeObjectTypeId); } - + var dtos = Database.Fetch(sql); - return dtos.Select(MapFromDto); + if (dtos.Count == 0) return Enumerable.Empty(); + + //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() + .Select("nodeId,alias,parentID") + .From() + .InnerJoin() + .On(dto => dto.NodeId, dto => dto.NodeId) + .Where(t => t.ParentId > 0); + var childIds = Database.Fetch(childIdsSql) + .Select(x => new UmbracoEntity + { + Id = x.nodeId, + ParentId = x.parentID, + Name = x.alias + }); + + return dtos.Select(d => MapFromDto(d, childIds)); } protected override IEnumerable PerformGetByQuery(IQuery query) @@ -82,7 +95,25 @@ namespace Umbraco.Core.Persistence.Repositories var dtos = Database.Fetch(sql); - return dtos.Select(MapFromDto); + if (dtos.Count == 0) return Enumerable.Empty(); + + //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() + .Select("nodeId,alias,parentID") + .From() + .InnerJoin() + .On(dto => dto.NodeId, dto => dto.NodeId) + .Where(t => t.ParentId > 0); + var childIds = Database.Fetch(childIdsSql) + .Select(x => new UmbracoEntity + { + Id = x.nodeId, + ParentId = x.parentID, + Name = x.alias + }); + + return dtos.Select(d => MapFromDto(d, childIds)); } #endregion @@ -107,7 +138,6 @@ namespace Umbraco.Core.Persistence.Repositories protected override IEnumerable GetDeleteClauses() { - //TODO check for references in DocumentDto and remove value (nullable) var list = new List { "DELETE FROM umbracoUser2NodeNotify WHERE nodeId = @Id", @@ -127,49 +157,30 @@ namespace Umbraco.Core.Persistence.Repositories protected override void PersistNewItem(ITemplate entity) { - var data = Encoding.UTF8.GetBytes(entity.Content); - var withBom = Encoding.UTF8.GetPreamble().Concat(data).ToArray(); - - using (var stream = new MemoryStream(withBom)) - { - if (entity.GetTypeOfRenderingEngine() == RenderingEngine.Mvc) - { - string viewName = string.Concat(entity.Alias, ".cshtml"); - _viewsFileSystem.AddFile(viewName, stream, true); - } - else - { - string masterpageName = string.Concat(entity.Alias, ".master"); - _masterpagesFileSystem.AddFile(masterpageName, stream, true); - } - } - - //TODO Possibly ensure unique alias here (as is done in the legacy Template class)? + EnsureValidAlias(entity); //Save to db - var template = entity as Template; + var template = (Template)entity; template.AddingEntity(); var factory = new TemplateFactory(NodeObjectTypeId); var dto = factory.BuildDto(template); - //NOTE Should the logic below have some kind of fallback for empty parent ids ? - //Logic for setting Path, Level and SortOrder - var parent = Database.First("WHERE id = @ParentId", new { ParentId = template.ParentId }); - int level = parent.Level + 1; - int sortOrder = - Database.ExecuteScalar("SELECT COUNT(*) FROM umbracoNode WHERE parentID = @ParentId AND nodeObjectType = @NodeObjectType", - new { ParentId = template.ParentId, NodeObjectType = NodeObjectTypeId }); - //Create the (base) node data - umbracoNode var nodeDto = dto.NodeDto; - nodeDto.Path = parent.Path; - nodeDto.Level = short.Parse(level.ToString(CultureInfo.InvariantCulture)); - nodeDto.SortOrder = sortOrder; + nodeDto.Path = "-1," + dto.NodeDto.NodeId; 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); + var parent = Get(template.MasterTemplateId.Value); + if (parent != null) + { + nodeDto.Path = string.Concat(parent.Path, ",", nodeDto.NodeId); + } + else + { + nodeDto.Path = "-1," + dto.NodeDto.NodeId; + } Database.Update(nodeDto); //Insert template dto @@ -179,54 +190,95 @@ namespace Umbraco.Core.Persistence.Repositories //Update entity with correct values template.Id = nodeDto.NodeId; //Set Id on entity to ensure an Id is set template.Path = nodeDto.Path; - template.SortOrder = sortOrder; - template.Level = level; + + //now do the file work + + if (DetermineTemplateRenderingEngine(entity) == RenderingEngine.Mvc) + { + var result = _viewHelper.CreateView(template, true); + if (result != entity.Content) + { + entity.Content = result; + //re-persist it... though we don't really care about the templates in the db do we??!! + dto.Design = result; + Database.Update(dto); + } + } + else + { + var result = _masterPageHelper.CreateMasterPage(template, this, true); + if (result != entity.Content) + { + entity.Content = result; + //re-persist it... though we don't really care about the templates in the db do we??!! + dto.Design = result; + Database.Update(dto); + } + } template.ResetDirtyProperties(); } protected override void PersistUpdatedItem(ITemplate entity) { - var data = Encoding.UTF8.GetBytes(entity.Content); - var withBom = Encoding.UTF8.GetPreamble().Concat(data).ToArray(); + EnsureValidAlias(entity); - using (var stream = new MemoryStream(withBom)) + //store the changed alias if there is one for use with updating files later + var originalAlias = entity.Alias; + if (entity.IsPropertyDirty("Alias")) { - if (entity.GetTypeOfRenderingEngine() == RenderingEngine.Mvc) - { - string viewName = string.Concat(entity.Alias, ".cshtml"); - _viewsFileSystem.AddFile(viewName, stream, true); - } - else - { - string masterpageName = string.Concat(entity.Alias, ".master"); - _masterpagesFileSystem.AddFile(masterpageName, stream, true); - } + //we need to check what it currently is before saving and remove that file + var current = Get(entity.Id); + originalAlias = current.Alias; } - //Look up parent to get and set the correct Path if ParentId has changed - if (entity.IsPropertyDirty("ParentId")) + var template = (Template)entity; + + if (entity.IsPropertyDirty("MasterTemplateId")) { - var parent = Database.First("WHERE id = @ParentId", new { ParentId = ((Template)entity).ParentId }); - entity.Path = string.Concat(parent.Path, ",", entity.Id); - ((Template)entity).Level = parent.Level + 1; - var maxSortOrder = - Database.ExecuteScalar( - "SELECT coalesce(max(sortOrder),0) FROM umbracoNode WHERE parentid = @ParentId AND nodeObjectType = @NodeObjectType", - new { ParentId = ((Template)entity).ParentId, NodeObjectType = NodeObjectTypeId }); - ((Template)entity).SortOrder = maxSortOrder + 1; + var parent = Get(template.MasterTemplateId.Value); + if (parent != null) + { + entity.Path = string.Concat(parent.Path, ",", entity.Id); + } + } //Get TemplateDto from db to get the Primary key of the entity var templateDto = Database.SingleOrDefault("WHERE nodeId = @Id", new { Id = entity.Id }); //Save updated entity to db - var template = entity as Template; + template.UpdateDate = DateTime.Now; var factory = new TemplateFactory(templateDto.PrimaryKey, NodeObjectTypeId); var dto = factory.BuildDto(template); Database.Update(dto.NodeDto); Database.Update(dto); + + //now do the file work + + if (DetermineTemplateRenderingEngine(entity) == RenderingEngine.Mvc) + { + var result = _viewHelper.UpdateViewFile(entity, originalAlias); + if (result != entity.Content) + { + entity.Content = result; + //re-persist it... though we don't really care about the templates in the db do we??!! + dto.Design = result; + Database.Update(dto); + } + } + else + { + var result = _masterPageHelper.UpdateMasterPageFile(entity, originalAlias, this); + if (result != entity.Content) + { + entity.Content = result; + //re-persist it... though we don't really care about the templates in the db do we??!! + dto.Design = result; + Database.Update(dto); + } + } entity.ResetDirtyProperties(); } @@ -241,11 +293,12 @@ namespace Umbraco.Core.Persistence.Repositories // to it, then in the PersistDeletedTemplate we wouldn't recurse the underlying function, we'd just call // PersistDeletedItem with a Template object and clear it's cache. - var sql = new Sql(); - sql.Select("*").From().Where(dto => dto.Master != null || dto.NodeId == entity.Id); - var dtos = Database.Fetch(sql); + var sql = GetBaseQuery(false).Where(dto => dto.ParentId > 0 || dto.NodeId == entity.Id); + + var dtos = Database.Fetch(sql); + var self = dtos.Single(x => x.NodeId == entity.Id); - var allChildren = dtos.Except(new[] {self}); + var allChildren = dtos.Except(new[] { self }); var hierarchy = GenerateTemplateHierarchy(self, allChildren); //remove ourselves hierarchy.Remove(self); @@ -261,46 +314,38 @@ namespace Umbraco.Core.Persistence.Repositories //now we can delete this one base.PersistDeletedItem(entity); - //Check for file under the Masterpages filesystem - if (_masterpagesFileSystem.FileExists(entity.Name)) + if (DetermineTemplateRenderingEngine(entity) == RenderingEngine.Mvc) { - _masterpagesFileSystem.DeleteFile(entity.Name); + var viewName = string.Concat(entity.Alias, ".cshtml"); + _viewsFileSystem.DeleteFile(viewName); } - else if (_masterpagesFileSystem.FileExists(entity.Path)) + else { - _masterpagesFileSystem.DeleteFile(entity.Path); + var masterpageName = string.Concat(entity.Alias, ".master"); + _masterpagesFileSystem.DeleteFile(masterpageName); } - //Check for file under the Views/Mvc filesystem - if (_viewsFileSystem.FileExists(entity.Name)) - { - _viewsFileSystem.DeleteFile(entity.Name); - } - else if (_viewsFileSystem.FileExists(entity.Path)) - { - _viewsFileSystem.DeleteFile(entity.Path); - } } #endregion - private ITemplate MapFromDto(TemplateDto dto) + private ITemplate MapFromDto(TemplateDto dto, IEnumerable childDefinitions) { string csViewName = string.Concat(dto.Alias, ".cshtml"); string vbViewName = string.Concat(dto.Alias, ".vbhtml"); string masterpageName = string.Concat(dto.Alias, ".master"); var factory = new TemplateFactory(); - var template = factory.BuildEntity(dto); + var template = factory.BuildEntity(dto, childDefinitions); - if (dto.Master.HasValue) + if (dto.NodeDto.ParentId > 0) { //TODO: Fix this n+1 query! - var masterTemplate = Get(dto.Master.Value); + var masterTemplate = Get(dto.NodeDto.ParentId); if (masterTemplate != null) { template.MasterTemplateAlias = masterTemplate.Alias; - template.MasterTemplateId = new Lazy(() => dto.Master.Value); + template.MasterTemplateId = new Lazy(() => dto.NodeDto.ParentId); } } @@ -349,7 +394,7 @@ namespace Umbraco.Core.Persistence.Repositories private static List GenerateTemplateHierarchy(TemplateDto template, IEnumerable allChildTemplates) { var hierarchy = new List { template }; - foreach (var t in allChildTemplates.Where(x => x.Master == template.NodeId)) + foreach (var t in allChildTemplates.Where(x => x.NodeDto.ParentId == template.NodeId)) { hierarchy.AddRange(GenerateTemplateHierarchy(t, allChildTemplates)); } @@ -359,27 +404,20 @@ namespace Umbraco.Core.Persistence.Repositories private void PopulateViewTemplate(ITemplate template, string fileName) { string content; - var path = string.Empty; using (var stream = _viewsFileSystem.OpenFile(fileName)) using (var reader = new StreamReader(stream, Encoding.UTF8, true)) { content = reader.ReadToEnd(); } - - template.Path = _viewsFileSystem.GetRelativePath(fileName); - template.UpdateDate = _viewsFileSystem.GetLastModified(path).UtcDateTime; - //Currently set with db values, but will eventually be changed - //template.CreateDate = _viewsFileSystem.GetCreated(path).UtcDateTime; - //template.Key = new FileInfo(path).Name.EncodeAsGuid(); - + template.UpdateDate = _viewsFileSystem.GetLastModified(fileName).UtcDateTime; template.Content = content; + template.VirtualPath = _viewsFileSystem.GetUrl(fileName); } private void PopulateMasterpageTemplate(ITemplate template, string fileName) { string content; - var path = string.Empty; using (var stream = _masterpagesFileSystem.OpenFile(fileName)) using (var reader = new StreamReader(stream, Encoding.UTF8, true)) @@ -387,22 +425,16 @@ namespace Umbraco.Core.Persistence.Repositories content = reader.ReadToEnd(); } - template.Path = _masterpagesFileSystem.GetRelativePath(fileName); - template.UpdateDate = _masterpagesFileSystem.GetLastModified(path).UtcDateTime; - //Currently set with db values, but will eventually be changed - //template.CreateDate = _masterpagesFileSystem.GetCreated(path).UtcDateTime; - //template.Key = new FileInfo(path).Name.EncodeAsGuid(); - - template.Path = path; + template.UpdateDate = _masterpagesFileSystem.GetLastModified(fileName).UtcDateTime; template.Content = content; + template.VirtualPath = _masterpagesFileSystem.GetUrl(fileName); } #region Implementation of ITemplateRepository public ITemplate Get(string alias) { - var sql = GetBaseQuery(false) - .Where(x => x.Alias == alias); + var sql = GetBaseQuery(false).Where(x => x.Alias == alias); var dto = Database.Fetch(sql).FirstOrDefault(); @@ -432,6 +464,28 @@ namespace Umbraco.Core.Persistence.Repositories } + public IEnumerable GetChildren(int masterTemplateId) + { + //TODO: Fix this N+1! + + List found; + if (masterTemplateId == -1) + { + var sql = GetBaseQuery(false).Where(x => x.ParentId <= 0); + found = Database.Fetch(sql); + } + else + { + var sql = GetBaseQuery(false).Where(x => x.ParentId == masterTemplateId); + found = Database.Fetch(sql); + } + + foreach (var templateDto in found) + { + yield return Get(templateDto.NodeId); + } + } + /// /// Returns a template as a template node which can be traversed (parent, children) /// @@ -439,13 +493,14 @@ namespace Umbraco.Core.Persistence.Repositories /// public TemplateNode GetTemplateNode(string alias) { - //in order to do this we need to get all of the templates and then organize, unfortunately - // our db structure does not use the path correctly for templates so we cannot just look + //in order to do this we need to get all of the templates and then organize, + // TODO: unfortunately our db structure does not use the path correctly for templates so we cannot just look // up a template tree easily. + //TODO: We do use the 'path' now, so this might be able to be fixed up //first get all template objects var allTemplates = GetAll().ToArray(); - + var selfTemplate = allTemplates.SingleOrDefault(x => x.Alias == alias); if (selfTemplate == null) { @@ -453,20 +508,19 @@ namespace Umbraco.Core.Persistence.Repositories } //then we need to get all template Dto's because those contain the master property - var sql = new Sql(); - sql.Select("*").From(); - var allDtos = Database.Fetch(sql).ToArray(); + var sql = GetBaseQuery(false); + var allDtos = Database.Fetch(sql).ToArray(); var selfDto = allDtos.Single(x => x.NodeId == selfTemplate.Id); - + //need to get the top-most node of the current tree var top = selfDto; - while (top.Master.HasValue) + while (top.NodeDto.ParentId > 0) { - top = allDtos.Single(x => x.NodeId == top.Master.Value); + top = allDtos.Single(x => x.NodeId == top.NodeDto.ParentId); } var topNode = new TemplateNode(allTemplates.Single(x => x.Id == top.NodeId)); - var childIds = allDtos.Where(x => x.Master == top.NodeId).Select(x => x.NodeId); + var childIds = allDtos.Where(x => x.NodeDto.ParentId == top.NodeId).Select(x => x.NodeId); //This now creates the hierarchy recursively topNode.Children = CreateChildren(topNode, childIds, allTemplates, allDtos); @@ -475,7 +529,7 @@ namespace Umbraco.Core.Persistence.Repositories } private static TemplateNode WalkTree(TemplateNode current, string alias) - { + { //now walk the tree to find the node if (current.Template.Alias == alias) { @@ -506,6 +560,85 @@ namespace Umbraco.Core.Persistence.Repositories return WalkTree(top, alias); } + /// + /// 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 + /// templates in business logic. Without this, it could cause the wrong rendering engine to be used for a package. + /// + public RenderingEngine DetermineTemplateRenderingEngine(ITemplate template) + { + var engine = _templateConfig.DefaultRenderingEngine; + + if (template.Content.IsNullOrWhiteSpace() == false && MasterPageHelper.IsMasterPageSyntax(template.Content)) + { + //there is a design but its definitely a webforms design + return RenderingEngine.WebForms; + } + + var viewHelper = new ViewHelper(_viewsFileSystem); + var masterPageHelper = new MasterPageHelper(_masterpagesFileSystem); + + switch (engine) + { + case RenderingEngine.Mvc: + //check if there's a view in ~/masterpages + if (masterPageHelper.MasterPageExists(template) && viewHelper.ViewExists(template) == false) + { + //change this to webforms since there's already a file there for this template alias + engine = RenderingEngine.WebForms; + } + break; + case RenderingEngine.WebForms: + //check if there's a view in ~/views + if (viewHelper.ViewExists(template) && masterPageHelper.MasterPageExists(template) == false) + { + //change this to mvc since there's already a file there for this template alias + engine = RenderingEngine.Mvc; + } + break; + } + return engine; + } + + /// + /// Validates a + /// + /// to validate + /// True if Script is valid, otherwise false + public bool ValidateTemplate(ITemplate template) + { + var exts = new List(); + if (_templateConfig.DefaultRenderingEngine == RenderingEngine.Mvc) + { + exts.Add("cshtml"); + exts.Add("vbhtml"); + } + else + { + exts.Add(_templateConfig.UseAspNetMasterPages ? "master" : "aspx"); + } + + var dirs = SystemDirectories.Masterpages; + if (_templateConfig.DefaultRenderingEngine == RenderingEngine.Mvc) + dirs += "," + SystemDirectories.MvcViews; + + //Validate file + var validFile = IOHelper.VerifyEditPath(template.VirtualPath, dirs.Split(',')); + + //Validate extension + var validExtension = IOHelper.VerifyFileExtension(template.VirtualPath, exts); + + return validFile && validExtension; + } + private static IEnumerable CreateChildren(TemplateNode parent, IEnumerable childIds, ITemplate[] allTemplates, TemplateDto[] allDtos) { var children = new List(); @@ -516,19 +649,53 @@ namespace Umbraco.Core.Persistence.Repositories { Parent = parent }; - + //add to our list children.Add(child); //get this node's children - var kids = allDtos.Where(x => x.Master == i).Select(x => x.NodeId).ToArray(); - + var kids = allDtos.Where(x => x.NodeDto.ParentId == i).Select(x => x.NodeId).ToArray(); + //recurse child.Children = CreateChildren(child, kids, allTemplates, allDtos); } return children; - } + } #endregion + + /// + /// Ensures that there are not duplicate aliases and if so, changes it to be a numbered version and also verifies the length + /// + /// + private void EnsureValidAlias(ITemplate template) + { + //ensure unique alias + template.Alias = template.Alias.ToCleanString(CleanStringType.UnderscoreAlias); + + if (template.Alias.Length > 100) + template.Alias = template.Alias.Substring(0, 95); + + if (AliasAlreadExists(template)) + { + template.Alias = EnsureUniqueAlias(template, 1); + } + } + + private bool AliasAlreadExists(ITemplate template) + { + var sql = GetBaseQuery(true).Where(x => x.Alias == template.Alias && x.NodeId != template.Id); + var count = Database.ExecuteScalar(sql); + return count > 0; + } + + private string EnsureUniqueAlias(ITemplate template, int attempts) + { + //TODO: This is ported from the old data layer... pretty crap way of doing this but it works for now. + if (AliasAlreadExists(template)) + return template.Alias + attempts; + attempts++; + return EnsureUniqueAlias(template, attempts); + } } } \ No newline at end of file diff --git a/src/Umbraco.Core/Persistence/Repositories/UserRepository.cs b/src/Umbraco.Core/Persistence/Repositories/UserRepository.cs index c08802f6e0..cafb93224a 100644 --- a/src/Umbraco.Core/Persistence/Repositories/UserRepository.cs +++ b/src/Umbraco.Core/Persistence/Repositories/UserRepository.cs @@ -3,11 +3,12 @@ using System.Collections.Generic; using System.Linq; using System.Linq.Expressions; using Umbraco.Core; +using Umbraco.Core.Logging; using Umbraco.Core.Models; using Umbraco.Core.Models.EntityBase; using Umbraco.Core.Models.Membership; using Umbraco.Core.Models.Rdbms; -using Umbraco.Core.Persistence.Caching; + using Umbraco.Core.Persistence.Factories; using Umbraco.Core.Persistence.Mappers; using Umbraco.Core.Persistence.Querying; @@ -25,15 +26,8 @@ namespace Umbraco.Core.Persistence.Repositories private readonly IUserTypeRepository _userTypeRepository; private readonly CacheHelper _cacheHelper; - public UserRepository(IDatabaseUnitOfWork work, IUserTypeRepository userTypeRepository, CacheHelper cacheHelper) - : base(work) - { - _userTypeRepository = userTypeRepository; - _cacheHelper = cacheHelper; - } - - public UserRepository(IDatabaseUnitOfWork work, IRepositoryCacheProvider cache, IUserTypeRepository userTypeRepository, CacheHelper cacheHelper) - : base(work, cache) + public UserRepository(IDatabaseUnitOfWork work, CacheHelper cacheHelper, ILogger logger, ISqlSyntaxProvider sqlSyntax, IUserTypeRepository userTypeRepository) + : base(work, cacheHelper, logger, sqlSyntax) { _userTypeRepository = userTypeRepository; _cacheHelper = cacheHelper; @@ -127,7 +121,7 @@ namespace Umbraco.Core.Persistence.Repositories "DELETE FROM umbracoUser2NodePermission WHERE userId = @Id", "DELETE FROM umbracoUser2NodeNotify WHERE userId = @Id", "DELETE FROM umbracoUserLogins WHERE userID = @Id", - "DELETE FROM umbracoUser2app WHERE " + SqlSyntaxContext.SqlSyntaxProvider.GetQuotedColumnName("user") + "=@Id", + "DELETE FROM umbracoUser2app WHERE " + SqlSyntaxProvider.GetQuotedColumnName("user") + "=@Id", "DELETE FROM umbracoUser WHERE id = @Id" }; return list; @@ -204,7 +198,7 @@ namespace Umbraco.Core.Persistence.Repositories foreach (var section in user.RemovedSections) { //we need to manually delete thsi record because it has a composite key - Database.Delete("WHERE app=@Section AND " + SqlSyntaxContext.SqlSyntaxProvider.GetQuotedColumnName("user") + "=@UserId", + Database.Delete("WHERE app=@Section AND " + SqlSyntaxProvider.GetQuotedColumnName("user") + "=@UserId", new { Section = section, UserId = (int)user.Id }); } @@ -221,7 +215,7 @@ namespace Umbraco.Core.Persistence.Repositories else { //we need to manually update this record because it has a composite key - Database.Update("SET app=@Section WHERE app=@Section AND " + SqlSyntaxContext.SqlSyntaxProvider.GetQuotedColumnName("user") + "=@UserId", + Database.Update("SET app=@Section WHERE app=@Section AND " + SqlSyntaxProvider.GetQuotedColumnName("user") + "=@UserId", new { Section = sectionDto.AppAlias, UserId = sectionDto.UserId }); } } @@ -276,7 +270,7 @@ namespace Umbraco.Core.Persistence.Repositories var sql = GetBaseQuery(false); var innerSql = GetBaseQuery("umbracoUser.id"); - innerSql.Where("umbracoUser2app.app = " + SqlSyntaxContext.SqlSyntaxProvider.GetQuotedValue(sectionAlias)); + innerSql.Where("umbracoUser2app.app = " + SqlSyntaxProvider.GetQuotedValue(sectionAlias)); sql.Where(string.Format("umbracoUser.id IN ({0})", innerSql.SQL)); return ConvertFromDtos(Database.Fetch(new UserSectionRelator().Map, sql)); @@ -350,7 +344,7 @@ namespace Umbraco.Core.Persistence.Repositories /// public IEnumerable GetUserPermissionsForEntities(int userId, params int[] entityIds) { - var repo = new PermissionRepository(UnitOfWork, _cacheHelper); + var repo = new PermissionRepository(UnitOfWork, _cacheHelper, SqlSyntaxProvider); return repo.GetUserPermissionsForEntities(userId, entityIds); } @@ -362,7 +356,7 @@ namespace Umbraco.Core.Persistence.Repositories /// public void ReplaceUserPermissions(int userId, IEnumerable permissions, params int[] entityIds) { - var repo = new PermissionRepository(UnitOfWork, _cacheHelper); + var repo = new PermissionRepository(UnitOfWork, _cacheHelper, SqlSyntaxProvider); repo.ReplaceUserPermissions(userId, permissions, entityIds); } diff --git a/src/Umbraco.Core/Persistence/Repositories/UserTypeRepository.cs b/src/Umbraco.Core/Persistence/Repositories/UserTypeRepository.cs index c7fd4723ab..1fd94ca357 100644 --- a/src/Umbraco.Core/Persistence/Repositories/UserTypeRepository.cs +++ b/src/Umbraco.Core/Persistence/Repositories/UserTypeRepository.cs @@ -1,11 +1,13 @@ using System; using System.Collections.Generic; using System.Linq; +using Umbraco.Core.Logging; using Umbraco.Core.Models.Membership; using Umbraco.Core.Models.Rdbms; -using Umbraco.Core.Persistence.Caching; + using Umbraco.Core.Persistence.Factories; using Umbraco.Core.Persistence.Querying; +using Umbraco.Core.Persistence.SqlSyntax; using Umbraco.Core.Persistence.UnitOfWork; namespace Umbraco.Core.Persistence.Repositories @@ -15,13 +17,8 @@ namespace Umbraco.Core.Persistence.Repositories /// internal class UserTypeRepository : PetaPocoRepositoryBase, IUserTypeRepository { - public UserTypeRepository(IDatabaseUnitOfWork work) - : base(work) - { - } - - public UserTypeRepository(IDatabaseUnitOfWork work, IRepositoryCacheProvider cache) - : base(work, cache) + public UserTypeRepository(IDatabaseUnitOfWork work, CacheHelper cache, ILogger logger, ISqlSyntaxProvider sqlSyntax) + : base(work, cache, logger, sqlSyntax) { } diff --git a/src/Umbraco.Core/Persistence/Repositories/VersionableRepositoryBase.cs b/src/Umbraco.Core/Persistence/Repositories/VersionableRepositoryBase.cs index 3acc06b132..30a36e4a89 100644 --- a/src/Umbraco.Core/Persistence/Repositories/VersionableRepositoryBase.cs +++ b/src/Umbraco.Core/Persistence/Repositories/VersionableRepositoryBase.cs @@ -8,10 +8,11 @@ using Umbraco.Core.Models; using Umbraco.Core.Models.Editors; using Umbraco.Core.Models.EntityBase; using Umbraco.Core.Models.Rdbms; -using Umbraco.Core.Persistence.Caching; + using Umbraco.Core.Persistence.DatabaseModelDefinitions; using Umbraco.Core.Persistence.Factories; using Umbraco.Core.Persistence.Querying; +using Umbraco.Core.Persistence.SqlSyntax; using Umbraco.Core.Persistence.UnitOfWork; using Umbraco.Core.PropertyEditors; using Umbraco.Core.Services; @@ -22,11 +23,9 @@ namespace Umbraco.Core.Persistence.Repositories internal abstract class VersionableRepositoryBase : PetaPocoRepositoryBase where TEntity : class, IAggregateRoot { - protected VersionableRepositoryBase(IDatabaseUnitOfWork work) : base(work) - { - } - protected VersionableRepositoryBase(IDatabaseUnitOfWork work, IRepositoryCacheProvider cache) : base(work, cache) + protected VersionableRepositoryBase(IDatabaseUnitOfWork work, CacheHelper cache, ILogger logger, ISqlSyntaxProvider sqlSyntax) + : base(work, cache, logger, sqlSyntax) { } @@ -472,7 +471,7 @@ WHERE EXISTS( if (result.ContainsKey(def.Id)) { - LogHelper.Warn>("The query returned multiple property sets for document definition " + def.Id + ", " + def.Composition.Name); + Logger.Warn>("The query returned multiple property sets for document definition " + def.Id + ", " + def.Composition.Name); } result[def.Id] = new PropertyCollection(properties); } diff --git a/src/Umbraco.Core/Persistence/RepositoryFactory.cs b/src/Umbraco.Core/Persistence/RepositoryFactory.cs index 1a8752739f..f5d5c677de 100644 --- a/src/Umbraco.Core/Persistence/RepositoryFactory.cs +++ b/src/Umbraco.Core/Persistence/RepositoryFactory.cs @@ -1,8 +1,11 @@ using Umbraco.Core.Configuration; using System; using Umbraco.Core.Configuration.UmbracoSettings; -using Umbraco.Core.Persistence.Caching; +using Umbraco.Core.IO; +using Umbraco.Core.Logging; + using Umbraco.Core.Persistence.Repositories; +using Umbraco.Core.Persistence.SqlSyntax; using Umbraco.Core.Persistence.UnitOfWork; namespace Umbraco.Core.Persistence @@ -12,75 +15,83 @@ namespace Umbraco.Core.Persistence /// public class RepositoryFactory { - private readonly bool _disableAllCache; + private readonly ILogger _logger; + private readonly ISqlSyntaxProvider _sqlSyntax; private readonly CacheHelper _cacheHelper; private readonly IUmbracoSettingsSection _settings; #region Ctors + + public RepositoryFactory(CacheHelper cacheHelper, ILogger logger, ISqlSyntaxProvider sqlSyntax, IUmbracoSettingsSection settings) + { + if (cacheHelper == null) throw new ArgumentNullException("cacheHelper"); + if (logger == null) throw new ArgumentNullException("logger"); + //if (sqlSyntax == null) throw new ArgumentNullException("sqlSyntax"); + if (settings == null) throw new ArgumentNullException("settings"); + + _cacheHelper = cacheHelper; + _logger = logger; + _sqlSyntax = sqlSyntax; + _settings = settings; + } + + [Obsolete("Use the ctor specifying all dependencies instead")] public RepositoryFactory() - : this(false, UmbracoConfig.For.UmbracoSettings()) + : this(ApplicationContext.Current.ApplicationCache, LoggerResolver.Current.Logger, SqlSyntaxContext.SqlSyntaxProvider, UmbracoConfig.For.UmbracoSettings()) { } + [Obsolete("Use the ctor specifying all dependencies instead")] public RepositoryFactory(CacheHelper cacheHelper) - : this(false, UmbracoConfig.For.UmbracoSettings()) + : this(cacheHelper, LoggerResolver.Current.Logger, SqlSyntaxContext.SqlSyntaxProvider, UmbracoConfig.For.UmbracoSettings()) { - if (cacheHelper == null) throw new ArgumentNullException("cacheHelper"); - _disableAllCache = false; - _cacheHelper = cacheHelper; } + [Obsolete("Use the ctor specifying all dependencies instead, NOTE: disableAllCache has zero effect")] public RepositoryFactory(bool disableAllCache, CacheHelper cacheHelper) - : this(disableAllCache, UmbracoConfig.For.UmbracoSettings()) + : this(cacheHelper, LoggerResolver.Current.Logger, SqlSyntaxContext.SqlSyntaxProvider, UmbracoConfig.For.UmbracoSettings()) { if (cacheHelper == null) throw new ArgumentNullException("cacheHelper"); _cacheHelper = cacheHelper; } + [Obsolete("Use the ctor specifying all dependencies instead")] public RepositoryFactory(bool disableAllCache) - : this(disableAllCache, UmbracoConfig.For.UmbracoSettings()) + : this(disableAllCache ? CacheHelper.CreateDisabledCacheHelper() : ApplicationContext.Current.ApplicationCache, LoggerResolver.Current.Logger, SqlSyntaxContext.SqlSyntaxProvider, UmbracoConfig.For.UmbracoSettings()) { - } - internal RepositoryFactory(bool disableAllCache, IUmbracoSettingsSection settings) - { - _disableAllCache = disableAllCache; - _settings = settings; - _cacheHelper = _disableAllCache ? CacheHelper.CreateDisabledCacheHelper() : ApplicationContext.Current.ApplicationCache; - } - - internal RepositoryFactory(bool disableAllCache, IUmbracoSettingsSection settings, CacheHelper cacheHelper) - { - _disableAllCache = disableAllCache; - _settings = settings; - _cacheHelper = cacheHelper; - } + #endregion public virtual ITagRepository CreateTagRepository(IDatabaseUnitOfWork uow) { return new TagRepository( uow, - _disableAllCache ? (IRepositoryCacheProvider)NullCacheProvider.Current : RuntimeCacheProvider.Current); + _cacheHelper, _logger, _sqlSyntax); } public virtual IContentRepository CreateContentRepository(IDatabaseUnitOfWork uow) { return new ContentRepository( - uow, - _disableAllCache ? (IRepositoryCacheProvider)NullCacheProvider.Current : RuntimeCacheProvider.Current, + uow, + _cacheHelper, + _logger, + _sqlSyntax, CreateContentTypeRepository(uow), CreateTemplateRepository(uow), - CreateTagRepository(uow), - _cacheHelper) { EnsureUniqueNaming = _settings.Content.EnsureUniqueNaming }; + CreateTagRepository(uow)) + { + EnsureUniqueNaming = _settings.Content.EnsureUniqueNaming + }; } public virtual IContentTypeRepository CreateContentTypeRepository(IDatabaseUnitOfWork uow) { return new ContentTypeRepository( uow, - _disableAllCache ? (IRepositoryCacheProvider)NullCacheProvider.Current : RuntimeCacheProvider.Current, + _cacheHelper, + _logger, _sqlSyntax, CreateTemplateRepository(uow)); } @@ -88,8 +99,9 @@ namespace Umbraco.Core.Persistence { return new DataTypeDefinitionRepository( uow, - _disableAllCache ? (IRepositoryCacheProvider)NullCacheProvider.Current : RuntimeCacheProvider.Current, + _cacheHelper, _cacheHelper, + _logger, _sqlSyntax, CreateContentTypeRepository(uow)); } @@ -97,7 +109,9 @@ namespace Umbraco.Core.Persistence { return new DictionaryRepository( uow, - _disableAllCache ? (IRepositoryCacheProvider)NullCacheProvider.Current : RuntimeCacheProvider.Current, + _cacheHelper, + _logger, + _sqlSyntax, CreateLanguageRepository(uow)); } @@ -105,14 +119,16 @@ namespace Umbraco.Core.Persistence { return new LanguageRepository( uow, - _disableAllCache ? (IRepositoryCacheProvider)NullCacheProvider.Current : RuntimeCacheProvider.Current); + _cacheHelper, + _logger, _sqlSyntax); } public virtual IMediaRepository CreateMediaRepository(IDatabaseUnitOfWork uow) { return new MediaRepository( uow, - _disableAllCache ? (IRepositoryCacheProvider)NullCacheProvider.Current : RuntimeCacheProvider.Current, + _cacheHelper, + _logger, _sqlSyntax, CreateMediaTypeRepository(uow), CreateTagRepository(uow)) { EnsureUniqueNaming = _settings.Content.EnsureUniqueNaming }; } @@ -121,14 +137,16 @@ namespace Umbraco.Core.Persistence { return new MediaTypeRepository( uow, - _disableAllCache ? (IRepositoryCacheProvider)NullCacheProvider.Current : RuntimeCacheProvider.Current); + _cacheHelper, + _logger, _sqlSyntax); } public virtual IRelationRepository CreateRelationRepository(IDatabaseUnitOfWork uow) { return new RelationRepository( uow, - NullCacheProvider.Current, + CacheHelper.CreateDisabledCacheHelper(), //never cache + _logger, _sqlSyntax, CreateRelationTypeRepository(uow)); } @@ -136,12 +154,13 @@ namespace Umbraco.Core.Persistence { return new RelationTypeRepository( uow, - NullCacheProvider.Current); + CacheHelper.CreateDisabledCacheHelper(), //never cache + _logger, _sqlSyntax); } public virtual IScriptRepository CreateScriptRepository(IUnitOfWork uow) { - return new ScriptRepository(uow); + return new ScriptRepository(uow, new PhysicalFileSystem(SystemDirectories.Scripts), _settings.Content); } internal virtual IPartialViewRepository CreatePartialViewRepository(IUnitOfWork uow) @@ -156,19 +175,25 @@ namespace Umbraco.Core.Persistence public virtual IStylesheetRepository CreateStylesheetRepository(IUnitOfWork uow, IDatabaseUnitOfWork db) { - return new StylesheetRepository(uow, db); + return new StylesheetRepository(uow, new PhysicalFileSystem(SystemDirectories.Css)); } public virtual ITemplateRepository CreateTemplateRepository(IDatabaseUnitOfWork uow) { - return new TemplateRepository(uow, _disableAllCache ? (IRepositoryCacheProvider)NullCacheProvider.Current : RuntimeCacheProvider.Current); + return new TemplateRepository(uow, + _cacheHelper, + _logger, _sqlSyntax, + new PhysicalFileSystem(SystemDirectories.Masterpages), + new PhysicalFileSystem(SystemDirectories.MvcViews), + _settings.Templates); } internal virtual ServerRegistrationRepository CreateServerRegistrationRepository(IDatabaseUnitOfWork uow) { return new ServerRegistrationRepository( uow, - NullCacheProvider.Current); + CacheHelper.CreateDisabledCacheHelper(), //never cache + _logger, _sqlSyntax); } public virtual IUserTypeRepository CreateUserTypeRepository(IDatabaseUnitOfWork uow) @@ -176,7 +201,8 @@ namespace Umbraco.Core.Persistence return new UserTypeRepository( uow, //There's not many user types but we query on users all the time so the result needs to be cached - _disableAllCache ? (IRepositoryCacheProvider)NullCacheProvider.Current : RuntimeCacheProvider.Current); + _cacheHelper, + _logger, _sqlSyntax); } public virtual IUserRepository CreateUserRepository(IDatabaseUnitOfWork uow) @@ -184,21 +210,24 @@ namespace Umbraco.Core.Persistence return new UserRepository( uow, //Need to cache users - we look up user information more than anything in the back office! - _disableAllCache ? (IRepositoryCacheProvider)NullCacheProvider.Current : RuntimeCacheProvider.Current, - CreateUserTypeRepository(uow), - _cacheHelper); + _cacheHelper, + _logger, _sqlSyntax, + CreateUserTypeRepository(uow)); } internal virtual IMacroRepository CreateMacroRepository(IDatabaseUnitOfWork uow) { - return new MacroRepository(uow, _disableAllCache ? (IRepositoryCacheProvider)NullCacheProvider.Current : RuntimeCacheProvider.Current); + return new MacroRepository(uow, + _cacheHelper, + _logger, _sqlSyntax); } public virtual IMemberRepository CreateMemberRepository(IDatabaseUnitOfWork uow) { return new MemberRepository( uow, - _disableAllCache ? (IRepositoryCacheProvider)NullCacheProvider.Current : RuntimeCacheProvider.Current, + _cacheHelper, + _logger, _sqlSyntax, CreateMemberTypeRepository(uow), CreateMemberGroupRepository(uow), CreateTagRepository(uow)); @@ -206,12 +235,17 @@ namespace Umbraco.Core.Persistence public virtual IMemberTypeRepository CreateMemberTypeRepository(IDatabaseUnitOfWork uow) { - return new MemberTypeRepository(uow, _disableAllCache ? (IRepositoryCacheProvider)NullCacheProvider.Current : RuntimeCacheProvider.Current); + return new MemberTypeRepository(uow, + _cacheHelper, + _logger, _sqlSyntax); } public virtual IMemberGroupRepository CreateMemberGroupRepository(IDatabaseUnitOfWork uow) { - return new MemberGroupRepository(uow, _disableAllCache ? (IRepositoryCacheProvider)NullCacheProvider.Current : RuntimeCacheProvider.Current, _cacheHelper); + return new MemberGroupRepository(uow, + _cacheHelper, + _logger, _sqlSyntax, + _cacheHelper); } public virtual IEntityRepository CreateEntityRepository(IDatabaseUnitOfWork uow) diff --git a/src/Umbraco.Core/Persistence/RepositoryResolver.cs b/src/Umbraco.Core/Persistence/RepositoryResolver.cs deleted file mode 100644 index 558a3aaee7..0000000000 --- a/src/Umbraco.Core/Persistence/RepositoryResolver.cs +++ /dev/null @@ -1,63 +0,0 @@ -using System; -using System.Linq; -using System.Reflection; -using Umbraco.Core.ObjectResolution; -using Umbraco.Core.Persistence.Repositories; -using Umbraco.Core.Persistence.UnitOfWork; - -namespace Umbraco.Core.Persistence -{ - /// - /// A resolver used to return the current implementation of the RepositoryInstanceFactory - /// - internal class RepositoryResolver : SingleObjectResolverBase - { - internal RepositoryResolver(RepositoryFactory registrar) - : base(registrar) - { - } - - /// - /// Can be used by developers at runtime to set their own RepositoryInstanceFactory at app startup - /// - /// - public void SetRepositoryInstanceFactory(RepositoryFactory factory) - { - Value = factory; - } - - /// - /// Returns the RepositoryInstanceFactory object - /// - internal RepositoryFactory Factory - { - get { return Value; } - } - - /// - /// Return the repository based on the type - /// - /// - /// - /// - internal TRepository ResolveByType(IUnitOfWork unitOfWork) - where TRepository : class, IRepository - { - var createMethod = this.Value.GetType().GetMethods(BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Public) - .First(x => x.Name == "Create" + typeof (TRepository).Name.Substring(1)); - - if (createMethod.GetParameters().Count() != 1 - || !createMethod.GetParameters().Single().ParameterType.IsType()) - { - throw new FormatException("The method " + createMethod.Name + " must only contain one parameter of type " + typeof(IUnitOfWork).FullName); - } - if (!createMethod.ReturnType.IsType()) - { - throw new FormatException("The method " + createMethod.Name + " must return the type " + typeof(TRepository).FullName); - } - - return (TRepository) createMethod.Invoke(this.Value, new object[] {unitOfWork}); - } - - } -} \ No newline at end of file diff --git a/src/Umbraco.Core/Persistence/SqlSyntax/MySqlSyntax.cs b/src/Umbraco.Core/Persistence/SqlSyntax/MySqlSyntax.cs deleted file mode 100644 index 00b07ae15a..0000000000 --- a/src/Umbraco.Core/Persistence/SqlSyntax/MySqlSyntax.cs +++ /dev/null @@ -1,10 +0,0 @@ -namespace Umbraco.Core.Persistence.SqlSyntax -{ - /// - /// Static class that provides simple access to the MySql SqlSyntax Provider - /// - internal static class MySqlSyntax - { - public static ISqlSyntaxProvider Provider { get { return new MySqlSyntaxProvider(); } } - } -} \ No newline at end of file diff --git a/src/Umbraco.Core/Persistence/SqlSyntax/MySqlSyntaxProvider.cs b/src/Umbraco.Core/Persistence/SqlSyntax/MySqlSyntaxProvider.cs index ba6f4dcc7e..dcb7dc029c 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 Umbraco.Core.Logging; using Umbraco.Core.Persistence.DatabaseAnnotations; using Umbraco.Core.Persistence.DatabaseModelDefinitions; @@ -12,8 +13,11 @@ namespace Umbraco.Core.Persistence.SqlSyntax [SqlSyntaxProviderAttribute("MySql.Data.MySqlClient")] public class MySqlSyntaxProvider : SqlSyntaxProviderBase { - public MySqlSyntaxProvider() + private readonly ILogger _logger; + + public MySqlSyntaxProvider(ILogger logger) { + _logger = logger; DefaultStringLength = 255; StringLengthColumnDefinitionFormat = StringLengthUnicodeColumnDefinitionFormat; StringColumnDefinition = string.Format(StringLengthColumnDefinitionFormat, DefaultStringLength); @@ -357,7 +361,7 @@ ORDER BY TABLE_NAME, INDEX_NAME", } catch (Exception ex) { - Logging.LogHelper.Error("Error querying for lower_case support", ex); + _logger.Error("Error querying for lower_case support", ex); } finally { diff --git a/src/Umbraco.Core/Persistence/SqlSyntax/SqlCeSyntax.cs b/src/Umbraco.Core/Persistence/SqlSyntax/SqlCeSyntax.cs deleted file mode 100644 index 29660355fe..0000000000 --- a/src/Umbraco.Core/Persistence/SqlSyntax/SqlCeSyntax.cs +++ /dev/null @@ -1,10 +0,0 @@ -namespace Umbraco.Core.Persistence.SqlSyntax -{ - /// - /// Static class that provides simple access to the Sql CE SqlSyntax Provider - /// - internal static class SqlCeSyntax - { - public static ISqlSyntaxProvider Provider { get { return new SqlCeSyntaxProvider(); } } - } -} \ No newline at end of file diff --git a/src/Umbraco.Core/Persistence/SqlSyntax/SqlServerSyntax.cs b/src/Umbraco.Core/Persistence/SqlSyntax/SqlServerSyntax.cs deleted file mode 100644 index a2f000e4b8..0000000000 --- a/src/Umbraco.Core/Persistence/SqlSyntax/SqlServerSyntax.cs +++ /dev/null @@ -1,10 +0,0 @@ -namespace Umbraco.Core.Persistence.SqlSyntax -{ - /// - /// Static class that provides simple access to the Sql Server SqlSyntax Provider - /// - internal static class SqlServerSyntax - { - public static ISqlSyntaxProvider Provider { get { return new SqlServerSyntaxProvider(); } } - } -} \ No newline at end of file diff --git a/src/Umbraco.Core/Persistence/SqlSyntax/SqlSyntaxContext.cs b/src/Umbraco.Core/Persistence/SqlSyntax/SqlSyntaxContext.cs index 9fe69a4ca9..b50acc5026 100644 --- a/src/Umbraco.Core/Persistence/SqlSyntax/SqlSyntaxContext.cs +++ b/src/Umbraco.Core/Persistence/SqlSyntax/SqlSyntaxContext.cs @@ -5,6 +5,7 @@ namespace Umbraco.Core.Persistence.SqlSyntax /// /// Singleton to handle the configuration of a SqlSyntaxProvider /// + [Obsolete("This should not be used, the ISqlSyntaxProvider is part of the DatabaseContext or should be injected into your services as a constructor parameter")] public static class SqlSyntaxContext { private static ISqlSyntaxProvider _sqlSyntaxProvider; diff --git a/src/Umbraco.Core/Persistence/SqlSyntax/SqlSyntaxProvidersResolver.cs b/src/Umbraco.Core/Persistence/SqlSyntax/SqlSyntaxProviders.cs similarity index 53% rename from src/Umbraco.Core/Persistence/SqlSyntax/SqlSyntaxProvidersResolver.cs rename to src/Umbraco.Core/Persistence/SqlSyntax/SqlSyntaxProviders.cs index 8db914801d..9f3d337d67 100644 --- a/src/Umbraco.Core/Persistence/SqlSyntax/SqlSyntaxProvidersResolver.cs +++ b/src/Umbraco.Core/Persistence/SqlSyntax/SqlSyntaxProviders.cs @@ -1,55 +1,58 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using Umbraco.Core.ObjectResolution; - -namespace Umbraco.Core.Persistence.SqlSyntax -{ - /// - /// A resolver to return all ISqlSyntaxProvider objects - /// - internal sealed class SqlSyntaxProvidersResolver : ManyObjectsResolverBase - { - /// - /// Constructor - /// - /// - internal SqlSyntaxProvidersResolver(IEnumerable syntaxProviders) - : base(syntaxProviders) - { - - } - - /// - /// Gets the implementations. - /// - public IEnumerable SqlSyntaxProviders - { - get - { - return Values; - } - } - - /// - /// Gets a by its attributed provider. - /// - /// ProviderName from the ConnectionString settings - /// that corresponds to the attributed provider or the default Sql Server Syntax Provider. - public ISqlSyntaxProvider GetByProviderNameOrDefault(string providerName) - { - var provider = - Values.FirstOrDefault( - x => - x.GetType() - .FirstAttribute() - .ProviderName.ToLowerInvariant() - .Equals(providerName.ToLowerInvariant())); - - if (provider != null) - return provider; - - return Values.First(x => x.GetType() == typeof (SqlServerSyntaxProvider)); - } - } +using System; +using System.Collections.Generic; +using System.Linq; +using Umbraco.Core.Logging; +using Umbraco.Core.ObjectResolution; + +namespace Umbraco.Core.Persistence.SqlSyntax +{ + /// + /// Used to return the correct syntax provider for a given provider name + /// + public sealed class SqlSyntaxProviders + { + private readonly IEnumerable _syntaxProviders; + + internal static SqlSyntaxProviders CreateDefault(ILogger logger) + { + return new SqlSyntaxProviders(new ISqlSyntaxProvider[] + { + new MySqlSyntaxProvider(logger), + new SqlCeSyntaxProvider(), + new SqlServerSyntaxProvider() + }); + } + + /// + /// Constructor + /// + /// + public SqlSyntaxProviders(IEnumerable syntaxProviders) + { + if (syntaxProviders == null) throw new ArgumentNullException("syntaxProviders"); + _syntaxProviders = syntaxProviders; + } + + /// + /// Gets a by its attributed provider. + /// + /// ProviderName from the ConnectionString settings + /// that corresponds to the attributed provider or the default Sql Server Syntax Provider. + public ISqlSyntaxProvider GetByProviderNameOrDefault(string providerName) + { + var provider = + _syntaxProviders.FirstOrDefault( + x => + x.GetType() + .FirstAttribute() + .ProviderName.ToLowerInvariant() + .Equals(providerName.ToLowerInvariant())); + + if (provider != null) + return provider; + + //default + return _syntaxProviders.First(x => x.GetType() == typeof(SqlServerSyntaxProvider)); + } + } } \ No newline at end of file diff --git a/src/Umbraco.Core/Persistence/UmbracoDatabase.cs b/src/Umbraco.Core/Persistence/UmbracoDatabase.cs index 98d5d9cebc..95c723deaa 100644 --- a/src/Umbraco.Core/Persistence/UmbracoDatabase.cs +++ b/src/Umbraco.Core/Persistence/UmbracoDatabase.cs @@ -8,51 +8,84 @@ using Umbraco.Core.Logging; namespace Umbraco.Core.Persistence { - /// - /// Represents the Umbraco implementation of the PetaPoco Database object - /// - /// - /// 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. - /// + /// + /// Represents the Umbraco implementation of the PetaPoco Database object + /// + /// + /// 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. + /// public class UmbracoDatabase : Database, IDisposeOnRequestEnd - { + { + private readonly ILogger _logger; private readonly Guid _instanceId = Guid.NewGuid(); - /// - /// Used for testing - /// - internal Guid InstanceId - { - get { return _instanceId; } - } + /// + /// Used for testing + /// + internal Guid InstanceId + { + get { return _instanceId; } + } - public UmbracoDatabase(IDbConnection connection) : base(connection) - { - } + [Obsolete("Use the other constructor specifying an ILogger instead")] + public UmbracoDatabase(IDbConnection connection) + : this(connection, LoggerResolver.Current.Logger) + { + } - public UmbracoDatabase(string connectionString, string providerName) : base(connectionString, providerName) - { - } + [Obsolete("Use the other constructor specifying an ILogger instead")] + public UmbracoDatabase(string connectionString, string providerName) + : this(connectionString, providerName, LoggerResolver.Current.Logger) + { + } - public UmbracoDatabase(string connectionString, DbProviderFactory provider) : base(connectionString, provider) - { - } + [Obsolete("Use the other constructor specifying an ILogger instead")] + public UmbracoDatabase(string connectionString, DbProviderFactory provider) + : this(connectionString, provider, LoggerResolver.Current.Logger) + { + } - public UmbracoDatabase(string connectionStringName) : base(connectionStringName) - { - } + [Obsolete("Use the other constructor specifying an ILogger instead")] + public UmbracoDatabase(string connectionStringName) + : this(connectionStringName, LoggerResolver.Current.Logger) + { + } + + public UmbracoDatabase(IDbConnection connection, ILogger logger) + : base(connection) + { + _logger = logger; + } + + public UmbracoDatabase(string connectionString, string providerName, ILogger logger) + : base(connectionString, providerName) + { + _logger = logger; + } + + public UmbracoDatabase(string connectionString, DbProviderFactory provider, ILogger logger) + : base(connectionString, provider) + { + _logger = logger; + } + + public UmbracoDatabase(string connectionStringName, ILogger logger) + : base(connectionStringName) + { + _logger = logger; + } public override IDbConnection OnConnectionOpened(IDbConnection connection) { // wrap the connection with a profiling connection that tracks timings return new StackExchange.Profiling.Data.ProfiledDbConnection(connection as DbConnection, MiniProfiler.Current); } - + public override void OnException(Exception x) { - LogHelper.Info(x.StackTrace); + _logger.Info(x.StackTrace); base.OnException(x); } - } + } } \ No newline at end of file diff --git a/src/Umbraco.Core/Persistence/UnitOfWork/PetaPocoUnitOfWorkProvider.cs b/src/Umbraco.Core/Persistence/UnitOfWork/PetaPocoUnitOfWorkProvider.cs index fbdae5b5e4..249b1c696b 100644 --- a/src/Umbraco.Core/Persistence/UnitOfWork/PetaPocoUnitOfWorkProvider.cs +++ b/src/Umbraco.Core/Persistence/UnitOfWork/PetaPocoUnitOfWorkProvider.cs @@ -1,4 +1,6 @@ -using Umbraco.Core.Configuration; +using System; +using Umbraco.Core.Configuration; +using Umbraco.Core.Logging; namespace Umbraco.Core.Persistence.UnitOfWork { @@ -7,61 +9,75 @@ namespace Umbraco.Core.Persistence.UnitOfWork /// public class PetaPocoUnitOfWorkProvider : IDatabaseUnitOfWorkProvider { - private readonly IDatabaseFactory _dbFactory; + private readonly IDatabaseFactory _dbFactory; + + [Obsolete("Use the constructor specifying an ILogger instead")] + public PetaPocoUnitOfWorkProvider() + : this(new DefaultDatabaseFactory(GlobalSettings.UmbracoConnectionName, LoggerResolver.Current.Logger)) + { + + } + + [Obsolete("Use the constructor specifying an ILogger instead")] + public PetaPocoUnitOfWorkProvider(string connectionString, string providerName) + : this(new DefaultDatabaseFactory(connectionString, providerName, LoggerResolver.Current.Logger)) + { } /// /// Parameterless constructor uses defaults /// - public PetaPocoUnitOfWorkProvider() - : this(new DefaultDatabaseFactory(GlobalSettings.UmbracoConnectionName)) + 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(string connectionString, string providerName) : this(new DefaultDatabaseFactory(connectionString, providerName)) - {} - - /// - /// Constructor accepting an IDatabaseFactory instance - /// - /// - internal PetaPocoUnitOfWorkProvider(IDatabaseFactory dbFactory) - { - Mandate.ParameterNotNull(dbFactory, "dbFactory"); - _dbFactory = dbFactory; - } - - #region Implementation of IUnitOfWorkProvider + public PetaPocoUnitOfWorkProvider(ILogger logger, string connectionString, string providerName) + : this(new DefaultDatabaseFactory(connectionString, providerName, logger)) + { } /// - /// 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() + /// Constructor accepting an IDatabaseFactory instance + /// + /// + internal 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() - { - var provider = new PetaPocoUnitOfWorkProvider(); - return provider.GetUnitOfWork(); - } + /// + /// 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/PluginManager.cs b/src/Umbraco.Core/PluginManager.cs index 26db01c165..7fa3b63ede 100644 --- a/src/Umbraco.Core/PluginManager.cs +++ b/src/Umbraco.Core/PluginManager.cs @@ -15,7 +15,9 @@ using Umbraco.Core.Models; using Umbraco.Core.Persistence.Mappers; using Umbraco.Core.Persistence.Migrations; using Umbraco.Core.Persistence.SqlSyntax; +using Umbraco.Core.Profiling; using Umbraco.Core.PropertyEditors; +using Umbraco.Core.Cache; using umbraco.interfaces; using File = System.IO.File; @@ -36,34 +38,27 @@ namespace Umbraco.Core /// public class PluginManager { - private readonly ApplicationContext _appContext; - private const string CacheKey = "umbraco-plugins.list"; - /// /// Creates a new PluginManager with an ApplicationContext instance which ensures that the plugin xml /// file is cached temporarily until app startup completes. /// - /// + /// /// - internal PluginManager(ApplicationContext appContext, bool detectChanges = true) - : this(detectChanges) + /// + /// + internal PluginManager(IServiceProvider serviceProvider, IRuntimeCacheProvider runtimeCache, ProfilingLogger logger, bool detectChanges = true) { - if (appContext == null) throw new ArgumentNullException("appContext"); - _appContext = appContext; - } + if (serviceProvider == null) throw new ArgumentNullException("serviceProvider"); + if (runtimeCache == null) throw new ArgumentNullException("runtimeCache"); + if (logger == null) throw new ArgumentNullException("logger"); + + _serviceProvider = serviceProvider; + _runtimeCache = runtimeCache; + _logger = logger; - /// - /// Creates a new PluginManager - /// - /// - /// If true will detect changes in the /bin folder, app_code, etc... and therefor load plugins from the - /// cached plugins file if one is found. If false will never use the cache file for plugins - /// - internal PluginManager(bool detectChanges = true) - { _tempFolder = IOHelper.MapPath("~/App_Data/TEMP/PluginCache"); //create the folder if it doesn't exist - if (!Directory.Exists(_tempFolder)) + if (Directory.Exists(_tempFolder) == false) { Directory.CreateDirectory(_tempFolder); } @@ -104,14 +99,18 @@ namespace Umbraco.Core //always set to true if we're not detecting (generally only for testing) RequiresRescanning = true; } - } + private readonly IServiceProvider _serviceProvider; + private readonly IRuntimeCacheProvider _runtimeCache; + private readonly ProfilingLogger _logger; + private const string CacheKey = "umbraco-plugins.list"; static PluginManager _resolver; - static readonly ReaderWriterLockSlim Lock = new ReaderWriterLockSlim(); private readonly string _tempFolder; private long _cachedAssembliesHash = -1; private long _currentAssembliesHash = -1; + private static bool _initialized = false; + private static object _singletonLock = new object(); /// /// We will ensure that no matter what, only one of these is created, this is to ensure that caching always takes place @@ -123,19 +122,28 @@ namespace Umbraco.Core { get { - using (var l = new UpgradeableReadLock(Lock)) + return LazyInitializer.EnsureInitialized(ref _resolver, ref _initialized, ref _singletonLock, () => { - if (_resolver == null) + if (ApplicationContext.Current == null) { - l.UpgradeToWriteLock(); - _resolver = ApplicationContext.Current == null - ? new PluginManager() - : new PluginManager(ApplicationContext.Current); + var logger = LoggerResolver.HasCurrent ? LoggerResolver.Current.Logger : new DebugDiagnosticsLogger(); + var profiler = ProfilerResolver.HasCurrent ? ProfilerResolver.Current.Profiler : new LogProfiler(logger); + return new PluginManager( + new ActivatorServiceProvider(), + new NullCacheProvider(), + new ProfilingLogger(logger, profiler)); } - return _resolver; - } + return new PluginManager( + new ActivatorServiceProvider(), + ApplicationContext.Current.ApplicationCache.RuntimeCache, + ApplicationContext.Current.ProfilingLogger); + }); + } + set + { + _initialized = true; + _resolver = value; } - set { _resolver = value; } } #region Hash checking methods @@ -196,7 +204,7 @@ namespace Umbraco.Core //add the trees.config - use the contents to create the has since this gets resaved on every app startup! new Tuple(new FileInfo(IOHelper.MapPath(SystemDirectories.Config + "/trees.config")), true) - } + }, _logger ); return _currentAssembliesHash; } @@ -219,9 +227,9 @@ namespace Umbraco.Core /// (true will make a hash based on it's contents) /// /// - internal static long GetFileHash(IEnumerable> filesAndFolders) + internal static long GetFileHash(IEnumerable> filesAndFolders, ProfilingLogger logger) { - using (DisposableTimer.TraceDuration("Determining hash of code files on disk", "Hash determined")) + using (logger.TraceDuration("Determining hash of code files on disk", "Hash determined")) { var hashCombiner = new HashCodeCombiner(); @@ -250,9 +258,9 @@ namespace Umbraco.Core } } - internal static long GetFileHash(IEnumerable filesAndFolders) + internal static long GetFileHash(IEnumerable filesAndFolders, ProfilingLogger logger) { - using (DisposableTimer.TraceDuration("Determining hash of code files on disk", "Hash determined")) + using (logger.TraceDuration("Determining hash of code files on disk", "Hash determined")) { var hashCombiner = new HashCodeCombiner(); @@ -297,18 +305,9 @@ namespace Umbraco.Core { //we will load the xml document, if the app context exist, we will load it from the cache (which is only around for 5 minutes) //while the app boots up, this should save some IO time on app startup when the app context is there (which is always unless in unit tests) - XDocument xml; - if (_appContext != null) - { - xml = _appContext.ApplicationCache.GetCacheItem(CacheKey, - new TimeSpan(0, 0, 5, 0), - () => XDocument.Load(filePath)); - } - else - { - xml = XDocument.Load(filePath); - } - + var xml = _runtimeCache.GetCacheItem(CacheKey, + () => XDocument.Load(filePath), + new TimeSpan(0, 0, 5, 0)); if (xml.Root == null) return Attempt>.Fail(); @@ -349,10 +348,7 @@ namespace Umbraco.Core if (File.Exists(path)) File.Delete(path); - if (_appContext != null) - { - _appContext.ApplicationCache.ClearCacheItem(CacheKey); - } + _runtimeCache.ClearCacheItem(CacheKey); } private string GetPluginListFilePath() @@ -590,35 +586,7 @@ namespace Umbraco.Core /// internal IEnumerable CreateInstances(IEnumerable types, bool throwException = false) { - //Have removed logging because it doesn't really need to be logged since the time taken is generally 0ms. - //we want to know if it fails ever, not how long it took if it is only 0. - - var typesAsArray = types.ToArray(); - //using (DisposableTimer.DebugDuration( - // String.Format("Starting instantiation of {0} objects of type {1}", typesAsArray.Length, typeof(T).FullName), - // String.Format("Completed instantiation of {0} objects of type {1}", typesAsArray.Length, typeof(T).FullName))) - //{ - var instances = new List(); - foreach (var t in typesAsArray) - { - try - { - var typeInstance = (T)Activator.CreateInstance(t); - instances.Add(typeInstance); - } - catch (Exception ex) - { - - LogHelper.Error(String.Format("Error creating type {0}", t.FullName), ex); - - if (throwException) - { - throw ex; - } - } - } - return instances; - //} + return _serviceProvider.CreateInstances(types, _logger.Logger, throwException); } /// @@ -643,9 +611,9 @@ namespace Umbraco.Core { var typesFound = new List(); - using (DisposableTimer.TraceDuration( - () => String.Format("Starting resolution types of {0}", typeof(T).FullName), - () => String.Format("Completed resolution of types of {0}, found {1}", typeof(T).FullName, typesFound.Count))) + using (_logger.TraceDuration( + String.Format("Starting resolution types of {0}", typeof(T).FullName), + String.Format("Completed resolution of types of {0}, found {1}", typeof(T).FullName, typesFound.Count))) { //check if the TypeList already exists, if so return it, if not we'll create it var typeList = _types.SingleOrDefault(x => x.IsTypeList(resolutionType)); @@ -653,7 +621,7 @@ namespace Umbraco.Core //need to put some logging here to try to figure out why this is happening: http://issues.umbraco.org/issue/U4-3505 if (cacheResult && typeList != null) { - LogHelper.Debug("Existing typeList found for {0} with resolution type {1}", () => typeof(T), () => resolutionType); + _logger.Logger.Debug("Existing typeList found for {0} with resolution type {1}", () => typeof(T), () => resolutionType); } //if we're not caching the result then proceed, or if the type list doesn't exist then proceed @@ -675,7 +643,7 @@ namespace Umbraco.Core //so in this instance there will never be a result. if (fileCacheResult.Exception != null && fileCacheResult.Exception is CachedPluginNotFoundInFileException) { - LogHelper.Debug("Tried to find typelist for type {0} and resolution {1} in file cache but the type was not found so loading types by assembly scan ", () => typeof(T), () => resolutionType); + _logger.Logger.Debug("Tried to find typelist for type {0} and resolution {1} in file cache but the type was not found so loading types by assembly scan ", () => typeof(T), () => resolutionType); //we don't have a cache for this so proceed to look them up by scanning LoadViaScanningAndUpdateCacheFile(typeList, resolutionType, finder); @@ -700,7 +668,7 @@ namespace Umbraco.Core //if there are any exceptions loading types, we have to exist, this should never happen so //we will need to revert to scanning for types. successfullyLoadedFromCache = false; - LogHelper.Error("Could not load a cached plugin type: " + t + " now reverting to re-scanning assemblies for the base type: " + typeof(T).FullName, ex); + _logger.Logger.Error("Could not load a cached plugin type: " + t + " now reverting to re-scanning assemblies for the base type: " + typeof(T).FullName, ex); break; } } @@ -711,14 +679,14 @@ namespace Umbraco.Core } else { - LogHelper.Debug("Loaded plugin types {0} with resolution {1} from persisted cache", () => typeof(T), () => resolutionType); + _logger.Logger.Debug("Loaded plugin types {0} with resolution {1} from persisted cache", () => typeof(T), () => resolutionType); } } } } else { - LogHelper.Debug("Assembly changes detected, loading types {0} for resolution {1} by assembly scan", () => typeof(T), () => resolutionType); + _logger.Logger.Debug("Assembly changes detected, loading types {0} for resolution {1} by assembly scan", () => typeof(T), () => resolutionType); //we don't have a cache for this so proceed to look them up by scanning LoadViaScanningAndUpdateCacheFile(typeList, resolutionType, finder); @@ -730,7 +698,7 @@ namespace Umbraco.Core //add the type list to the collection var added = _types.Add(typeList); - LogHelper.Debug("Caching of typelist for type {0} and resolution {1} was successful = {2}", () => typeof(T), () => resolutionType, () => added); + _logger.Logger.Debug("Caching of typelist for type {0} and resolution {1} was successful = {2}", () => typeof(T), () => resolutionType, () => added); } } diff --git a/src/Umbraco.Core/Profiling/IProfiler.cs b/src/Umbraco.Core/Profiling/IProfiler.cs index 4a3f7a8829..4a6a32194d 100644 --- a/src/Umbraco.Core/Profiling/IProfiler.cs +++ b/src/Umbraco.Core/Profiling/IProfiler.cs @@ -5,7 +5,7 @@ namespace Umbraco.Core.Profiling /// /// Defines an object for use in the application to profile operations /// - internal interface IProfiler + public interface IProfiler { /// /// Render the UI to display the profiler diff --git a/src/Umbraco.Core/Profiling/LogProfiler.cs b/src/Umbraco.Core/Profiling/LogProfiler.cs index fbcb21988a..117d177650 100644 --- a/src/Umbraco.Core/Profiling/LogProfiler.cs +++ b/src/Umbraco.Core/Profiling/LogProfiler.cs @@ -7,10 +7,17 @@ using Umbraco.Core.Logging; namespace Umbraco.Core.Profiling { /// - /// A profiler that outputs its results to the LogHelper + /// A profiler that outputs its results to an ILogger /// internal class LogProfiler : IProfiler { + private readonly ILogger _logger; + + public LogProfiler(ILogger logger) + { + _logger = logger; + } + public string Render() { return string.Empty; @@ -18,8 +25,8 @@ namespace Umbraco.Core.Profiling public IDisposable Step(string name) { - LogHelper.Debug(typeof(LogProfiler), "Starting - " + name); - return DisposableTimer.Start(l => LogHelper.Info(typeof(LogProfiler), () => name + " (took " + l + "ms)")); + _logger.Debug(typeof(LogProfiler), "Starting - " + name); + return new DisposableTimer(l => _logger.Info(typeof(LogProfiler), () => name + " (took " + l + "ms)")); } public void Start() diff --git a/src/Umbraco.Core/PropertyEditors/ParameterEditorResolver.cs b/src/Umbraco.Core/PropertyEditors/ParameterEditorResolver.cs index ef01b3a891..3c8d04fcf0 100644 --- a/src/Umbraco.Core/PropertyEditors/ParameterEditorResolver.cs +++ b/src/Umbraco.Core/PropertyEditors/ParameterEditorResolver.cs @@ -1,6 +1,7 @@ using System; using System.Collections.Generic; using System.Linq; +using Umbraco.Core.Logging; using Umbraco.Core.Manifest; using Umbraco.Core.ObjectResolution; @@ -15,8 +16,8 @@ namespace Umbraco.Core.PropertyEditors /// internal class ParameterEditorResolver : LazyManyObjectsResolverBase { - public ParameterEditorResolver(Func> typeListProducerList) - : base(typeListProducerList, ObjectLifetimeScope.Application) + public ParameterEditorResolver(IServiceProvider serviceProvider, ILogger logger, Func> typeListProducerList) + : base(serviceProvider, logger, typeListProducerList, ObjectLifetimeScope.Application) { } diff --git a/src/Umbraco.Core/PropertyEditors/PropertyEditorResolver.cs b/src/Umbraco.Core/PropertyEditors/PropertyEditorResolver.cs index 441d7fde2c..fa2d4da594 100644 --- a/src/Umbraco.Core/PropertyEditors/PropertyEditorResolver.cs +++ b/src/Umbraco.Core/PropertyEditors/PropertyEditorResolver.cs @@ -1,6 +1,7 @@ using System; using System.Collections.Generic; using System.Linq; +using Umbraco.Core.Logging; using Umbraco.Core.Manifest; using Umbraco.Core.ObjectResolution; @@ -14,6 +15,12 @@ namespace Umbraco.Core.PropertyEditors /// public class PropertyEditorResolver : LazyManyObjectsResolverBase { + public PropertyEditorResolver(IServiceProvider serviceProvider, ILogger logger, Func> typeListProducerList) + : base(serviceProvider, logger, typeListProducerList, ObjectLifetimeScope.Application) + { + } + + [Obsolete("Use the ctor specifying a PluginManager instead")] public PropertyEditorResolver(Func> typeListProducerList) : base(typeListProducerList, ObjectLifetimeScope.Application) { diff --git a/src/Umbraco.Core/PropertyEditors/PropertyValueConvertersResolver.cs b/src/Umbraco.Core/PropertyEditors/PropertyValueConvertersResolver.cs index 295fdb4b09..622ed2661f 100644 --- a/src/Umbraco.Core/PropertyEditors/PropertyValueConvertersResolver.cs +++ b/src/Umbraco.Core/PropertyEditors/PropertyValueConvertersResolver.cs @@ -2,6 +2,7 @@ using System; using System.Collections.Generic; using System.Linq; using System.Threading; +using Umbraco.Core.Logging; using Umbraco.Core.ObjectResolution; namespace Umbraco.Core.PropertyEditors @@ -15,20 +16,24 @@ namespace Umbraco.Core.PropertyEditors /// Initializes a new instance of the class with /// an initial list of converter types. /// + /// + /// /// The list of converter types /// The resolver is created by the WebBootManager and thus the constructor remains internal. - internal PropertyValueConvertersResolver(IEnumerable converters) - : base(converters) + internal PropertyValueConvertersResolver(IServiceProvider serviceProvider, ILogger logger, IEnumerable converters) + : base(serviceProvider, logger, converters) { } /// /// Initializes a new instance of the class with /// an initial list of converter types. /// + /// + /// /// The list of converter types /// The resolver is created by the WebBootManager and thus the constructor remains internal. - internal PropertyValueConvertersResolver(params Type[] converters) - : base(converters) + internal PropertyValueConvertersResolver(IServiceProvider serviceProvider, ILogger logger, params Type[] converters) + : base(serviceProvider, logger, converters) { } /// diff --git a/src/Umbraco.Core/PropertyEditors/ValidatorsResolver.cs b/src/Umbraco.Core/PropertyEditors/ValidatorsResolver.cs index 6fcbe112f7..547271a941 100644 --- a/src/Umbraco.Core/PropertyEditors/ValidatorsResolver.cs +++ b/src/Umbraco.Core/PropertyEditors/ValidatorsResolver.cs @@ -1,6 +1,7 @@ using System; using System.Collections.Generic; using System.Linq; +using Umbraco.Core.Logging; using Umbraco.Core.ObjectResolution; namespace Umbraco.Core.PropertyEditors @@ -9,9 +10,9 @@ namespace Umbraco.Core.PropertyEditors /// A resolver to resolve all registered validators /// internal class ValidatorsResolver : LazyManyObjectsResolverBase - { - public ValidatorsResolver(IEnumerable> lazyTypeList) - : base(lazyTypeList, ObjectLifetimeScope.Application) + { + public ValidatorsResolver(IServiceProvider serviceProvider, ILogger logger, IEnumerable> lazyTypeList) + : base(serviceProvider, logger, lazyTypeList, ObjectLifetimeScope.Application) { } diff --git a/src/Umbraco.Core/ServiceProviderExtensions.cs b/src/Umbraco.Core/ServiceProviderExtensions.cs new file mode 100644 index 0000000000..335396ede6 --- /dev/null +++ b/src/Umbraco.Core/ServiceProviderExtensions.cs @@ -0,0 +1,45 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using Umbraco.Core.Logging; + +namespace Umbraco.Core +{ + internal static class ServiceProviderExtensions + { + /// + /// Used to create instances of the specified type based on the resolved/cached plugin types + /// + /// + /// + /// + /// + /// set to true if an exception is to be thrown if there is an error during instantiation + /// + public static IEnumerable CreateInstances(this IServiceProvider serviceProvider, IEnumerable types, ILogger logger, bool throwException = false) + { + var typesAsArray = types.ToArray(); + + var instances = new List(); + foreach (var t in typesAsArray) + { + try + { + var typeInstance = (T) serviceProvider.GetService(t); + instances.Add(typeInstance); + } + catch (Exception ex) + { + + logger.Error(String.Format("Error creating type {0}", t.FullName), ex); + + if (throwException) + { + throw; + } + } + } + return instances; + } + } +} \ No newline at end of file diff --git a/src/Umbraco.Core/Services/ApplicationTreeService.cs b/src/Umbraco.Core/Services/ApplicationTreeService.cs index 5278990d6a..a17d54ea8b 100644 --- a/src/Umbraco.Core/Services/ApplicationTreeService.cs +++ b/src/Umbraco.Core/Services/ApplicationTreeService.cs @@ -15,6 +15,7 @@ namespace Umbraco.Core.Services { internal class ApplicationTreeService : IApplicationTreeService { + private readonly ILogger _logger; private readonly CacheHelper _cache; private IEnumerable _allAvailableTrees; private volatile bool _isInitialized = false; @@ -22,12 +23,12 @@ namespace Umbraco.Core.Services private static string _treeConfig; private static readonly object Locker = new object(); - public ApplicationTreeService(CacheHelper cache) + public ApplicationTreeService(ILogger logger, CacheHelper cache) { + _logger = logger; _cache = cache; } - /// /// gets/sets the trees.config file path @@ -340,7 +341,7 @@ namespace Umbraco.Core.Services var clrType = Type.GetType(type); if (clrType == null) { - LogHelper.Warn("The tree definition: " + addElement.ToString() + " could not be resolved to a .Net object type"); + _logger.Warn("The tree definition: " + addElement.ToString() + " could not be resolved to a .Net object type"); continue; } diff --git a/src/Umbraco.Core/Services/ContentService.cs b/src/Umbraco.Core/Services/ContentService.cs index 93069b7bd9..fdc5885cda 100644 --- a/src/Umbraco.Core/Services/ContentService.cs +++ b/src/Umbraco.Core/Services/ContentService.cs @@ -5,13 +5,14 @@ using System.Linq; using System.Threading; using System.Xml.Linq; using Umbraco.Core.Auditing; +using Umbraco.Core.Configuration; using Umbraco.Core.Events; 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.Caching; + using Umbraco.Core.Persistence.DatabaseModelDefinitions; using Umbraco.Core.Persistence.Querying; using Umbraco.Core.Persistence.Repositories; @@ -26,6 +27,7 @@ namespace Umbraco.Core.Services /// public class ContentService : IContentService { + private readonly ILogger _logger; private readonly IDatabaseUnitOfWorkProvider _uowProvider; private readonly IPublishingStrategy _publishingStrategy; private readonly RepositoryFactory _repositoryFactory; @@ -37,27 +39,34 @@ namespace Umbraco.Core.Services //for example, the Move method needs to be locked but this calls the Save method which also needs to be locked. private static readonly ReaderWriterLockSlim Locker = new ReaderWriterLockSlim(LockRecursionPolicy.SupportsRecursion); + [Obsolete("Use the constructors that specify all dependencies instead")] public ContentService() - : this(new RepositoryFactory()) + : this(LoggerResolver.Current.Logger, new RepositoryFactory(ApplicationContext.Current.ApplicationCache, LoggerResolver.Current.Logger, SqlSyntaxContext.SqlSyntaxProvider, UmbracoConfig.For.UmbracoSettings())) { } - public ContentService(RepositoryFactory repositoryFactory) - : this(new PetaPocoUnitOfWorkProvider(), repositoryFactory, new PublishingStrategy()) + [Obsolete("Use the constructors that specify all dependencies instead")] + public ContentService(ILogger logger, RepositoryFactory repositoryFactory) + : this(logger, new PetaPocoUnitOfWorkProvider(LoggerResolver.Current.Logger), repositoryFactory, new PublishingStrategy()) { } - public ContentService(IDatabaseUnitOfWorkProvider provider) - : this(provider, new RepositoryFactory(), new PublishingStrategy()) + [Obsolete("Use the constructors that specify all dependencies instead")] + public ContentService(ILogger logger, IDatabaseUnitOfWorkProvider provider) + : this(logger, provider, new RepositoryFactory(ApplicationContext.Current.ApplicationCache, LoggerResolver.Current.Logger, SqlSyntaxContext.SqlSyntaxProvider, UmbracoConfig.For.UmbracoSettings()), new PublishingStrategy()) { } - public ContentService(IDatabaseUnitOfWorkProvider provider, RepositoryFactory repositoryFactory) - : this(provider, repositoryFactory, new PublishingStrategy()) + [Obsolete("Use the constructors that specify all dependencies instead")] + public ContentService(ILogger logger, IDatabaseUnitOfWorkProvider provider, RepositoryFactory repositoryFactory) + : this(logger, provider, repositoryFactory, new PublishingStrategy()) { } - public ContentService(IDatabaseUnitOfWorkProvider provider, RepositoryFactory repositoryFactory, IPublishingStrategy publishingStrategy) + [Obsolete("Use the constructors that specify all dependencies instead")] + public ContentService(ILogger logger, IDatabaseUnitOfWorkProvider provider, RepositoryFactory repositoryFactory, IPublishingStrategy publishingStrategy) { + if (logger == null) throw new ArgumentNullException("logger"); if (provider == null) throw new ArgumentNullException("provider"); if (repositoryFactory == null) throw new ArgumentNullException("repositoryFactory"); if (publishingStrategy == null) throw new ArgumentNullException("publishingStrategy"); + _logger = logger; _uowProvider = provider; _publishingStrategy = publishingStrategy; _repositoryFactory = repositoryFactory; @@ -65,11 +74,13 @@ namespace Umbraco.Core.Services _userService = new UserService(provider, repositoryFactory); } - public ContentService(IDatabaseUnitOfWorkProvider provider, RepositoryFactory repositoryFactory, IPublishingStrategy publishingStrategy, IDataTypeService dataTypeService, IUserService userService) + public ContentService(ILogger logger, IDatabaseUnitOfWorkProvider provider, RepositoryFactory repositoryFactory, IPublishingStrategy publishingStrategy, IDataTypeService dataTypeService, IUserService userService) { + if (logger == null) throw new ArgumentNullException("logger"); if (provider == null) throw new ArgumentNullException("provider"); if (repositoryFactory == null) throw new ArgumentNullException("repositoryFactory"); if (publishingStrategy == null) throw new ArgumentNullException("publishingStrategy"); + _logger = logger; _uowProvider = provider; _publishingStrategy = publishingStrategy; _repositoryFactory = repositoryFactory; @@ -775,7 +786,7 @@ namespace Umbraco.Core.Services } catch (Exception ex) { - LogHelper.Error("An error occurred executing RePublishAll", ex); + _logger.Error("An error occurred executing RePublishAll", ex); return false; } } @@ -795,7 +806,7 @@ namespace Umbraco.Core.Services } catch (Exception ex) { - LogHelper.Error("An error occurred executing RePublishAll", ex); + _logger.Error("An error occurred executing RePublishAll", ex); } } @@ -808,7 +819,7 @@ namespace Umbraco.Core.Services public bool Publish(IContent content, int userId = 0) { var result = SaveAndPublishDo(content, userId); - LogHelper.Info("Call was made to ContentService.Publish, use PublishWithStatus instead since that method will provide more detailed information on the outcome"); + _logger.Info("Call was made to ContentService.Publish, use PublishWithStatus instead since that method will provide more detailed information on the outcome"); return result.Success; } @@ -1318,11 +1329,6 @@ namespace Umbraco.Core.Services Copied.RaiseEvent(new CopyEventArgs(content, copy, false, parentId, relateToOriginal), this); Audit.Add(AuditTypes.Copy, "Copy Content performed by user", content.WriterId, content.Id); - - //TODO: Don't think we need this here because cache should be cleared by the event listeners - // and the correct ICacheRefreshers!? - RuntimeCacheProvider.Current.Clear(); - return copy; } } @@ -1611,7 +1617,7 @@ namespace Umbraco.Core.Services //Check if parent is published (although not if its a root node) - if parent isn't published this Content cannot be published if (content.ParentId != Constants.System.Root && content.ParentId != Constants.System.RecycleBinContent && IsPublishable(content) == false) { - LogHelper.Info( + _logger.Info( string.Format( "Content '{0}' with Id '{1}' could not be published because its parent or one of its ancestors is not published.", content.Name, content.Id)); @@ -1622,7 +1628,7 @@ namespace Umbraco.Core.Services //Content contains invalid property values and can therefore not be published - fire event? if (!content.IsValid()) { - LogHelper.Info( + _logger.Info( string.Format("Content '{0}' with Id '{1}' could not be published because of invalid properties.", content.Name, content.Id)); result.Add( @@ -1885,7 +1891,7 @@ namespace Umbraco.Core.Services //Check if parent is published (although not if its a root node) - if parent isn't published this Content cannot be published if (content.ParentId != Constants.System.Root && content.ParentId != Constants.System.RecycleBinContent && IsPublishable(content) == false) { - LogHelper.Info( + _logger.Info( string.Format( "Content '{0}' with Id '{1}' could not be published because its parent is not published.", content.Name, content.Id)); @@ -1900,7 +1906,7 @@ namespace Umbraco.Core.Services //Content contains invalid property values and can therefore not be published - fire event? if (content.IsValid() == false) { - LogHelper.Info( + _logger.Info( string.Format( "Content '{0}' with Id '{1}' could not be published because of invalid properties.", content.Name, content.Id)); diff --git a/src/Umbraco.Core/Services/ContentTypeService.cs b/src/Umbraco.Core/Services/ContentTypeService.cs index 4c1f9cd038..c98becabf2 100644 --- a/src/Umbraco.Core/Services/ContentTypeService.cs +++ b/src/Umbraco.Core/Services/ContentTypeService.cs @@ -28,21 +28,30 @@ namespace Umbraco.Core.Services private readonly RepositoryFactory _repositoryFactory; private readonly IContentService _contentService; private readonly IMediaService _mediaService; + private readonly ILogger _logger; private readonly IDatabaseUnitOfWorkProvider _uowProvider; //Support recursive locks because some of the methods that require locking call other methods that require locking. //for example, the Move method needs to be locked but this calls the Save method which also needs to be locked. - private static readonly ReaderWriterLockSlim Locker = new ReaderWriterLockSlim(LockRecursionPolicy.SupportsRecursion); + private static readonly ReaderWriterLockSlim Locker = new ReaderWriterLockSlim(LockRecursionPolicy.SupportsRecursion); - public ContentTypeService(IContentService contentService, IMediaService mediaService) - : this(new PetaPocoUnitOfWorkProvider(), new RepositoryFactory(), contentService, mediaService) + [Obsolete("Use the constructors that specify all dependencies instead")] + public ContentTypeService(ILogger logger, IContentService contentService, IMediaService mediaService) + : this(logger, new PetaPocoUnitOfWorkProvider(logger), new RepositoryFactory(), contentService, mediaService) {} - public ContentTypeService(RepositoryFactory repositoryFactory, IContentService contentService, IMediaService mediaService) - : this(new PetaPocoUnitOfWorkProvider(), repositoryFactory, contentService, mediaService) + [Obsolete("Use the constructors that specify all dependencies instead")] + public ContentTypeService(ILogger logger, RepositoryFactory repositoryFactory, IContentService contentService, IMediaService mediaService) + : this(logger, new PetaPocoUnitOfWorkProvider(), repositoryFactory, contentService, mediaService) { } - public ContentTypeService(IDatabaseUnitOfWorkProvider provider, RepositoryFactory repositoryFactory, IContentService contentService, IMediaService mediaService) + public ContentTypeService(ILogger logger, IDatabaseUnitOfWorkProvider provider, RepositoryFactory repositoryFactory, IContentService contentService, IMediaService mediaService) { + if (logger == null) throw new ArgumentNullException("logger"); + if (provider == null) throw new ArgumentNullException("provider"); + if (repositoryFactory == null) throw new ArgumentNullException("repositoryFactory"); + if (contentService == null) throw new ArgumentNullException("contentService"); + if (mediaService == null) throw new ArgumentNullException("mediaService"); + _logger = logger; _uowProvider = provider; _repositoryFactory = repositoryFactory; _contentService = contentService; diff --git a/src/Umbraco.Core/Services/DataTypeService.cs b/src/Umbraco.Core/Services/DataTypeService.cs index 63e0a390e7..7b03615d2f 100644 --- a/src/Umbraco.Core/Services/DataTypeService.cs +++ b/src/Umbraco.Core/Services/DataTypeService.cs @@ -21,17 +21,19 @@ namespace Umbraco.Core.Services { private readonly RepositoryFactory _repositoryFactory; private readonly IDatabaseUnitOfWorkProvider _uowProvider; - private static readonly ReaderWriterLockSlim Locker = new ReaderWriterLockSlim(LockRecursionPolicy.SupportsRecursion); + [Obsolete("Use the constructors that specify all dependencies instead")] public DataTypeService() : this(new RepositoryFactory()) {} + [Obsolete("Use the constructors that specify all dependencies instead")] public DataTypeService(RepositoryFactory repositoryFactory) : this(new PetaPocoUnitOfWorkProvider(), repositoryFactory) { } + [Obsolete("Use the constructors that specify all dependencies instead")] public DataTypeService(IDatabaseUnitOfWorkProvider provider) : this(provider, new RepositoryFactory()) { diff --git a/src/Umbraco.Core/Services/FileService.cs b/src/Umbraco.Core/Services/FileService.cs index 56f7d3a07b..258539b4c2 100644 --- a/src/Umbraco.Core/Services/FileService.cs +++ b/src/Umbraco.Core/Services/FileService.cs @@ -3,15 +3,17 @@ using System.Collections.Generic; using System.IO; using System.Linq; using System.Runtime.Remoting.Messaging; -using System.Text; using System.Text.RegularExpressions; using System.Web; using Umbraco.Core.Auditing; +using Umbraco.Core.Configuration; +using Umbraco.Core.Configuration.UmbracoSettings; using Umbraco.Core.Events; using Umbraco.Core.IO; using Umbraco.Core.Logging; using Umbraco.Core.Models; using Umbraco.Core.Persistence; +using Umbraco.Core.Persistence.Querying; using Umbraco.Core.Persistence.Repositories; using Umbraco.Core.Persistence.UnitOfWork; @@ -29,10 +31,12 @@ namespace Umbraco.Core.Services private const string PartialViewHeader = "@inherits Umbraco.Web.Mvc.UmbracoTemplatePage"; private const string PartialViewMacroHeader = "@inherits Umbraco.Web.Macros.PartialViewMacroPage"; + [Obsolete("Use the constructors that specify all dependencies instead")] public FileService() : this(new RepositoryFactory()) { } + [Obsolete("Use the constructors that specify all dependencies instead")] public FileService(RepositoryFactory repositoryFactory) : this(new FileUnitOfWorkProvider(), new PetaPocoUnitOfWorkProvider(), repositoryFactory) { @@ -40,6 +44,9 @@ namespace Umbraco.Core.Services public FileService(IUnitOfWorkProvider fileProvider, IDatabaseUnitOfWorkProvider dataProvider, RepositoryFactory repositoryFactory) { + if (fileProvider == null) throw new ArgumentNullException("fileProvider"); + if (dataProvider == null) throw new ArgumentNullException("dataProvider"); + if (repositoryFactory == null) throw new ArgumentNullException("repositoryFactory"); _repositoryFactory = repositoryFactory; _fileUowProvider = fileProvider; _dataUowProvider = dataProvider; @@ -127,7 +134,12 @@ namespace Umbraco.Core.Services /// True if Stylesheet is valid, otherwise false public bool ValidateStylesheet(Stylesheet stylesheet) { - return stylesheet.IsValid() && stylesheet.IsFileValidCss(); + + var uow = _fileUowProvider.GetUnitOfWork(); + using (var repository = _repositoryFactory.CreateStylesheetRepository(uow, _dataUowProvider.GetUnitOfWork())) + { + return repository.ValidateStylesheet(stylesheet); + } } #endregion @@ -211,7 +223,11 @@ namespace Umbraco.Core.Services /// True if Script is valid, otherwise false public bool ValidateScript(Script script) { - return script.IsValid(); + var uow = _fileUowProvider.GetUnitOfWork(); + using (var repository = _repositoryFactory.CreateScriptRepository(uow)) + { + return repository.ValidateScript(script); + } } public void CreateScriptFolder(string folderPath) @@ -238,6 +254,21 @@ namespace Umbraco.Core.Services #region Templates + + public ITemplate CreateTemplateWithIdentity(string name, string content, ITemplate masterTemplate = null, int userId = 0) + { + var template = new Template(name, name) + { + Content = content + }; + if (masterTemplate != null) + { + template.SetMasterTemplate(masterTemplate); + } + SaveTemplate(template, userId); + return template; + } + /// /// Gets a list of all objects /// @@ -246,7 +277,19 @@ namespace Umbraco.Core.Services { using (var repository = _repositoryFactory.CreateTemplateRepository(_dataUowProvider.GetUnitOfWork())) { - return repository.GetAll(aliases); + return repository.GetAll(aliases).OrderBy(x => x.Name); + } + } + + /// + /// Gets a list of all objects + /// + /// An enumerable list of objects + public IEnumerable GetTemplates(int masterTemplateId) + { + using (var repository = _repositoryFactory.CreateTemplateRepository(_dataUowProvider.GetUnitOfWork())) + { + return repository.GetChildren(masterTemplateId).OrderBy(x => x.Name); } } @@ -350,6 +393,28 @@ namespace Umbraco.Core.Services Audit.Add(AuditTypes.Save, string.Format("Save Template performed by user"), userId, -1); } + /// + /// 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 + /// templates in business logic. Without this, it could cause the wrong rendering engine to be used for a package. + /// + public RenderingEngine DetermineTemplateRenderingEngine(ITemplate template) + { + var uow = _dataUowProvider.GetUnitOfWork(); + using (var repository = _repositoryFactory.CreateTemplateRepository(uow)) + { + return repository.DetermineTemplateRenderingEngine(template); + } + } + /// /// Deletes a template by its alias /// @@ -382,7 +447,11 @@ namespace Umbraco.Core.Services /// True if Script is valid, otherwise false public bool ValidateTemplate(ITemplate template) { - return template.IsValid(); + var uow = _dataUowProvider.GetUnitOfWork(); + using (var repository = _repositoryFactory.CreateTemplateRepository(uow)) + { + return repository.ValidateTemplate(template); + } } #endregion @@ -598,9 +667,12 @@ namespace Umbraco.Core.Services return Attempt.Succeed(partialView); } - internal bool ValidatePartialView(PartialView partialView) + public bool ValidatePartialView(PartialView partialView) { - return partialView.IsValid(); + var validatePath = IOHelper.ValidateEditPath(partialView.Path, new[] { SystemDirectories.MvcViews + "/Partials/", SystemDirectories.MvcViews + "/MacroPartials/" }); + var verifyFileExtension = IOHelper.VerifyFileExtension(partialView.Path, new List { "cshtml" }); + + return validatePath && verifyFileExtension; } internal string StripPartialViewHeader(string contents) @@ -725,5 +797,8 @@ namespace Umbraco.Core.Services #endregion + + + } } \ No newline at end of file diff --git a/src/Umbraco.Core/Services/IFileService.cs b/src/Umbraco.Core/Services/IFileService.cs index 924fb0c093..484226ae78 100644 --- a/src/Umbraco.Core/Services/IFileService.cs +++ b/src/Umbraco.Core/Services/IFileService.cs @@ -19,13 +19,14 @@ namespace Umbraco.Core.Services bool DeletePartialViewMacro(string path, int userId = 0); Attempt SavePartialView(IPartialView partialView, int userId = 0); Attempt SavePartialViewMacro(IPartialView partialView, int userId = 0); + bool ValidatePartialView(PartialView partialView); /// /// Gets a list of all objects /// /// An enumerable list of objects IEnumerable GetStylesheets(params string[] names); - + /// /// Gets a object by its name /// @@ -107,6 +108,12 @@ namespace Umbraco.Core.Services /// An enumerable list of objects IEnumerable GetTemplates(params string[] aliases); + /// + /// Gets a list of all objects + /// + /// An enumerable list of objects + IEnumerable GetTemplates(int masterTemplateId); + /// /// Gets a object by its alias /// @@ -143,6 +150,8 @@ namespace Umbraco.Core.Services /// Optional id of the user saving the template void SaveTemplate(ITemplate template, int userId = 0); + ITemplate CreateTemplateWithIdentity(string name, string content, ITemplate masterTemplate = null, int userId = 0); + /// /// Deletes a template by its alias /// @@ -163,5 +172,20 @@ namespace Umbraco.Core.Services /// List of to save /// Optional id of the user void SaveTemplate(IEnumerable templates, int userId = 0); + + /// + /// 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 + /// templates in business logic. Without this, it could cause the wrong rendering engine to be used for a package. + /// + RenderingEngine DetermineTemplateRenderingEngine(ITemplate template); } } \ No newline at end of file diff --git a/src/Umbraco.Core/Services/ILocalizationService.cs b/src/Umbraco.Core/Services/ILocalizationService.cs index 5c3bc965ec..49eb8f266d 100644 --- a/src/Umbraco.Core/Services/ILocalizationService.cs +++ b/src/Umbraco.Core/Services/ILocalizationService.cs @@ -15,6 +15,24 @@ namespace Umbraco.Core.Services //Add/Set Text (Insert/Update) //Remove Text (in translation) + /// + /// Adds or updates a translation for a dictionary item and language + /// + /// + /// + /// + /// + void AddOrUpdateDictionaryValue(IDictionaryItem item, ILanguage language, string value); + + /// + /// Creates and saves a new dictionary item and assigns a value to all languages if defaultValue is specified. + /// + /// + /// + /// + /// + IDictionaryItem CreateDictionaryItemWithIdentity(string key, Guid? parentId, string defaultValue = null); + /// /// Gets a by its id /// diff --git a/src/Umbraco.Core/Services/LocalizationService.cs b/src/Umbraco.Core/Services/LocalizationService.cs index b7c0cb3b55..7fb7ae379c 100644 --- a/src/Umbraco.Core/Services/LocalizationService.cs +++ b/src/Umbraco.Core/Services/LocalizationService.cs @@ -2,10 +2,13 @@ using System; using System.Collections.Generic; using System.Linq; using Umbraco.Core.Auditing; +using Umbraco.Core.Configuration; using Umbraco.Core.Events; +using Umbraco.Core.Logging; using Umbraco.Core.Models; using Umbraco.Core.Persistence; using Umbraco.Core.Persistence.Querying; +using Umbraco.Core.Persistence.SqlSyntax; using Umbraco.Core.Persistence.UnitOfWork; namespace Umbraco.Core.Services @@ -17,19 +20,22 @@ namespace Umbraco.Core.Services { private readonly RepositoryFactory _repositoryFactory; private readonly IDatabaseUnitOfWorkProvider _uowProvider; - private static readonly Guid RootParentId = new Guid("41c7638d-f529-4bff-853e-59a0c2fb1bde"); + private static readonly Guid RootParentId = new Guid(Constants.Conventions.Localization.DictionaryItemRootId); + [Obsolete("Use the constructors that specify all dependencies instead")] public LocalizationService() - : this(new RepositoryFactory()) + : this(new RepositoryFactory(ApplicationContext.Current.ApplicationCache, LoggerResolver.Current.Logger, SqlSyntaxContext.SqlSyntaxProvider, UmbracoConfig.For.UmbracoSettings())) {} + [Obsolete("Use the constructors that specify all dependencies instead")] public LocalizationService(RepositoryFactory repositoryFactory) - : this(new PetaPocoUnitOfWorkProvider(), repositoryFactory) + : this(new PetaPocoUnitOfWorkProvider(LoggerResolver.Current.Logger), repositoryFactory) { } + [Obsolete("Use the constructors that specify all dependencies instead")] public LocalizationService(IDatabaseUnitOfWorkProvider provider) - : this(provider, new RepositoryFactory()) + : this(provider, new RepositoryFactory(ApplicationContext.Current.ApplicationCache, LoggerResolver.Current.Logger, SqlSyntaxContext.SqlSyntaxProvider, UmbracoConfig.For.UmbracoSettings())) { } @@ -39,6 +45,81 @@ namespace Umbraco.Core.Services _uowProvider = provider; } + /// + /// Adds or updates a translation for a dictionary item and language + /// + /// + /// + /// + /// + /// + /// This does not save the item, that needs to be done explicitly + /// + public void AddOrUpdateDictionaryValue(IDictionaryItem item, ILanguage language, string value) + { + if (item == null) throw new ArgumentNullException("item"); + if (language == null) throw new ArgumentNullException("language"); + + var existing = item.Translations.FirstOrDefault(x => x.Language.Id == language.Id); + if (existing != null) + { + existing.Value = value; + } + else + { + item.Translations = new List(item.Translations) + { + new DictionaryTranslation(language, value) + }; + } + } + + /// + /// Creates and saves a new dictionary item and assigns a value to all languages if defaultValue is specified. + /// + /// + /// + /// + /// + public IDictionaryItem CreateDictionaryItemWithIdentity(string key, Guid? parentId, string defaultValue = null) + { + var uow = _uowProvider.GetUnitOfWork(); + using (var repository = _repositoryFactory.CreateDictionaryRepository(uow)) + { + //validate the parent + if (parentId.HasValue && parentId.Value != Guid.Empty) + { + var parent = GetDictionaryItemById(parentId.Value); + if (parent == null) + { + throw new ArgumentException("No parent dictionary item was found with id " + parentId.Value); + } + } + + var item = new DictionaryItem(parentId.HasValue ? parentId.Value : RootParentId, key); + + if (defaultValue.IsNullOrWhiteSpace() == false) + { + var langs = GetAllLanguages(); + var translations = langs.Select(language => new DictionaryTranslation(language, defaultValue)) + .Cast() + .ToList(); + + item.Translations = translations; + } + + if (SavingDictionaryItem.IsRaisedEventCancelled(new SaveEventArgs(item), this)) + return item; + + repository.AddOrUpdate(item); + uow.Commit(); + + SavedDictionaryItem.RaiseEvent(new SaveEventArgs(item), this); + + return item; + } + } + /// /// Gets a by its id /// @@ -61,10 +142,11 @@ namespace Umbraco.Core.Services { using (var repository = _repositoryFactory.CreateDictionaryRepository(_uowProvider.GetUnitOfWork())) { - var query = Query.Builder.Where(x => x.Key == id); - var items = repository.GetByQuery(query); + return repository.Get(id); + //var query = Query.Builder.Where(x => x.Key == id); + //var items = repository.GetByQuery(query); - return items.FirstOrDefault(); + //return items.FirstOrDefault(); } } @@ -77,10 +159,11 @@ namespace Umbraco.Core.Services { using (var repository = _repositoryFactory.CreateDictionaryRepository(_uowProvider.GetUnitOfWork())) { - var query = Query.Builder.Where(x => x.ItemKey == key); - var items = repository.GetByQuery(query); + return repository.Get(key); + //var query = Query.Builder.Where(x => x.ItemKey == key); + //var items = repository.GetByQuery(query); - return items.FirstOrDefault(); + //return items.FirstOrDefault(); } } @@ -124,10 +207,11 @@ namespace Umbraco.Core.Services { using (var repository = _repositoryFactory.CreateDictionaryRepository(_uowProvider.GetUnitOfWork())) { - var query = Query.Builder.Where(x => x.ItemKey == key); - var items = repository.GetByQuery(query); + return repository.Get(key) != null; + //var query = Query.Builder.Where(x => x.ItemKey == key); + //var items = repository.GetByQuery(query); - return items.Any(); + //return items.Any(); } } @@ -199,10 +283,11 @@ namespace Umbraco.Core.Services { using (var repository = _repositoryFactory.CreateLanguageRepository(_uowProvider.GetUnitOfWork())) { - var query = Query.Builder.Where(x => x.CultureName == cultureName); - var items = repository.GetByQuery(query); + return repository.GetByCultureName(cultureName); + //var query = Query.Builder.Where(x => x.CultureName == cultureName); + //var items = repository.GetByQuery(query); - return items.FirstOrDefault(); + //return items.FirstOrDefault(); } } @@ -215,10 +300,11 @@ namespace Umbraco.Core.Services { using (var repository = _repositoryFactory.CreateLanguageRepository(_uowProvider.GetUnitOfWork())) { - var query = Query.Builder.Where(x => x.IsoCode == isoCode); - var items = repository.GetByQuery(query); + return repository.GetByIsoCode(isoCode); + //var query = Query.Builder.Where(x => x.IsoCode == isoCode); + //var items = repository.GetByQuery(query); - return items.FirstOrDefault(); + //return items.FirstOrDefault(); } } diff --git a/src/Umbraco.Core/Services/LocalizedTextService.cs b/src/Umbraco.Core/Services/LocalizedTextService.cs index c9d05f3a3b..cdd52d0787 100644 --- a/src/Umbraco.Core/Services/LocalizedTextService.cs +++ b/src/Umbraco.Core/Services/LocalizedTextService.cs @@ -13,6 +13,7 @@ namespace Umbraco.Core.Services public class LocalizedTextService : ILocalizedTextService { + private readonly ILogger _logger; private readonly IDictionary>> _dictionarySource; private readonly IDictionary> _xmlSource; @@ -20,8 +21,11 @@ namespace Umbraco.Core.Services /// Initializes with a file sources instance /// /// - public LocalizedTextService(LocalizedTextServiceFileSources fileSources) + /// + public LocalizedTextService(LocalizedTextServiceFileSources fileSources, ILogger logger) { + if (logger == null) throw new ArgumentNullException("logger"); + _logger = logger; _xmlSource = fileSources.GetXmlSources(); } @@ -29,10 +33,13 @@ namespace Umbraco.Core.Services /// Initializes with an XML source /// /// - public LocalizedTextService(IDictionary> source) + /// + public LocalizedTextService(IDictionary> source, ILogger logger) { if (source == null) throw new ArgumentNullException("source"); + if (logger == null) throw new ArgumentNullException("logger"); _xmlSource = source; + _logger = logger; } /// @@ -81,7 +88,7 @@ namespace Umbraco.Core.Services { if (_xmlSource.ContainsKey(culture) == false) { - LogHelper.Warn("The culture specified {0} was not found in any configured sources for this service", () => culture); + _logger.Warn("The culture specified {0} was not found in any configured sources for this service", () => culture); return result; } @@ -105,7 +112,7 @@ namespace Umbraco.Core.Services { if (_dictionarySource.ContainsKey(culture) == false) { - LogHelper.Warn("The culture specified {0} was not found in any configured sources for this service", () => culture); + _logger.Warn("The culture specified {0} was not found in any configured sources for this service", () => culture); return result; } @@ -140,7 +147,7 @@ namespace Umbraco.Core.Services { if (_dictionarySource.ContainsKey(culture) == false) { - LogHelper.Warn("The culture specified {0} was not found in any configured sources for this service", () => culture); + _logger.Warn("The culture specified {0} was not found in any configured sources for this service", () => culture); return "[" + key + "]"; } @@ -178,7 +185,7 @@ namespace Umbraco.Core.Services { if (_xmlSource.ContainsKey(culture) == false) { - LogHelper.Warn("The culture specified {0} was not found in any configured sources for this service", () => culture); + _logger.Warn("The culture specified {0} was not found in any configured sources for this service", () => culture); return "[" + key + "]"; } diff --git a/src/Umbraco.Core/Services/MacroService.cs b/src/Umbraco.Core/Services/MacroService.cs index 9e7dc66b59..2c656f240f 100644 --- a/src/Umbraco.Core/Services/MacroService.cs +++ b/src/Umbraco.Core/Services/MacroService.cs @@ -21,11 +21,13 @@ namespace Umbraco.Core.Services private readonly RepositoryFactory _repositoryFactory; private readonly IDatabaseUnitOfWorkProvider _uowProvider; + [Obsolete("Use the constructors that specify all dependencies instead")] public MacroService() : this(new PetaPocoUnitOfWorkProvider(), new RepositoryFactory()) { } - + + [Obsolete("Use the constructors that specify all dependencies instead")] public MacroService(IDatabaseUnitOfWorkProvider provider) : this(provider, new RepositoryFactory()) { diff --git a/src/Umbraco.Core/Services/MediaService.cs b/src/Umbraco.Core/Services/MediaService.cs index 279ec9f07f..e8a547897a 100644 --- a/src/Umbraco.Core/Services/MediaService.cs +++ b/src/Umbraco.Core/Services/MediaService.cs @@ -36,11 +36,13 @@ namespace Umbraco.Core.Services private readonly IDataTypeService _dataTypeService; private readonly IUserService _userService; + [Obsolete("Use the constructors that specify all dependencies instead")] public MediaService(RepositoryFactory repositoryFactory) : this(new PetaPocoUnitOfWorkProvider(), repositoryFactory) { } + [Obsolete("Use the constructors that specify all dependencies instead")] public MediaService(IDatabaseUnitOfWorkProvider provider, RepositoryFactory repositoryFactory) { _uowProvider = provider; @@ -1113,6 +1115,8 @@ namespace Umbraco.Core.Services private IMediaType FindMediaTypeByAlias(string mediaTypeAlias) { + Mandate.ParameterNotNullOrEmpty(mediaTypeAlias, "mediaTypeAlias"); + var uow = _uowProvider.GetUnitOfWork(); using (var repository = _repositoryFactory.CreateMediaTypeRepository(uow)) { diff --git a/src/Umbraco.Core/Services/MemberGroupService.cs b/src/Umbraco.Core/Services/MemberGroupService.cs index ae12614d56..dd223e69ba 100644 --- a/src/Umbraco.Core/Services/MemberGroupService.cs +++ b/src/Umbraco.Core/Services/MemberGroupService.cs @@ -1,3 +1,4 @@ +using System; using System.Collections.Generic; using System.Linq; using Umbraco.Core.Events; @@ -14,11 +15,13 @@ namespace Umbraco.Core.Services private readonly RepositoryFactory _repositoryFactory; private readonly IDatabaseUnitOfWorkProvider _uowProvider; + [Obsolete("Use the constructors that specify all dependencies instead")] public MemberGroupService(RepositoryFactory repositoryFactory) : this(new PetaPocoUnitOfWorkProvider(), repositoryFactory) { } + [Obsolete("Use the constructors that specify all dependencies instead")] public MemberGroupService(IDatabaseUnitOfWorkProvider provider) : this(provider, new RepositoryFactory()) { diff --git a/src/Umbraco.Core/Services/MemberService.cs b/src/Umbraco.Core/Services/MemberService.cs index 5aa94fb409..2b226ef4fd 100644 --- a/src/Umbraco.Core/Services/MemberService.cs +++ b/src/Umbraco.Core/Services/MemberService.cs @@ -31,16 +31,19 @@ namespace Umbraco.Core.Services private readonly IDataTypeService _dataTypeService; private static readonly ReaderWriterLockSlim Locker = new ReaderWriterLockSlim(); + [Obsolete("Use the constructors that specify all dependencies instead")] public MemberService(RepositoryFactory repositoryFactory, IMemberGroupService memberGroupService) : this(new PetaPocoUnitOfWorkProvider(), repositoryFactory, memberGroupService) { } + [Obsolete("Use the constructors that specify all dependencies instead")] public MemberService(IDatabaseUnitOfWorkProvider provider, IMemberGroupService memberGroupService) : this(provider, new RepositoryFactory(), memberGroupService) { } + [Obsolete("Use the constructors that specify all dependencies instead")] public MemberService(IDatabaseUnitOfWorkProvider provider, RepositoryFactory repositoryFactory, IMemberGroupService memberGroupService) { if (provider == null) throw new ArgumentNullException("provider"); @@ -52,6 +55,7 @@ namespace Umbraco.Core.Services _dataTypeService = new DataTypeService(provider, repositoryFactory); } + [Obsolete("Use the constructors that specify all dependencies instead")] public MemberService(IDatabaseUnitOfWorkProvider provider, IMemberGroupService memberGroupService, IDataTypeService dataTypeService) : this(provider, new RepositoryFactory(), memberGroupService, dataTypeService) { diff --git a/src/Umbraco.Core/Services/MemberTypeService.cs b/src/Umbraco.Core/Services/MemberTypeService.cs index 81a91e37b5..dc49d89230 100644 --- a/src/Umbraco.Core/Services/MemberTypeService.cs +++ b/src/Umbraco.Core/Services/MemberTypeService.cs @@ -19,10 +19,12 @@ namespace Umbraco.Core.Services private static readonly ReaderWriterLockSlim Locker = new ReaderWriterLockSlim(); + [Obsolete("Use the constructors that specify all dependencies instead")] public MemberTypeService(IMemberService memberService) : this(new PetaPocoUnitOfWorkProvider(), new RepositoryFactory(), memberService) {} + [Obsolete("Use the constructors that specify all dependencies instead")] public MemberTypeService(RepositoryFactory repositoryFactory, IMemberService memberService) : this(new PetaPocoUnitOfWorkProvider(), repositoryFactory, memberService) { } diff --git a/src/Umbraco.Core/Services/NotificationService.cs b/src/Umbraco.Core/Services/NotificationService.cs index 6dd9017924..1aae82f52c 100644 --- a/src/Umbraco.Core/Services/NotificationService.cs +++ b/src/Umbraco.Core/Services/NotificationService.cs @@ -24,12 +24,18 @@ namespace Umbraco.Core.Services private readonly IDatabaseUnitOfWorkProvider _uowProvider; private readonly IUserService _userService; private readonly IContentService _contentService; + private readonly ILogger _logger; - public NotificationService(IDatabaseUnitOfWorkProvider provider, IUserService userService, IContentService contentService) + public NotificationService(IDatabaseUnitOfWorkProvider provider, IUserService userService, IContentService contentService, ILogger logger) { + if (provider == null) throw new ArgumentNullException("provider"); + if (userService == null) throw new ArgumentNullException("userService"); + if (contentService == null) throw new ArgumentNullException("contentService"); + if (logger == null) throw new ArgumentNullException("logger"); _uowProvider = provider; _userService = userService; _contentService = contentService; + _logger = logger; } /// @@ -75,11 +81,11 @@ namespace Umbraco.Core.Services try { SendNotification(operatingUser, u, content, allVersions, actionName, http, createSubject, createBody); - LogHelper.Debug(string.Format("Notification type: {0} sent to {1} ({2})", action, u.Name, u.Email)); + _logger.Debug(string.Format("Notification type: {0} sent to {1} ({2})", action, u.Name, u.Email)); } catch (Exception ex) { - LogHelper.Error("An error occurred sending notification", ex); + _logger.Error("An error occurred sending notification", ex); } } } @@ -331,7 +337,7 @@ namespace Umbraco.Core.Services } catch (Exception ex) { - LogHelper.Error("An error occurred sending notification", ex); + _logger.Error("An error occurred sending notification", ex); } }); } diff --git a/src/Umbraco.Core/Services/PackagingService.cs b/src/Umbraco.Core/Services/PackagingService.cs index 579da33a9d..2e22e81fe1 100644 --- a/src/Umbraco.Core/Services/PackagingService.cs +++ b/src/Umbraco.Core/Services/PackagingService.cs @@ -26,6 +26,7 @@ namespace Umbraco.Core.Services /// public class PackagingService : IPackagingService { + private readonly ILogger _logger; private readonly IContentService _contentService; private readonly IContentTypeService _contentTypeService; private readonly IMediaService _mediaService; @@ -40,7 +41,9 @@ namespace Umbraco.Core.Services private readonly IUserService _userService; - public PackagingService(IContentService contentService, + public PackagingService( + ILogger logger, + IContentService contentService, IContentTypeService contentTypeService, IMediaService mediaService, IMacroService macroService, @@ -51,6 +54,7 @@ namespace Umbraco.Core.Services RepositoryFactory repositoryFactory, IDatabaseUnitOfWorkProvider uowProvider) { + _logger = logger; _contentService = contentService; _contentTypeService = contentTypeService; _mediaService = mediaService; @@ -531,7 +535,7 @@ namespace Umbraco.Core.Services } else { - LogHelper.Warn( + _logger.Warn( string.Format( "Packager: Error handling allowed templates. Template with alias '{0}' could not be found.", alias)); @@ -550,7 +554,7 @@ namespace Umbraco.Core.Services } else { - LogHelper.Warn( + _logger.Warn( string.Format( "Packager: Error handling default template. Default template with alias '{0}' could not be found.", defaultTemplateElement.Value)); @@ -624,7 +628,7 @@ namespace Umbraco.Core.Services // This means that the property will not be created. if (dataTypeDefinition == null) { - LogHelper.Warn( + _logger.Warn( string.Format("Packager: Error handling creation of PropertyType '{0}'. Could not find DataTypeDefintion with unique id '{1}' nor one referencing the DataType with a property editor alias (or legacy control id) '{2}'. Did the package creator forget to package up custom datatypes? This property will be converted to a label/readonly editor if one exists.", property.Element("Name").Value, dataTypeDefinitionId, @@ -680,7 +684,7 @@ namespace Umbraco.Core.Services } else { - LogHelper.Warn( + _logger.Warn( string.Format( "Packager: Error handling DocumentType structure. DocumentType with alias '{0}' could not be found and was not added to the structure for '{1}'.", alias, contentType.Alias)); @@ -1355,7 +1359,7 @@ namespace Umbraco.Core.Services templateElements.Any(x => x.Element("Alias").Value == elementCopy.Element("Master").Value) == false) { - LogHelper.Info(string.Format("Template '{0}' has an invalid Master '{1}', so the reference has been ignored.", elementCopy.Element("Alias").Value, elementCopy.Element("Master").Value)); + _logger.Info(string.Format("Template '{0}' has an invalid Master '{1}', so the reference has been ignored.", elementCopy.Element("Alias").Value, elementCopy.Element("Master").Value)); } var field = new TopologicalSorter.DependencyField diff --git a/src/Umbraco.Core/Services/ServiceContext.cs b/src/Umbraco.Core/Services/ServiceContext.cs index 6dabf8b0b6..e01471e3a7 100644 --- a/src/Umbraco.Core/Services/ServiceContext.cs +++ b/src/Umbraco.Core/Services/ServiceContext.cs @@ -1,4 +1,6 @@ using System; +using log4net; +using Umbraco.Core.Logging; using System.IO; using Umbraco.Core.IO; using Umbraco.Core.Persistence; @@ -73,7 +75,7 @@ namespace Umbraco.Core.Services ISectionService sectionService, IApplicationTreeService treeService, ITagService tagService, - INotificationService notificationService, + INotificationService notificationService, ILocalizedTextService localizedTextService) { _localizedTextService = new Lazy(() => localizedTextService); @@ -94,22 +96,19 @@ namespace Umbraco.Core.Services _memberService = new Lazy(() => memberService); _userService = new Lazy(() => userService); _notificationService = new Lazy(() => notificationService); - } - /// - /// Constructor used to instantiate the core services - /// - /// - /// - /// - /// - internal ServiceContext(IDatabaseUnitOfWorkProvider dbUnitOfWorkProvider, IUnitOfWorkProvider fileUnitOfWorkProvider, BasePublishingStrategy publishingStrategy, CacheHelper cache) + internal ServiceContext( + RepositoryFactory repositoryFactory, + IDatabaseUnitOfWorkProvider dbUnitOfWorkProvider, + IUnitOfWorkProvider fileUnitOfWorkProvider, + BasePublishingStrategy publishingStrategy, + CacheHelper cache, + ILogger logger) { - BuildServiceCache(dbUnitOfWorkProvider, fileUnitOfWorkProvider, publishingStrategy, cache, - //this needs to be lazy because when we create the service context it's generally before the - //resolvers have been initialized! - new Lazy(() => RepositoryResolver.Current.Factory)); + BuildServiceCache(dbUnitOfWorkProvider, fileUnitOfWorkProvider, publishingStrategy, cache, + repositoryFactory, + logger); } /// @@ -120,76 +119,76 @@ namespace Umbraco.Core.Services IUnitOfWorkProvider fileUnitOfWorkProvider, BasePublishingStrategy publishingStrategy, CacheHelper cache, - Lazy repositoryFactory) + RepositoryFactory repositoryFactory, + ILogger logger) { var provider = dbUnitOfWorkProvider; var fileProvider = fileUnitOfWorkProvider; - - - + if (_localizedTextService == null) _localizedTextService = new Lazy(() => new LocalizedTextService( - new LocalizedTextServiceFileSources(cache.RuntimeCache, new DirectoryInfo(IOHelper.MapPath(SystemDirectories.Umbraco + "/config/lang/"))))); + new LocalizedTextServiceFileSources(cache.RuntimeCache, new DirectoryInfo(IOHelper.MapPath(SystemDirectories.Umbraco + "/config/lang/"))), + logger)); if (_notificationService == null) - _notificationService = new Lazy(() => new NotificationService(provider, _userService.Value, _contentService.Value)); + _notificationService = new Lazy(() => new NotificationService(provider, _userService.Value, _contentService.Value, logger)); if (_serverRegistrationService == null) - _serverRegistrationService = new Lazy(() => new ServerRegistrationService(provider, repositoryFactory.Value)); + _serverRegistrationService = new Lazy(() => new ServerRegistrationService(provider, repositoryFactory)); if (_userService == null) - _userService = new Lazy(() => new UserService(provider, repositoryFactory.Value)); + _userService = new Lazy(() => new UserService(provider, repositoryFactory)); if (_memberService == null) - _memberService = new Lazy(() => new MemberService(provider, repositoryFactory.Value, _memberGroupService.Value, _dataTypeService.Value)); + _memberService = new Lazy(() => new MemberService(provider, repositoryFactory, _memberGroupService.Value, _dataTypeService.Value)); if (_contentService == null) - _contentService = new Lazy(() => new ContentService(provider, repositoryFactory.Value, publishingStrategy, _dataTypeService.Value, _userService.Value)); + _contentService = new Lazy(() => new ContentService(logger, provider, repositoryFactory, publishingStrategy, _dataTypeService.Value, _userService.Value)); if (_mediaService == null) - _mediaService = new Lazy(() => new MediaService(provider, repositoryFactory.Value, _dataTypeService.Value, _userService.Value)); + _mediaService = new Lazy(() => new MediaService(provider, repositoryFactory, _dataTypeService.Value, _userService.Value)); if (_contentTypeService == null) - _contentTypeService = new Lazy(() => new ContentTypeService(provider, repositoryFactory.Value, _contentService.Value, _mediaService.Value)); + _contentTypeService = new Lazy(() => new ContentTypeService(logger, provider, repositoryFactory, _contentService.Value, _mediaService.Value)); if (_dataTypeService == null) - _dataTypeService = new Lazy(() => new DataTypeService(provider, repositoryFactory.Value)); + _dataTypeService = new Lazy(() => new DataTypeService(provider, repositoryFactory)); if (_fileService == null) - _fileService = new Lazy(() => new FileService(fileProvider, provider, repositoryFactory.Value)); + _fileService = new Lazy(() => new FileService(fileProvider, provider, repositoryFactory)); if (_localizationService == null) - _localizationService = new Lazy(() => new LocalizationService(provider, repositoryFactory.Value)); + _localizationService = new Lazy(() => new LocalizationService(provider, repositoryFactory)); if (_packagingService == null) - _packagingService = new Lazy(() => new PackagingService(_contentService.Value, _contentTypeService.Value, _mediaService.Value, _macroService.Value, _dataTypeService.Value, _fileService.Value, _localizationService.Value, _userService.Value, repositoryFactory.Value, provider)); + _packagingService = new Lazy(() => new PackagingService(logger, _contentService.Value, _contentTypeService.Value, _mediaService.Value, _macroService.Value, _dataTypeService.Value, _fileService.Value, _localizationService.Value, _userService.Value, repositoryFactory, provider)); if (_entityService == null) _entityService = new Lazy(() => new EntityService( - provider, repositoryFactory.Value, + provider, repositoryFactory, _contentService.Value, _contentTypeService.Value, _mediaService.Value, _dataTypeService.Value, _memberService.Value, _memberTypeService.Value)); if (_relationService == null) - _relationService = new Lazy(() => new RelationService(provider, repositoryFactory.Value, _entityService.Value)); + _relationService = new Lazy(() => new RelationService(provider, repositoryFactory, _entityService.Value)); if (_treeService == null) - _treeService = new Lazy(() => new ApplicationTreeService(cache)); + _treeService = new Lazy(() => new ApplicationTreeService(logger, cache)); if (_sectionService == null) _sectionService = new Lazy(() => new SectionService(_userService.Value, _treeService.Value, provider, cache)); if (_macroService == null) - _macroService = new Lazy(() => new MacroService(provider, repositoryFactory.Value)); + _macroService = new Lazy(() => new MacroService(provider, repositoryFactory)); if (_memberTypeService == null) - _memberTypeService = new Lazy(() => new MemberTypeService(provider, repositoryFactory.Value, _memberService.Value)); + _memberTypeService = new Lazy(() => new MemberTypeService(provider, repositoryFactory, _memberService.Value)); if (_tagService == null) - _tagService = new Lazy(() => new TagService(provider, repositoryFactory.Value)); + _tagService = new Lazy(() => new TagService(provider, repositoryFactory)); if (_memberGroupService == null) - _memberGroupService = new Lazy(() => new MemberGroupService(provider, repositoryFactory.Value)); - + _memberGroupService = new Lazy(() => new MemberGroupService(provider, repositoryFactory)); + } /// @@ -351,6 +350,6 @@ namespace Umbraco.Core.Services { get { return _memberGroupService.Value; } } - + } } \ No newline at end of file diff --git a/src/Umbraco.Core/Services/TagService.cs b/src/Umbraco.Core/Services/TagService.cs index a1339ce360..2578372dd4 100644 --- a/src/Umbraco.Core/Services/TagService.cs +++ b/src/Umbraco.Core/Services/TagService.cs @@ -1,3 +1,4 @@ +using System; using System.Collections.Generic; using Umbraco.Core.Models; using Umbraco.Core.Persistence; @@ -17,15 +18,18 @@ namespace Umbraco.Core.Services private readonly RepositoryFactory _repositoryFactory; private readonly IDatabaseUnitOfWorkProvider _uowProvider; + [Obsolete("Use the constructors that specify all dependencies instead")] public TagService() : this(new RepositoryFactory()) {} + [Obsolete("Use the constructors that specify all dependencies instead")] public TagService(RepositoryFactory repositoryFactory) : this(new PetaPocoUnitOfWorkProvider(), repositoryFactory) { } + [Obsolete("Use the constructors that specify all dependencies instead")] public TagService(IDatabaseUnitOfWorkProvider provider) : this(provider, new RepositoryFactory()) { diff --git a/src/Umbraco.Core/Standalone/ServiceContextManager.cs b/src/Umbraco.Core/Standalone/ServiceContextManager.cs index 955c7a25df..b036359dc6 100644 --- a/src/Umbraco.Core/Standalone/ServiceContextManager.cs +++ b/src/Umbraco.Core/Standalone/ServiceContextManager.cs @@ -1,8 +1,11 @@ using System; using System.Diagnostics; using Umbraco.Core.Cache; +using Umbraco.Core.Configuration; +using Umbraco.Core.Logging; using Umbraco.Core.Persistence; using Umbraco.Core.Persistence.Mappers; +using Umbraco.Core.Persistence.SqlSyntax; using Umbraco.Core.Persistence.UnitOfWork; using Umbraco.Core.Publishing; using Umbraco.Core.Services; @@ -13,13 +16,17 @@ namespace Umbraco.Core.Standalone { private readonly string _connectionString; private readonly string _providerName; + private readonly ILogger _logger; + private readonly ISqlSyntaxProvider _syntaxProvider; private ServiceContext _serviceContext; private readonly StandaloneCoreApplication _application; - public ServiceContextManager(string connectionString, string providerName, string baseDirectory) + public ServiceContextManager(string connectionString, string providerName, string baseDirectory, ILogger logger, ISqlSyntaxProvider syntaxProvider) { _connectionString = connectionString; _providerName = providerName; + _logger = logger; + _syntaxProvider = syntaxProvider; Trace.WriteLine("ServiceContextManager-Current AppDomain: " + AppDomain.CurrentDomain.FriendlyName); Trace.WriteLine("ServiceContextManager-Current AppDomain: " + AppDomain.CurrentDomain.BaseDirectory); @@ -52,14 +59,16 @@ namespace Umbraco.Core.Standalone //we have no request based cache when running standalone new NullCacheProvider()); - var dbFactory = new DefaultDatabaseFactory(_connectionString, _providerName); - var dbContext = new DatabaseContext(dbFactory); + var dbFactory = new DefaultDatabaseFactory(_connectionString, _providerName, _logger); + var dbContext = new DatabaseContext(dbFactory, _logger, _syntaxProvider, _providerName); Database.Mapper = new PetaPocoMapper(); _serviceContext = new ServiceContext( + new RepositoryFactory(cacheHelper, _logger, dbContext.SqlSyntax, UmbracoConfig.For.UmbracoSettings()), new PetaPocoUnitOfWorkProvider(dbFactory), new FileUnitOfWorkProvider(), new PublishingStrategy(), - cacheHelper); + cacheHelper, + new DebugDiagnosticsLogger()); //initialize the DatabaseContext dbContext.Initialize(_providerName); diff --git a/src/Umbraco.Core/Strategies/RelateOnTrashHandler.cs b/src/Umbraco.Core/Strategies/RelateOnTrashHandler.cs new file mode 100644 index 0000000000..ffe55eadcc --- /dev/null +++ b/src/Umbraco.Core/Strategies/RelateOnTrashHandler.cs @@ -0,0 +1,64 @@ +using System; +using System.Linq; +using Umbraco.Core.Auditing; +using Umbraco.Core.Events; +using Umbraco.Core.Models; +using Umbraco.Core.Services; + +namespace Umbraco.Core.Strategies +{ + public sealed class RelateOnTrashHandler : ApplicationEventHandler + { + protected override void ApplicationStarted(UmbracoApplicationBase umbracoApplication, ApplicationContext applicationContext) + { + ContentService.Moved += ContentService_Moved; + ContentService.Trashed += ContentService_Trashed; + } + + private void ContentService_Moved(IContentService sender, MoveEventArgs e) + { + foreach (var item in e.MoveInfoCollection.Where(x => x.OriginalPath.Contains(Constants.System.RecycleBinContent.ToInvariantString()))) + { + var relationService = ApplicationContext.Current.Services.RelationService; + var relationTypeAlias = Constants.Conventions.RelationTypes.RelateParentDocumentOnDeleteAlias; + var relations = relationService.GetByChildId(item.Entity.Id); + + foreach (var relation in relations.Where(x => x.RelationType.Alias.InvariantEquals(relationTypeAlias))) + { + relationService.Delete(relation); + } + } + } + + private void ContentService_Trashed(IContentService sender, MoveEventArgs e) + { + var relationService = ApplicationContext.Current.Services.RelationService; + var relationTypeAlias = Constants.Conventions.RelationTypes.RelateParentDocumentOnDeleteAlias; + var relationType = relationService.GetRelationTypeByAlias(relationTypeAlias); + + // check that the relation-type exists, if not, then recreate it + if (relationType == null) + { + var documentObjectType = new Guid(Constants.ObjectTypes.Document); + var relationTypeName = Constants.Conventions.RelationTypes.RelateParentDocumentOnDeleteName; + + relationType = new RelationType(documentObjectType, documentObjectType, relationTypeAlias, relationTypeName); + relationService.Save(relationType); + } + + foreach (var item in e.MoveInfoCollection) + { + var originalPath = item.OriginalPath.ToDelimitedList(); + var originalParentId = originalPath.Count > 2 + ? int.Parse(originalPath[originalPath.Count - 2]) + : Constants.System.Root; + + // Add a relation for the item being deleted, so that we can know the original parent for if we need to restore later + var relation = new Relation(originalParentId, item.Entity.Id, relationType); + relationService.Save(relation); + + Audit.Add(AuditTypes.Delete, string.Format("Trashed content with Id: '{0}' related to original parent content with Id: '{1}'", item.Entity.Id, originalParentId), item.Entity.WriterId, item.Entity.Id); + } + } + } +} \ No newline at end of file diff --git a/src/Umbraco.Core/StringExtensions.cs b/src/Umbraco.Core/StringExtensions.cs index fe18f018bb..0aa2028e39 100644 --- a/src/Umbraco.Core/StringExtensions.cs +++ b/src/Umbraco.Core/StringExtensions.cs @@ -374,6 +374,11 @@ namespace Umbraco.Core return input.EndsWith(value.ToString(CultureInfo.InvariantCulture)) ? input : input + value; } + public static string EnsureEndsWith(this string input, string toEndWith) + { + return input.EndsWith(toEndWith.ToString(CultureInfo.InvariantCulture)) ? input : input + toEndWith; + } + public static bool IsLowerCase(this char ch) { return ch.ToString(CultureInfo.InvariantCulture) == ch.ToString(CultureInfo.InvariantCulture).ToLowerInvariant(); diff --git a/src/Umbraco.Core/Strings/Css/StylesheetHelper.cs b/src/Umbraco.Core/Strings/Css/StylesheetHelper.cs new file mode 100644 index 0000000000..ff7591c6b5 --- /dev/null +++ b/src/Umbraco.Core/Strings/Css/StylesheetHelper.cs @@ -0,0 +1,54 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text.RegularExpressions; + +namespace Umbraco.Core.Strings.Css +{ + internal class StylesheetHelper + { + private const string RuleRegexFormat = @"/\*\*\s*umb_name:\s*(?{0}?)\s*\*/\s*(?[^\s,{{]*?)\s*{{\s*(?.*?)\s*}}"; + + public static IEnumerable ParseRules(string input) + { + var rules = new List(); + var ruleRegex = new Regex(string.Format(RuleRegexFormat, @"[^\*\r\n]*"), RegexOptions.IgnoreCase | RegexOptions.Singleline); + + var contents = input; + var ruleMatches = ruleRegex.Matches(contents); + + foreach (Match match in ruleMatches) + { + var name = match.Groups["Name"].Value; + + //If this name already exists, only use the first one + if (rules.Any(x => x.Name == name)) continue; + + rules.Add(new StylesheetRule + { + Name = match.Groups["Name"].Value, + Selector = match.Groups["Selector"].Value, + // Only match first selector when chained together + Styles = string.Join(Environment.NewLine, match.Groups["Styles"].Value.Split(new string[] { "\r\n", "\n" }, StringSplitOptions.None).Select(x => x.Trim()).ToArray()) + }); + } + + return rules; + } + + 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); + contents = ruleRegex.Replace(contents, rule != null ? rule.ToString() : ""); + return contents; + } + + public static string AppendRule(string input, StylesheetRule rule) + { + var contents = input; + contents += Environment.NewLine + Environment.NewLine + rule; + return contents; + } + } +} diff --git a/src/Umbraco.Core/Strings/Css/StylesheetRule.cs b/src/Umbraco.Core/Strings/Css/StylesheetRule.cs new file mode 100644 index 0000000000..4f45525038 --- /dev/null +++ b/src/Umbraco.Core/Strings/Css/StylesheetRule.cs @@ -0,0 +1,30 @@ +using System; +using System.Linq; +using System.Text; + +namespace Umbraco.Core.Strings.Css +{ + internal class StylesheetRule + { + public string Name { get; set; } + + public string Selector { get; set; } + + public string Styles { get; set; } + + public override string ToString() + { + var sb = new StringBuilder(); + sb.Append("/**"); + sb.AppendFormat("umb_name:{0}", Name); + sb.Append("*/"); + sb.Append(Environment.NewLine); + sb.Append(Selector); + sb.Append("{"); + sb.Append(Styles.IsNullOrWhiteSpace() ? "" : Styles.Trim()); + sb.Append("}"); + + return sb.ToString(); + } + } +} \ No newline at end of file diff --git a/src/Umbraco.Core/Strings/UrlSegmentProviderResolver.cs b/src/Umbraco.Core/Strings/UrlSegmentProviderResolver.cs index f545cd8b86..745694e178 100644 --- a/src/Umbraco.Core/Strings/UrlSegmentProviderResolver.cs +++ b/src/Umbraco.Core/Strings/UrlSegmentProviderResolver.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using Umbraco.Core.Logging; using Umbraco.Core.ObjectResolution; namespace Umbraco.Core.Strings @@ -12,19 +13,23 @@ namespace Umbraco.Core.Strings /// /// Initializes a new instance of the class with an initial list of provider types. /// + /// + /// /// The list of provider types. /// The resolver is created by the WebBootManager and thus the constructor remains internal. - internal UrlSegmentProviderResolver(IEnumerable providerTypes) - : base(providerTypes) + internal UrlSegmentProviderResolver(IServiceProvider serviceProvider, ILogger logger, IEnumerable providerTypes) + : base(serviceProvider, logger, providerTypes) { } /// /// Initializes a new instance of the class with an initial list of provider types. /// + /// + /// /// The list of provider types. /// The resolver is created by the WebBootManager and thus the constructor remains internal. - internal UrlSegmentProviderResolver(params Type[] providerTypes) - : base(providerTypes) + internal UrlSegmentProviderResolver(IServiceProvider serviceProvider, ILogger logger, params Type[] providerTypes) + : base(serviceProvider, logger, providerTypes) { } /// diff --git a/src/Umbraco.Core/Umbraco.Core.csproj b/src/Umbraco.Core/Umbraco.Core.csproj index e1eff16813..7b26dc141d 100644 --- a/src/Umbraco.Core/Umbraco.Core.csproj +++ b/src/Umbraco.Core/Umbraco.Core.csproj @@ -133,6 +133,7 @@ Properties\SolutionInfo.cs + @@ -296,12 +297,24 @@ + + + + + + + + + + + + @@ -376,6 +389,8 @@ + + @@ -403,9 +418,6 @@ - - - @@ -429,14 +441,7 @@ - - - - - - - - + @@ -517,10 +522,6 @@ - - - - @@ -595,7 +596,6 @@ - @@ -826,7 +826,6 @@ - @@ -836,7 +835,7 @@ - + @@ -1053,6 +1052,7 @@ + @@ -1069,9 +1069,12 @@ + + + diff --git a/src/Umbraco.Core/UmbracoApplicationBase.cs b/src/Umbraco.Core/UmbracoApplicationBase.cs index c861eca6cd..bed1149234 100644 --- a/src/Umbraco.Core/UmbracoApplicationBase.cs +++ b/src/Umbraco.Core/UmbracoApplicationBase.cs @@ -1,4 +1,5 @@ using System; +using System.Linq; using System.Web; using System.Web.Hosting; using System.Web.Mvc; @@ -120,8 +121,8 @@ namespace Umbraco.Core { return; } - - LogHelper.Error("An unhandled exception occurred", exc); + + Logger.Error("An unhandled exception occurred", exc); OnApplicationError(sender, e); } @@ -140,12 +141,68 @@ namespace Umbraco.Core { if (SystemUtilities.GetCurrentTrustLevel() == AspNetHostingPermissionLevel.Unrestricted) { - LogHelper.Info("Application shutdown. Reason: " + HostingEnvironment.ShutdownReason); + Logger.Info("Application shutdown. Reason: " + HostingEnvironment.ShutdownReason); } OnApplicationEnd(sender, e); } protected abstract IBootManager GetBootManager(); + protected ILogger Logger + { + get + { + if (LoggerResolver.HasCurrent && LoggerResolver.Current.HasValue) + { + return LoggerResolver.Current.Logger; + } + return new HttpTraceLogger(); + } + } + + private class HttpTraceLogger : ILogger + { + public void Error(Type callingType, string message, Exception exception) + { + if (HttpContext.Current == null) return; + HttpContext.Current.Trace.Warn(callingType.ToString(), message + Environment.NewLine + exception); + } + + public void Warn(Type callingType, string message, params Func[] formatItems) + { + if (HttpContext.Current == null) return; + HttpContext.Current.Trace.Warn(callingType.ToString(), string.Format(message, formatItems.Select(x => x()))); + } + + public void WarnWithException(Type callingType, string message, Exception e, params Func[] formatItems) + { + if (HttpContext.Current == null) return; + HttpContext.Current.Trace.Warn(callingType.ToString(), string.Format(message + Environment.NewLine + e, formatItems.Select(x => x()))); + } + + public void Info(Type callingType, Func generateMessage) + { + if (HttpContext.Current == null) return; + HttpContext.Current.Trace.Write(callingType.ToString(), generateMessage()); + } + + public void Info(Type type, string generateMessageFormat, params Func[] formatItems) + { + if (HttpContext.Current == null) return; + HttpContext.Current.Trace.Write(type.ToString(), string.Format(generateMessageFormat, formatItems.Select(x => x()))); + } + + public void Debug(Type callingType, Func generateMessage) + { + if (HttpContext.Current == null) return; + HttpContext.Current.Trace.Write(callingType.ToString(), generateMessage()); + } + + public void Debug(Type type, string generateMessageFormat, params Func[] formatItems) + { + if (HttpContext.Current == null) return; + HttpContext.Current.Trace.Write(type.ToString(), string.Format(generateMessageFormat, formatItems.Select(x => x()))); + } + } } } diff --git a/src/Umbraco.Tests/BootManagers/CoreBootManagerTests.cs b/src/Umbraco.Tests/BootManagers/CoreBootManagerTests.cs index 6a83caf407..381f3889b5 100644 --- a/src/Umbraco.Tests/BootManagers/CoreBootManagerTests.cs +++ b/src/Umbraco.Tests/BootManagers/CoreBootManagerTests.cs @@ -3,8 +3,11 @@ using System.Collections.Generic; using System.Linq; using System.Text; using System.Web; +using Moq; using NUnit.Framework; using Umbraco.Core; +using Umbraco.Core.Configuration; +using Umbraco.Core.Logging; using Umbraco.Core.ObjectResolution; using Umbraco.Core.Persistence.SqlSyntax; using Umbraco.Tests.TestHelpers; @@ -22,7 +25,7 @@ namespace Umbraco.Tests.BootManagers public override void Initialize() { base.Initialize(); - _testApp = new TestApp(); + _testApp = new TestApp(); } [TearDown] @@ -30,10 +33,7 @@ namespace Umbraco.Tests.BootManagers { base.TearDown(); - _testApp = null; - - //ApplicationEventsResolver.Reset(); - //SqlSyntaxProvidersResolver.Reset(); + _testApp = null; } protected override void FreezeResolution() @@ -65,7 +65,9 @@ namespace Umbraco.Tests.BootManagers protected override void InitializeApplicationEventsResolver() { //create an empty resolver so we can add our own custom ones (don't type find) - ApplicationEventsResolver.Current = new ApplicationEventsResolver(new Type[] + ApplicationEventsResolver.Current = new ApplicationEventsResolver( + new ActivatorServiceProvider(), Mock.Of(), + new Type[] { typeof(LegacyStartupHandler), typeof(TestApplicationEventHandler) @@ -74,17 +76,7 @@ namespace Umbraco.Tests.BootManagers CanResolveBeforeFrozen = true }; } - - protected override void InitializeResolvers() - { - //Do nothing as we don't want to initialize all resolvers in this test - //We only include this resolver to not cause trouble for the database context - SqlSyntaxProvidersResolver.Current = new SqlSyntaxProvidersResolver( - PluginManager.Current.ResolveSqlSyntaxProviders()) - { - CanResolveBeforeFrozen = true - }; - } + } /// diff --git a/src/Umbraco.Tests/DistributedCache/DistributedCacheTests.cs b/src/Umbraco.Tests/DistributedCache/DistributedCacheTests.cs index c714cd0a2e..f3942a1716 100644 --- a/src/Umbraco.Tests/DistributedCache/DistributedCacheTests.cs +++ b/src/Umbraco.Tests/DistributedCache/DistributedCacheTests.cs @@ -1,9 +1,13 @@ using System; using System.Collections.Generic; using System.Linq; +using Moq; using NUnit.Framework; using Umbraco.Core; +using Umbraco.Core.Cache; +using Umbraco.Core.Logging; using Umbraco.Core.ObjectResolution; +using Umbraco.Core.Profiling; using Umbraco.Core.Sync; using umbraco.interfaces; @@ -22,7 +26,8 @@ namespace Umbraco.Tests.DistributedCache new TestServerRegistrar()); ServerMessengerResolver.Current = new ServerMessengerResolver( new TestServerMessenger()); - CacheRefreshersResolver.Current = new CacheRefreshersResolver(() => new[] { typeof(TestCacheRefresher) }); + CacheRefreshersResolver.Current = new CacheRefreshersResolver( + new ActivatorServiceProvider(), Mock.Of(), () => new[] { typeof(TestCacheRefresher) }); Resolution.Freeze(); } diff --git a/src/Umbraco.Tests/LibraryTests.cs b/src/Umbraco.Tests/LibraryTests.cs index 129b520b2f..dca6215d90 100644 --- a/src/Umbraco.Tests/LibraryTests.cs +++ b/src/Umbraco.Tests/LibraryTests.cs @@ -4,6 +4,7 @@ using System.IO; using System.Linq; using System.Text; using NUnit.Framework; +using Umbraco.Core; using Umbraco.Core.Models; using Umbraco.Core.Configuration; using Umbraco.Core.Models.PublishedContent; @@ -27,7 +28,7 @@ namespace Umbraco.Tests public override void Initialize() { // required so we can access property.Value - PropertyValueConvertersResolver.Current = new PropertyValueConvertersResolver(); + PropertyValueConvertersResolver.Current = new PropertyValueConvertersResolver(new ActivatorServiceProvider(), Logger); base.Initialize(); diff --git a/src/Umbraco.Tests/Macros/MacroEngineFactoryTests.cs b/src/Umbraco.Tests/Macros/MacroEngineFactoryTests.cs index 2ab4c9f04e..da91cd13b5 100644 --- a/src/Umbraco.Tests/Macros/MacroEngineFactoryTests.cs +++ b/src/Umbraco.Tests/Macros/MacroEngineFactoryTests.cs @@ -1,11 +1,14 @@ using System; using System.Collections.Generic; using System.Linq; +using Moq; using NUnit.Framework; using umbraco.cms.businesslogic.macro; using Umbraco.Core; +using Umbraco.Core.Cache; +using Umbraco.Core.Logging; +using Umbraco.Core.Profiling; using umbraco.interfaces; -using Umbraco.Tests.TestHelpers; namespace Umbraco.Tests.Macros { @@ -15,16 +18,20 @@ namespace Umbraco.Tests.Macros [SetUp] public void Initialize() { - TestHelper.SetupLog4NetForTests(); + var logger = new ProfilingLogger(Mock.Of(), Mock.Of()); - //this ensures its reset - PluginManager.Current = new PluginManager(false); + //this ensures its reset + PluginManager.Current = new PluginManager(new ActivatorServiceProvider(), new NullCacheProvider(), + logger, + false) + { + AssembliesToScan = new[] + { + this.GetType().Assembly + } + }; //for testing, we'll specify which assemblies are scanned for the PluginTypeResolver - PluginManager.Current.AssembliesToScan = new[] - { - this.GetType().Assembly - }; } [TearDown] diff --git a/src/Umbraco.Tests/Macros/MacroTests.cs b/src/Umbraco.Tests/Macros/MacroTests.cs index b70e5bc114..eca60cfe0a 100644 --- a/src/Umbraco.Tests/Macros/MacroTests.cs +++ b/src/Umbraco.Tests/Macros/MacroTests.cs @@ -3,10 +3,12 @@ using System.IO; using System.Web.Caching; using System.Web.UI; using System.Web.UI.WebControls; +using Moq; using NUnit.Framework; using Umbraco.Core; using Umbraco.Core.Cache; using Umbraco.Core.Models; +using Umbraco.Core.Logging; using Umbraco.Core.Profiling; using umbraco; using umbraco.cms.businesslogic.macro; @@ -28,7 +30,7 @@ namespace Umbraco.Tests.Macros new StaticCacheProvider(), new NullCacheProvider()); ApplicationContext.Current = new ApplicationContext(cacheHelper); - ProfilerResolver.Current = new ProfilerResolver(new LogProfiler()) + ProfilerResolver.Current = new ProfilerResolver(new LogProfiler(Mock.Of())) { CanResolveBeforeFrozen = true }; diff --git a/src/Umbraco.Tests/MediaFactoryTests.cs b/src/Umbraco.Tests/MediaFactoryTests.cs index 1c658f840f..3dc43d3da3 100644 --- a/src/Umbraco.Tests/MediaFactoryTests.cs +++ b/src/Umbraco.Tests/MediaFactoryTests.cs @@ -1,11 +1,14 @@ using System; using System.Collections.Generic; using System.Linq; +using Moq; using NUnit.Framework; using Umbraco.Core; -using Umbraco.Tests.TestHelpers; using umbraco.BusinessLogic; using umbraco.cms.businesslogic.media; +using Umbraco.Core.Cache; +using Umbraco.Core.Logging; +using Umbraco.Core.Profiling; namespace Umbraco.Tests { @@ -15,16 +18,19 @@ namespace Umbraco.Tests [SetUp] public void Initialize() { - TestHelper.SetupLog4NetForTests(); - - //this ensures its reset - PluginManager.Current = new PluginManager(false); + var logger = new ProfilingLogger(Mock.Of(), Mock.Of()); + //this ensures its reset + PluginManager.Current = new PluginManager(new ActivatorServiceProvider(), new NullCacheProvider(), + logger, + false) + { + AssembliesToScan = new[] + { + this.GetType().Assembly + } + }; //for testing, we'll specify which assemblies are scanned for the PluginTypeResolver - PluginManager.Current.AssembliesToScan = new[] - { - this.GetType().Assembly - }; } [TearDown] diff --git a/src/Umbraco.Tests/Migrations/AlterMigrationTests.cs b/src/Umbraco.Tests/Migrations/AlterMigrationTests.cs index 1b18b77e51..94e8802ca4 100644 --- a/src/Umbraco.Tests/Migrations/AlterMigrationTests.cs +++ b/src/Umbraco.Tests/Migrations/AlterMigrationTests.cs @@ -1,6 +1,8 @@ using System; using System.Linq; +using Moq; using NUnit.Framework; +using Umbraco.Core.Logging; using Umbraco.Core.Persistence; using Umbraco.Core.Persistence.Migrations; using Umbraco.Core.Persistence.SqlSyntax; @@ -11,18 +13,13 @@ namespace Umbraco.Tests.Migrations [TestFixture] public class AlterMigrationTests { - [SetUp] - public void SetUp() - { - SqlSyntaxContext.SqlSyntaxProvider = SqlCeSyntax.Provider; - } [Test] public void Drop_Foreign_Key() { // Arrange - var context = new MigrationContext(DatabaseProviders.SqlServerCE, null); - var stub = new DropForeignKeyMigrationStub(); + var context = new MigrationContext(DatabaseProviders.SqlServerCE, null, Mock.Of()); + var stub = new DropForeignKeyMigrationStub(new SqlCeSyntaxProvider(), Mock.Of()); // Act stub.GetUpExpressions(context); @@ -38,8 +35,8 @@ namespace Umbraco.Tests.Migrations public void Can_Get_Up_Migration_From_MigrationStub() { // Arrange - var context = new MigrationContext(DatabaseProviders.SqlServerCE, null); - var stub = new AlterUserTableMigrationStub(); + var context = new MigrationContext(DatabaseProviders.SqlServerCE, null, Mock.Of()); + var stub = new AlterUserTableMigrationStub(new SqlCeSyntaxProvider(), Mock.Of()); // Act stub.GetUpExpressions(context); diff --git a/src/Umbraco.Tests/Migrations/FindingMigrationsTest.cs b/src/Umbraco.Tests/Migrations/FindingMigrationsTest.cs index 5775ad8718..a3e6aca822 100644 --- a/src/Umbraco.Tests/Migrations/FindingMigrationsTest.cs +++ b/src/Umbraco.Tests/Migrations/FindingMigrationsTest.cs @@ -4,12 +4,12 @@ using System.Linq; using Moq; using NUnit.Framework; using Umbraco.Core; +using Umbraco.Core.Logging; using Umbraco.Core.ObjectResolution; using Umbraco.Core.Persistence; using Umbraco.Core.Persistence.Migrations; using Umbraco.Core.Persistence.SqlSyntax; using Umbraco.Tests.Migrations.Stubs; -using Umbraco.Tests.TestHelpers; namespace Umbraco.Tests.Migrations { @@ -19,9 +19,9 @@ namespace Umbraco.Tests.Migrations [SetUp] public void Initialize() { - TestHelper.SetupLog4NetForTests(); - - MigrationResolver.Current = new MigrationResolver(() => new List + MigrationResolver.Current = new MigrationResolver( + new ActivatorServiceProvider(), Mock.Of(), + () => new List { typeof (AlterUserTableMigrationStub), typeof(Dummy), @@ -31,9 +31,16 @@ namespace Umbraco.Tests.Migrations typeof (FiveZeroMigration) }); + //This is needed because the PluginManager is creating the migration instances with their default ctors + LoggerResolver.Current = new LoggerResolver(Mock.Of()) + { + CanResolveBeforeFrozen = true + }; + SqlSyntaxContext.SqlSyntaxProvider = new SqlCeSyntaxProvider(); + Resolution.Freeze(); - SqlSyntaxContext.SqlSyntaxProvider = SqlCeSyntax.Provider; + SqlSyntaxContext.SqlSyntaxProvider = new SqlCeSyntaxProvider(); } [Test] @@ -57,7 +64,7 @@ namespace Umbraco.Tests.Migrations Assert.That(list.Count, Is.EqualTo(3)); - var context = new MigrationContext(DatabaseProviders.SqlServerCE, null); + var context = new MigrationContext(DatabaseProviders.SqlServerCE, null, Mock.Of()); foreach (var migration1 in list) { var migration = (MigrationBase) migration1; @@ -76,6 +83,7 @@ namespace Umbraco.Tests.Migrations [TearDown] public void TearDown() { + LoggerResolver.Reset(); MigrationResolver.Reset(); } } diff --git a/src/Umbraco.Tests/Migrations/MigrationRunnerTests.cs b/src/Umbraco.Tests/Migrations/MigrationRunnerTests.cs index d7aca12bfa..01ddf4a871 100644 --- a/src/Umbraco.Tests/Migrations/MigrationRunnerTests.cs +++ b/src/Umbraco.Tests/Migrations/MigrationRunnerTests.cs @@ -1,10 +1,13 @@ using System; using System.Collections.Generic; using System.Linq; +using Moq; using NUnit.Framework; +using Umbraco.Core.Logging; using Umbraco.Core.Persistence; using Umbraco.Core.Persistence.Migrations; using Umbraco.Core.Persistence.Migrations.Syntax.Alter.Expressions; +using Umbraco.Core.Persistence.SqlSyntax; namespace Umbraco.Tests.Migrations { @@ -14,9 +17,9 @@ namespace Umbraco.Tests.Migrations [Test] public void Executes_Only_One_Migration_For_Spanning_Multiple_Targets() { - var runner = new MigrationRunner(new Version(4, 0, 0), new Version(6, 0, 0), "Test"); + var runner = new MigrationRunner(Mock.Of(), new Version(4, 0, 0), new Version(6, 0, 0), "Test"); - var migrations = runner.OrderedUpgradeMigrations(new List { new MultiMigration() }); + var migrations = runner.OrderedUpgradeMigrations(new List { new MultiMigration(new SqlCeSyntaxProvider(), Mock.Of()) }); var ctx = runner.InitializeMigrations( //new List {new DoRunMigration(), new DoNotRunMigration()}, @@ -30,9 +33,9 @@ namespace Umbraco.Tests.Migrations [Test] public void Executes_Migration_For_Spanning_One_Target_1() { - var runner = new MigrationRunner(new Version(4, 0, 0), new Version(5, 0, 0), "Test"); + var runner = new MigrationRunner(Mock.Of(), new Version(4, 0, 0), new Version(5, 0, 0), "Test"); - var migrations = runner.OrderedUpgradeMigrations(new List { new MultiMigration() }); + var migrations = runner.OrderedUpgradeMigrations(new List { new MultiMigration(new SqlCeSyntaxProvider(), Mock.Of()) }); var ctx = runner.InitializeMigrations( //new List {new DoRunMigration(), new DoNotRunMigration()}, @@ -46,9 +49,9 @@ namespace Umbraco.Tests.Migrations [Test] public void Executes_Migration_For_Spanning_One_Target_2() { - var runner = new MigrationRunner(new Version(5, 0, 1), new Version(6, 0, 0), "Test"); + var runner = new MigrationRunner(Mock.Of(), new Version(5, 0, 1), new Version(6, 0, 0), "Test"); - var migrations = runner.OrderedUpgradeMigrations(new List { new MultiMigration() }); + var migrations = runner.OrderedUpgradeMigrations(new List { new MultiMigration(new SqlCeSyntaxProvider(), Mock.Of()) }); var ctx = runner.InitializeMigrations( //new List {new DoRunMigration(), new DoNotRunMigration()}, @@ -63,14 +66,18 @@ namespace Umbraco.Tests.Migrations [Migration("5.0.0", 1, "Test")] private class MultiMigration : MigrationBase { + public MultiMigration(ISqlSyntaxProvider sqlSyntax, ILogger logger) : base(sqlSyntax, logger) + { + } + public override void Up() { - Context.Expressions.Add(new AlterColumnExpression()); + Context.Expressions.Add(new AlterColumnExpression(SqlSyntax)); } public override void Down() { - Context.Expressions.Add(new AlterColumnExpression()); + Context.Expressions.Add(new AlterColumnExpression(SqlSyntax)); } } } diff --git a/src/Umbraco.Tests/Migrations/Stubs/AlterUserTableMigrationStub.cs b/src/Umbraco.Tests/Migrations/Stubs/AlterUserTableMigrationStub.cs index a9a7385530..b0ff9999a9 100644 --- a/src/Umbraco.Tests/Migrations/Stubs/AlterUserTableMigrationStub.cs +++ b/src/Umbraco.Tests/Migrations/Stubs/AlterUserTableMigrationStub.cs @@ -1,10 +1,21 @@ -using Umbraco.Core.Persistence.Migrations; +using Umbraco.Core.Logging; +using Umbraco.Core.Persistence.Migrations; +using Umbraco.Core.Persistence.SqlSyntax; namespace Umbraco.Tests.Migrations.Stubs { [MigrationAttribute("6.0.0", 0, "Test")] public class AlterUserTableMigrationStub : MigrationBase { + + public AlterUserTableMigrationStub() + { + + } + public AlterUserTableMigrationStub(ISqlSyntaxProvider sqlSyntax, ILogger logger) : base(sqlSyntax, logger) + { + } + public override void Up() { Alter.Table("umbracoUser") @@ -22,6 +33,14 @@ namespace Umbraco.Tests.Migrations.Stubs [MigrationAttribute("1.0.0", 0, "Test")] public class DropForeignKeyMigrationStub : MigrationBase { + public DropForeignKeyMigrationStub() + { + + } + public DropForeignKeyMigrationStub(ISqlSyntaxProvider sqlSyntax, ILogger logger) : base(sqlSyntax, logger) + { + } + public override void Up() { Delete.ForeignKey().FromTable("umbracoUser2app").ForeignColumn("user").ToTable("umbracoUser").PrimaryColumn("id"); diff --git a/src/Umbraco.Tests/Migrations/TargetVersionSixthMigrationsTest.cs b/src/Umbraco.Tests/Migrations/TargetVersionSixthMigrationsTest.cs index 9a9b2922d4..1697110b5d 100644 --- a/src/Umbraco.Tests/Migrations/TargetVersionSixthMigrationsTest.cs +++ b/src/Umbraco.Tests/Migrations/TargetVersionSixthMigrationsTest.cs @@ -3,9 +3,11 @@ using System.Collections.Generic; using System.Data.SqlServerCe; using System.Linq; using System.Text.RegularExpressions; +using Moq; using NUnit.Framework; using SQLCE4Umbraco; using Umbraco.Core; +using Umbraco.Core.Logging; using Umbraco.Core.ObjectResolution; using Umbraco.Core.Persistence; using Umbraco.Core.Persistence.Migrations; @@ -25,13 +27,14 @@ namespace Umbraco.Tests.Migrations [SetUp] public override void Initialize() { - TestHelper.SetupLog4NetForTests(); TestHelper.InitializeContentDirectories(); Path = TestHelper.CurrentAssemblyDirectory; AppDomain.CurrentDomain.SetData("DataDirectory", Path); - MigrationResolver.Current = new MigrationResolver(() => new List + MigrationResolver.Current = new MigrationResolver( + new ActivatorServiceProvider(), ProfilingLogger.Logger, + () => new List { typeof (Core.Persistence.Migrations.Upgrades.TargetVersionFourNineZero.RemoveUmbracoAppConstraints), typeof (DeleteAppTables), @@ -47,9 +50,16 @@ namespace Umbraco.Tests.Migrations typeof (UpdateCmsPropertyTypeGroupTable) }.OrderByDescending(x => x.Name)); + //This is needed because the PluginManager is creating the migration instances with their default ctors + LoggerResolver.Current = new LoggerResolver(Logger) + { + CanResolveBeforeFrozen = true + }; + SqlSyntaxContext.SqlSyntaxProvider = new SqlCeSyntaxProvider(); + Resolution.Freeze(); - SqlSyntaxContext.SqlSyntaxProvider = SqlCeSyntax.Provider; + SqlSyntaxContext.SqlSyntaxProvider = new SqlCeSyntaxProvider(); var engine = new SqlCeEngine("Datasource=|DataDirectory|UmbracoPetaPocoTests.sdf;Flush Interval=1;"); engine.CreateDatabase(); @@ -76,10 +86,10 @@ namespace Umbraco.Tests.Migrations var targetVersion = new Version("6.0.0"); var foundMigrations = MigrationResolver.Current.Migrations; - var migrationRunner = new MigrationRunner(configuredVersion, targetVersion, GlobalSettings.UmbracoMigrationName); + var migrationRunner = new MigrationRunner(Logger, configuredVersion, targetVersion, GlobalSettings.UmbracoMigrationName); var migrations = migrationRunner.OrderedUpgradeMigrations(foundMigrations).ToList(); - var context = new MigrationContext(DatabaseProviders.SqlServerCE, db); + var context = new MigrationContext(DatabaseProviders.SqlServerCE, db, Logger); foreach (MigrationBase migration in migrations) { migration.GetUpExpressions(context); @@ -114,7 +124,7 @@ namespace Umbraco.Tests.Migrations public UmbracoDatabase GetConfiguredDatabase() { - return new UmbracoDatabase("Datasource=|DataDirectory|UmbracoPetaPocoTests.sdf;Flush Interval=1;", "System.Data.SqlServerCe.4.0"); + return new UmbracoDatabase("Datasource=|DataDirectory|UmbracoPetaPocoTests.sdf;Flush Interval=1;", "System.Data.SqlServerCe.4.0", Mock.Of()); } public DatabaseProviders GetDatabaseProvider() diff --git a/src/Umbraco.Tests/Migrations/Upgrades/BaseUpgradeTest.cs b/src/Umbraco.Tests/Migrations/Upgrades/BaseUpgradeTest.cs index b496560287..ea99b01c32 100644 --- a/src/Umbraco.Tests/Migrations/Upgrades/BaseUpgradeTest.cs +++ b/src/Umbraco.Tests/Migrations/Upgrades/BaseUpgradeTest.cs @@ -1,9 +1,11 @@ using System; using System.Collections.Generic; using System.Text.RegularExpressions; +using Moq; using NUnit.Framework; using Umbraco.Core; using Umbraco.Core.Configuration; +using Umbraco.Core.Logging; using Umbraco.Core.ObjectResolution; using Umbraco.Core.Persistence; using Umbraco.Core.Persistence.Migrations; @@ -23,13 +25,14 @@ namespace Umbraco.Tests.Migrations.Upgrades [SetUp] public virtual void Initialize() { - TestHelper.SetupLog4NetForTests(); TestHelper.InitializeContentDirectories(); Path = TestHelper.CurrentAssemblyDirectory; AppDomain.CurrentDomain.SetData("DataDirectory", Path); - MigrationResolver.Current = new MigrationResolver(() => new List + MigrationResolver.Current = new MigrationResolver( + new ActivatorServiceProvider(), Mock.Of(), + () => new List { typeof (Core.Persistence.Migrations.Upgrades.TargetVersionFourNineZero.RemoveUmbracoAppConstraints), typeof (DeleteAppTables), @@ -45,6 +48,11 @@ namespace Umbraco.Tests.Migrations.Upgrades typeof (UpdateCmsPropertyTypeGroupTable) }); + LoggerResolver.Current = new LoggerResolver(Mock.Of()) + { + CanResolveBeforeFrozen = true + }; + Resolution.Freeze(); DatabaseSpecificSetUp(); @@ -73,7 +81,7 @@ namespace Umbraco.Tests.Migrations.Upgrades } //Setup the MigrationRunner - var migrationRunner = new MigrationRunner(configuredVersion, targetVersion, GlobalSettings.UmbracoMigrationName); + var migrationRunner = new MigrationRunner(Mock.Of(), configuredVersion, targetVersion, GlobalSettings.UmbracoMigrationName); bool upgraded = migrationRunner.Execute(db, provider, true); Assert.That(upgraded, Is.True); @@ -93,6 +101,7 @@ namespace Umbraco.Tests.Migrations.Upgrades PluginManager.Current = null; SqlSyntaxContext.SqlSyntaxProvider = null; MigrationResolver.Reset(); + LoggerResolver.Reset(); TestHelper.CleanContentDirectories(); diff --git a/src/Umbraco.Tests/Migrations/Upgrades/MySqlUpgradeTest.cs b/src/Umbraco.Tests/Migrations/Upgrades/MySqlUpgradeTest.cs index b8174b2583..bdcb55a4a7 100644 --- a/src/Umbraco.Tests/Migrations/Upgrades/MySqlUpgradeTest.cs +++ b/src/Umbraco.Tests/Migrations/Upgrades/MySqlUpgradeTest.cs @@ -1,4 +1,6 @@ -using NUnit.Framework; +using Moq; +using NUnit.Framework; +using Umbraco.Core.Logging; using Umbraco.Core.Persistence; using Umbraco.Core.Persistence.SqlSyntax; @@ -19,12 +21,12 @@ namespace Umbraco.Tests.Migrations.Upgrades public override ISqlSyntaxProvider GetSyntaxProvider() { - return MySqlSyntax.Provider; + return new MySqlSyntaxProvider(Mock.Of()); } public override UmbracoDatabase GetConfiguredDatabase() { - return new UmbracoDatabase("Server = 169.254.120.3; Database = upgradetest; Uid = umbraco; Pwd = umbraco", "MySql.Data.MySqlClient"); + return new UmbracoDatabase("Server = 169.254.120.3; Database = upgradetest; Uid = umbraco; Pwd = umbraco", "MySql.Data.MySqlClient", Mock.Of()); } public override DatabaseProviders GetDatabaseProvider() diff --git a/src/Umbraco.Tests/Migrations/Upgrades/SqlCeDataUpgradeTest.cs b/src/Umbraco.Tests/Migrations/Upgrades/SqlCeDataUpgradeTest.cs index f75a215763..a3b0623f34 100644 --- a/src/Umbraco.Tests/Migrations/Upgrades/SqlCeDataUpgradeTest.cs +++ b/src/Umbraco.Tests/Migrations/Upgrades/SqlCeDataUpgradeTest.cs @@ -1,6 +1,8 @@ using System; +using Moq; using NUnit.Framework; using SQLCE4Umbraco; +using Umbraco.Core.Logging; using Umbraco.Core.Persistence; using Umbraco.Core.Persistence.Migrations; using Umbraco.Core.Persistence.SqlSyntax; @@ -24,7 +26,7 @@ namespace Umbraco.Tests.Migrations.Upgrades var fix = new PublishAfterUpgradeToVersionSixth(); //Setup the MigrationRunner - var migrationRunner = new MigrationRunner(configuredVersion, targetVersion, GlobalSettings.UmbracoMigrationName); + var migrationRunner = new MigrationRunner(Mock.Of(), configuredVersion, targetVersion, GlobalSettings.UmbracoMigrationName); bool upgraded = migrationRunner.Execute(db, provider, true); Assert.That(upgraded, Is.True); @@ -52,12 +54,12 @@ namespace Umbraco.Tests.Migrations.Upgrades public override ISqlSyntaxProvider GetSyntaxProvider() { - return SqlCeSyntax.Provider; + return new SqlCeSyntaxProvider(); } public override UmbracoDatabase GetConfiguredDatabase() { - return new UmbracoDatabase("Datasource=|DataDirectory|UmbracoPetaPocoTests.sdf;Flush Interval=1;", "System.Data.SqlServerCe.4.0"); + return new UmbracoDatabase("Datasource=|DataDirectory|UmbracoPetaPocoTests.sdf;Flush Interval=1;", "System.Data.SqlServerCe.4.0", Mock.Of()); } public override DatabaseProviders GetDatabaseProvider() diff --git a/src/Umbraco.Tests/Migrations/Upgrades/SqlCeUpgradeTest.cs b/src/Umbraco.Tests/Migrations/Upgrades/SqlCeUpgradeTest.cs index 238256499c..0f8e0543ad 100644 --- a/src/Umbraco.Tests/Migrations/Upgrades/SqlCeUpgradeTest.cs +++ b/src/Umbraco.Tests/Migrations/Upgrades/SqlCeUpgradeTest.cs @@ -2,8 +2,10 @@ using System.Configuration; using System.Data.SqlServerCe; using System.IO; +using Moq; using NUnit.Framework; using SQLCE4Umbraco; +using Umbraco.Core.Logging; using Umbraco.Core.Persistence; using Umbraco.Core.Persistence.SqlSyntax; using Umbraco.Tests.TestHelpers; @@ -15,6 +17,8 @@ namespace Umbraco.Tests.Migrations.Upgrades { public override void DatabaseSpecificSetUp() { + SqlSyntaxContext.SqlSyntaxProvider = new SqlCeSyntaxProvider(); + string filePath = string.Concat(Path, "\\UmbracoPetaPocoTests.sdf"); if (!File.Exists(filePath)) @@ -58,12 +62,12 @@ namespace Umbraco.Tests.Migrations.Upgrades public override ISqlSyntaxProvider GetSyntaxProvider() { - return SqlCeSyntax.Provider; + return new SqlCeSyntaxProvider(); } public override UmbracoDatabase GetConfiguredDatabase() { - return new UmbracoDatabase("Datasource=|DataDirectory|UmbracoPetaPocoTests.sdf;Flush Interval=1;", "System.Data.SqlServerCe.4.0"); + return new UmbracoDatabase("Datasource=|DataDirectory|UmbracoPetaPocoTests.sdf;Flush Interval=1;", "System.Data.SqlServerCe.4.0", Mock.Of()); } public override DatabaseProviders GetDatabaseProvider() diff --git a/src/Umbraco.Tests/Migrations/Upgrades/SqlServerUpgradeTest.cs b/src/Umbraco.Tests/Migrations/Upgrades/SqlServerUpgradeTest.cs index dd278254c5..8b5fc13114 100644 --- a/src/Umbraco.Tests/Migrations/Upgrades/SqlServerUpgradeTest.cs +++ b/src/Umbraco.Tests/Migrations/Upgrades/SqlServerUpgradeTest.cs @@ -1,4 +1,6 @@ -using NUnit.Framework; +using Moq; +using NUnit.Framework; +using Umbraco.Core.Logging; using Umbraco.Core.Persistence; using Umbraco.Core.Persistence.SqlSyntax; @@ -17,12 +19,12 @@ namespace Umbraco.Tests.Migrations.Upgrades public override ISqlSyntaxProvider GetSyntaxProvider() { - return SqlServerSyntax.Provider; + return new SqlServerSyntaxProvider(); } public override UmbracoDatabase GetConfiguredDatabase() { - return new UmbracoDatabase(@"server=.\SQLEXPRESS;database=EmptyForTest;user id=umbraco;password=umbraco", "System.Data.SqlClient"); + return new UmbracoDatabase(@"server=.\SQLEXPRESS;database=EmptyForTest;user id=umbraco;password=umbraco", "System.Data.SqlClient", 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 c427eec1b2..e735e2330c 100644 --- a/src/Umbraco.Tests/Migrations/Upgrades/ValidateOlderSchemaTest.cs +++ b/src/Umbraco.Tests/Migrations/Upgrades/ValidateOlderSchemaTest.cs @@ -7,6 +7,7 @@ using Moq; using NUnit.Framework; using SQLCE4Umbraco; using Umbraco.Core.Configuration; +using Umbraco.Core.Logging; using Umbraco.Core.ObjectResolution; using Umbraco.Core.Persistence; using Umbraco.Core.Persistence.Migrations.Initial; @@ -26,7 +27,7 @@ namespace Umbraco.Tests.Migrations.Upgrades { // Arrange var db = GetConfiguredDatabase(); - var schema = new DatabaseSchemaCreation(db); + var schema = new DatabaseSchemaCreation(db, Mock.Of(), new SqlCeSyntaxProvider()); //Create db schema and data from old Total.sql file for Sql Ce string statements = GetDatabaseSpecificSqlScript(); @@ -51,7 +52,6 @@ namespace Umbraco.Tests.Migrations.Upgrades [SetUp] public virtual void Initialize() { - TestHelper.SetupLog4NetForTests(); TestHelper.InitializeContentDirectories(); Path = TestHelper.CurrentAssemblyDirectory; @@ -73,7 +73,7 @@ namespace Umbraco.Tests.Migrations.Upgrades var engine = new SqlCeEngine(settings.ConnectionString); engine.CreateDatabase(); - SqlSyntaxContext.SqlSyntaxProvider = SqlCeSyntax.Provider; + SqlSyntaxContext.SqlSyntaxProvider = new SqlCeSyntaxProvider(); } [TearDown] @@ -101,7 +101,7 @@ namespace Umbraco.Tests.Migrations.Upgrades public UmbracoDatabase GetConfiguredDatabase() { - return new UmbracoDatabase("Datasource=|DataDirectory|UmbracoPetaPocoTests.sdf;Flush Interval=1;", "System.Data.SqlServerCe.4.0"); + return new UmbracoDatabase("Datasource=|DataDirectory|UmbracoPetaPocoTests.sdf;Flush Interval=1;", "System.Data.SqlServerCe.4.0", Mock.Of()); } public string GetDatabaseSpecificSqlScript() diff --git a/src/Umbraco.Tests/Migrations/Upgrades/ValidateV7TagsUpgradeTest.cs b/src/Umbraco.Tests/Migrations/Upgrades/ValidateV7TagsUpgradeTest.cs index 880a44c82e..e8fccc48f8 100644 --- a/src/Umbraco.Tests/Migrations/Upgrades/ValidateV7TagsUpgradeTest.cs +++ b/src/Umbraco.Tests/Migrations/Upgrades/ValidateV7TagsUpgradeTest.cs @@ -1,11 +1,15 @@ using System.Collections.Generic; using System.Linq; +using Moq; using NUnit.Framework; using Umbraco.Core; +using Umbraco.Core.Configuration.UmbracoSettings; +using Umbraco.Core.IO; +using Umbraco.Core.Logging; using Umbraco.Core.Models; using Umbraco.Core.Models.Rdbms; using Umbraco.Core.Persistence; -using Umbraco.Core.Persistence.Caching; + using Umbraco.Core.Persistence.Migrations; using Umbraco.Core.Persistence.Migrations.Upgrades.TargetVersionSeven; using Umbraco.Core.Persistence.Repositories; @@ -21,17 +25,17 @@ namespace Umbraco.Tests.Migrations.Upgrades { private ContentRepository CreateRepository(IDatabaseUnitOfWork unitOfWork, out ContentTypeRepository contentTypeRepository) { - var templateRepository = new TemplateRepository(unitOfWork, NullCacheProvider.Current); - var tagRepository = new TagRepository(unitOfWork, NullCacheProvider.Current); - contentTypeRepository = new ContentTypeRepository(unitOfWork, NullCacheProvider.Current, templateRepository); - var repository = new ContentRepository(unitOfWork, NullCacheProvider.Current, contentTypeRepository, templateRepository, tagRepository, CacheHelper.CreateDisabledCacheHelper()); + var templateRepository = new TemplateRepository(unitOfWork, CacheHelper.CreateDisabledCacheHelper(), Mock.Of(), SqlSyntaxProvider, Mock.Of(), Mock.Of(), Mock.Of()); + var tagRepository = new TagRepository(unitOfWork, CacheHelper.CreateDisabledCacheHelper(), Mock.Of(), SqlSyntaxProvider); + contentTypeRepository = new ContentTypeRepository(unitOfWork, CacheHelper.CreateDisabledCacheHelper(), Mock.Of(), SqlSyntaxProvider, templateRepository); + var repository = new ContentRepository(unitOfWork, CacheHelper.CreateDisabledCacheHelper(), Mock.Of(), SqlSyntaxProvider, contentTypeRepository, templateRepository, tagRepository); return repository; } [Test] public void Validate_Data_Upgrade() { - var provider = new PetaPocoUnitOfWorkProvider(); + var provider = new PetaPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); ContentTypeRepository contentTypeRepository; var insertedContent = new List(); @@ -116,7 +120,7 @@ namespace Umbraco.Tests.Migrations.Upgrades var migration = new AlterTagRelationsTable(); - var migrationContext = new MigrationContext(DatabaseProviders.SqlServerCE, DatabaseContext.Database); + var migrationContext = new MigrationContext(DatabaseProviders.SqlServerCE, DatabaseContext.Database, Logger); migration.GetUpExpressions(migrationContext); Assert.AreEqual( diff --git a/src/Umbraco.Tests/Migrations/Upgrades/ValidateV7UpgradeTest.cs b/src/Umbraco.Tests/Migrations/Upgrades/ValidateV7UpgradeTest.cs index b1cfaadee2..973cfdfe70 100644 --- a/src/Umbraco.Tests/Migrations/Upgrades/ValidateV7UpgradeTest.cs +++ b/src/Umbraco.Tests/Migrations/Upgrades/ValidateV7UpgradeTest.cs @@ -1,5 +1,7 @@ using System.Linq; +using Moq; using NUnit.Framework; +using Umbraco.Core.Logging; using Umbraco.Core.Persistence; using Umbraco.Core.Persistence.Migrations; using Umbraco.Core.Persistence.Migrations.Upgrades.TargetVersionSeven; @@ -15,10 +17,8 @@ namespace Umbraco.Tests.Migrations.Upgrades [Test] public void Validate_AddIndexToCmsMacroTable() { - SqlSyntaxContext.SqlSyntaxProvider = new SqlCeSyntaxProvider(); - - var migration = new AddIndexToCmsMacroTable(true); - var migrationContext = new MigrationContext(DatabaseProviders.SqlServerCE, null); + var migration = new AddIndexToCmsMacroTable(true, new SqlCeSyntaxProvider(), Mock.Of()); + var migrationContext = new MigrationContext(DatabaseProviders.SqlServerCE, null, Mock.Of()); migration.GetUpExpressions(migrationContext); Assert.AreEqual(1, migrationContext.Expressions.Count); @@ -31,10 +31,8 @@ namespace Umbraco.Tests.Migrations.Upgrades [Test] public void Validate_AddIndexToCmsMacroPropertyTable() { - SqlSyntaxContext.SqlSyntaxProvider = new SqlCeSyntaxProvider(); - - var migration = new AddIndexToCmsMacroPropertyTable(true); - var migrationContext = new MigrationContext(DatabaseProviders.SqlServerCE, null); + var migration = new AddIndexToCmsMacroPropertyTable(true, new SqlCeSyntaxProvider(), Mock.Of()); + var migrationContext = new MigrationContext(DatabaseProviders.SqlServerCE, null, Mock.Of()); migration.GetUpExpressions(migrationContext); Assert.AreEqual(1, migrationContext.Expressions.Count); diff --git a/src/Umbraco.Tests/MockTests.cs b/src/Umbraco.Tests/MockTests.cs index 95c324fd49..f6e99c9e38 100644 --- a/src/Umbraco.Tests/MockTests.cs +++ b/src/Umbraco.Tests/MockTests.cs @@ -5,8 +5,12 @@ using System.Text; using System.Web; using NUnit.Framework; using Umbraco.Core; +using Umbraco.Core.Configuration.UmbracoSettings; +using Umbraco.Core.Logging; using Umbraco.Core.Persistence; +using Umbraco.Core.Persistence.SqlSyntax; using Umbraco.Core.Persistence.UnitOfWork; +using Umbraco.Core.Profiling; using Umbraco.Core.Services; using Moq; using Umbraco.Web; @@ -35,6 +39,7 @@ namespace Umbraco.Tests new Mock().Object, new Mock().Object, new PackagingService( + new Mock().Object, new Mock().Object, new Mock().Object, new Mock().Object, @@ -43,12 +48,12 @@ namespace Umbraco.Tests new Mock().Object, new Mock().Object, new Mock().Object, - new RepositoryFactory(true), + new RepositoryFactory(CacheHelper.CreateDisabledCacheHelper(), Mock.Of(), Mock.Of(), Mock.Of()), new Mock().Object), new Mock().Object, new RelationService( new Mock().Object, - new RepositoryFactory(true), + new RepositoryFactory(CacheHelper.CreateDisabledCacheHelper(), Mock.Of(), Mock.Of(), Mock.Of()), new Mock().Object), new Mock().Object, new Mock().Object, @@ -65,7 +70,7 @@ namespace Umbraco.Tests [Test] public void Can_Create_Db_Context() { - var dbCtx = new DatabaseContext(new Mock().Object); + var dbCtx = new DatabaseContext(new Mock().Object, Mock.Of(), Mock.Of(), "test"); Assert.Pass(); } @@ -73,8 +78,8 @@ namespace Umbraco.Tests public void Can_Create_App_Context_With_Services() { var appCtx = new ApplicationContext( - new DatabaseContext(new Mock().Object), - new ServiceContext( + new DatabaseContext(new Mock().Object, Mock.Of(), Mock.Of(), "test"), + new ServiceContext( new Mock().Object, new Mock().Object, new Mock().Object, @@ -82,6 +87,7 @@ namespace Umbraco.Tests new Mock().Object, new Mock().Object, new PackagingService( + new Mock().Object, new Mock().Object, new Mock().Object, new Mock().Object, @@ -90,12 +96,12 @@ namespace Umbraco.Tests new Mock().Object, new Mock().Object, new Mock().Object, - new RepositoryFactory(true), + new RepositoryFactory(CacheHelper.CreateDisabledCacheHelper(), Mock.Of(), Mock.Of(), Mock.Of()), new Mock().Object), new Mock().Object, new RelationService( new Mock().Object, - new RepositoryFactory(true), + new RepositoryFactory(CacheHelper.CreateDisabledCacheHelper(), Mock.Of(), Mock.Of(), Mock.Of()), new Mock().Object), new Mock().Object, new Mock().Object, @@ -106,7 +112,8 @@ namespace Umbraco.Tests new Mock().Object, new Mock().Object, Mock.Of()), - CacheHelper.CreateDisabledCacheHelper()); + CacheHelper.CreateDisabledCacheHelper(), + new ProfilingLogger(Mock.Of(), Mock.Of())); Assert.Pass(); } diff --git a/src/Umbraco.Tests/Models/ContentTests.cs b/src/Umbraco.Tests/Models/ContentTests.cs index dfaaae1d27..d8dea6b04d 100644 --- a/src/Umbraco.Tests/Models/ContentTests.cs +++ b/src/Umbraco.Tests/Models/ContentTests.cs @@ -1,15 +1,17 @@ using System; using System.Collections.Generic; +using System.Globalization; using System.IO; using System.Linq; using System.Web; using Moq; using NUnit.Framework; using Umbraco.Core; +using Umbraco.Core.Cache; using Umbraco.Core.Exceptions; using Umbraco.Core.Models; using Umbraco.Core.Models.EntityBase; -using Umbraco.Core.Persistence.Caching; + using Umbraco.Core.Serialization; using Umbraco.Tests.TestHelpers; using Umbraco.Tests.TestHelpers.Entities; @@ -220,14 +222,14 @@ namespace Umbraco.Tests.Models ((IUmbracoEntity)content).AdditionalData.Add("test1", 123); ((IUmbracoEntity)content).AdditionalData.Add("test2", "hello"); - var runtimeCache = new RuntimeCacheProvider(); - runtimeCache.Save(typeof(IContent), content); + var runtimeCache = new ObjectCacheRuntimeCacheProvider(); + runtimeCache.InsertCacheItem(content.Id.ToString(CultureInfo.InvariantCulture), () => content); using (DisposableTimer.DebugDuration("STARTING PERF TEST WITH RUNTIME CACHE")) { for (int j = 0; j < 1000; j++) { - var clone = runtimeCache.GetById(typeof(IContent), content.Id.ToGuid()); + var clone = runtimeCache.GetCacheItem(content.Id.ToString(CultureInfo.InvariantCulture)); } } diff --git a/src/Umbraco.Tests/Models/ContentXmlTest.cs b/src/Umbraco.Tests/Models/ContentXmlTest.cs index ac7bae8ce2..f1a42c20b6 100644 --- a/src/Umbraco.Tests/Models/ContentXmlTest.cs +++ b/src/Umbraco.Tests/Models/ContentXmlTest.cs @@ -21,7 +21,10 @@ namespace Umbraco.Tests.Models protected override void FreezeResolution() { - UrlSegmentProviderResolver.Current = new UrlSegmentProviderResolver(typeof(DefaultUrlSegmentProvider)); + UrlSegmentProviderResolver.Current = new UrlSegmentProviderResolver( + new ActivatorServiceProvider(), + Logger, + typeof(DefaultUrlSegmentProvider)); base.FreezeResolution(); } diff --git a/src/Umbraco.Tests/Models/MediaXmlTest.cs b/src/Umbraco.Tests/Models/MediaXmlTest.cs index 4d25081992..ff7e3cb08f 100644 --- a/src/Umbraco.Tests/Models/MediaXmlTest.cs +++ b/src/Umbraco.Tests/Models/MediaXmlTest.cs @@ -21,7 +21,10 @@ namespace Umbraco.Tests.Models protected override void FreezeResolution() { - UrlSegmentProviderResolver.Current = new UrlSegmentProviderResolver(typeof(DefaultUrlSegmentProvider)); + UrlSegmentProviderResolver.Current = new UrlSegmentProviderResolver( + new ActivatorServiceProvider(), + Logger, + typeof(DefaultUrlSegmentProvider)); base.FreezeResolution(); } diff --git a/src/Umbraco.Tests/Models/StylesheetTests.cs b/src/Umbraco.Tests/Models/StylesheetTests.cs index d45aed9cae..21e339f54b 100644 --- a/src/Umbraco.Tests/Models/StylesheetTests.cs +++ b/src/Umbraco.Tests/Models/StylesheetTests.cs @@ -22,39 +22,50 @@ namespace Umbraco.Tests.Models } [Test] - public void Can_Validate_Stylesheet() + public void Can_Add_Property() { // Arrange - var stylesheet = new Stylesheet("/css/styles.css"); - stylesheet.Content = @"body { color:#000; } .bold {font-weight:bold;}"; + var stylesheet = new Stylesheet("/css/styles.css") {Content = @"body { color:#000; } .bold {font-weight:bold;}"}; + + stylesheet.AddProperty(new StylesheetProperty("Test", "p", "font-weight:bold; font-family:Arial;")); // Assert - Assert.That(stylesheet.IsFileValidCss(), Is.True); - Assert.That(stylesheet.IsValid(), Is.True); + Assert.AreEqual(1, stylesheet.Properties.Count()); + Assert.AreEqual("Test", stylesheet.Properties.Single().Name); + Assert.AreEqual("p", stylesheet.Properties.Single().Alias); + Assert.AreEqual("font-weight:bold; font-family:Arial;", stylesheet.Properties.Single().Value); } [Test] - public void Can_InValidate_Stylesheet() + public void Can_Remove_Property() { // Arrange - var stylesheet = new Stylesheet("/css/styles.css"); - stylesheet.Content = @"body { color:#000; } .bold font-weight:bold;}"; + var stylesheet = new Stylesheet("/css/styles.css") { Content = @"body { color:#000; } /**umb_name:Hello*/p{font-size:2em;} .bold {font-weight:bold;}" }; - // Assert - Assert.That(stylesheet.IsFileValidCss(), Is.False); - Assert.That(stylesheet.IsValid(), Is.True); + + Assert.AreEqual(1, stylesheet.Properties.Count()); + + stylesheet.RemoveProperty("Hello"); + + Assert.AreEqual(0, stylesheet.Properties.Count()); + Assert.AreEqual(@"body { color:#000; } .bold {font-weight:bold;}", stylesheet.Content); } [Test] - public void Can_Validate_Css3_Stylesheet() + public void Can_Update_Property() { // Arrange - var stylesheet = new Stylesheet("/css/styles.css"); - stylesheet.Content = "@media screen and (min-width: 768px) { body {background: red}}"; + var stylesheet = new Stylesheet("/css/styles.css") { Content = @"body { color:#000; } /**umb_name:Hello*/p{font-size:2em;} .bold {font-weight:bold;}" }; - // Assert - Assert.That(stylesheet.IsFileValidCss(), Is.True); - Assert.That(stylesheet.IsValid(), Is.True); + var prop = stylesheet.Properties.Single(); + prop.Alias = "li"; + prop.Value = "font-size:5em;"; + + //re-get + prop = stylesheet.Properties.Single(); + Assert.AreEqual("li", prop.Alias); + Assert.AreEqual("font-size:5em;", prop.Value); + Assert.AreEqual("body { color:#000; } /**umb_name:Hello*/\r\nli{font-size:5em;} .bold {font-weight:bold;}", stylesheet.Content); } [Test] @@ -62,74 +73,20 @@ namespace Umbraco.Tests.Models { // Arrange var stylesheet = new Stylesheet("/css/styles.css"); - stylesheet.Content = @"body { color:#000; } .bold {font-weight:bold;}"; + stylesheet.Content = @"body { color:#000; } .bold {font-weight:bold;} /**umb_name:Hello */ p { font-size: 1em; } /**umb_name:testing123*/ li:first-child {padding:0px;}"; // Act var properties = stylesheet.Properties; - // Assert - Assert.That(properties, Is.Not.Null); - Assert.That(properties.Any(), Is.True); - Assert.That(properties.Count(), Is.EqualTo(2)); + Assert.AreEqual(2, properties.Count()); + Assert.AreEqual("Hello", properties.First().Name); + Assert.AreEqual("font-size: 1em;", properties.First().Value); + Assert.AreEqual("p", properties.First().Alias); + Assert.AreEqual("testing123", properties.Last().Name); + Assert.AreEqual("padding:0px;", properties.Last().Value); + Assert.AreEqual("li:first-child", properties.Last().Alias); } - [Test] - public void Can_Verify_Property_From_Css() - { - // Arrange - var stylesheet = new Stylesheet("/css/styles.css"); - stylesheet.Content = @"body { color:#000;font-weight:normal; } .bold {font-weight:bold;}"; - - // Act - var properties = stylesheet.Properties; - var property = properties.FirstOrDefault(); - - // Assert - Assert.That(property, Is.Not.Null); - Assert.That(property.Alias, Is.EqualTo("body")); - Assert.That(property.Value, Is.EqualTo("color:#000;\r\nfont-weight:normal;\r\n")); - } - - [Test] - public void Can_Verify_Multiple_Properties_From_Css_Selectors() - { - // Arrange - var stylesheet = new Stylesheet("/css/styles.css"); - stylesheet.Content = @".bold, .my-font {font-weight:bold; color:#000; align:left;} - #column-sidebar { - width: auto; - float: none; - }"; - - // Act - var properties = stylesheet.Properties; - var firstProperty = properties.Any(x => x.Alias == "bold"); - var secondProperty = properties.Any(x => x.Alias == "my-font"); - - // Assert - Assert.That(firstProperty, Is.True); - Assert.That(secondProperty, Is.True); - } - - [Test] - public void Can_Verify_Mixed_Css_Css3_Property_From_Css() - { - // Arrange - var stylesheet = new Stylesheet("/css/styles.css"); - stylesheet.Content = @"@media screen and (min-width: 600px) and (min-width: 900px) { - .class { - background: #666; - } - }"; - - // Act - var properties = stylesheet.Properties; - - // Assert - Assert.That(stylesheet.IsFileValidCss(), Is.True); - Assert.That(properties, Is.Not.Null); - Assert.That(properties.Any(), Is.True); - } [Test] public void Can_Serialize_Without_Error() diff --git a/src/Umbraco.Tests/Models/TemplateTests.cs b/src/Umbraco.Tests/Models/TemplateTests.cs index bf63387d61..a6ba4c9eae 100644 --- a/src/Umbraco.Tests/Models/TemplateTests.cs +++ b/src/Umbraco.Tests/Models/TemplateTests.cs @@ -2,26 +2,25 @@ using System; using NUnit.Framework; using Umbraco.Core.Models; using Umbraco.Core.Serialization; +using Umbraco.Tests.TestHelpers; namespace Umbraco.Tests.Models { [TestFixture] - public class TemplateTests + public class TemplateTests : BaseUmbracoConfigurationTest { [Test] public void Can_Deep_Clone() { - var item = new Template("-1,2,3", "Test", "test") + var item = new Template("Test", "test") { Id = 3, CreateDate = DateTime.Now, Key = Guid.NewGuid(), UpdateDate = DateTime.Now, Content = "blah", - CreatorId = 66, - Level = 55, - ParentId = 2, - SortOrder = 99, + Path = "-1,3", + IsMasterTemplate = true, MasterTemplateAlias = "master", MasterTemplateId = new Lazy(() => 88) }; @@ -30,17 +29,15 @@ namespace Umbraco.Tests.Models Assert.AreNotSame(clone, item); Assert.AreEqual(clone, item); + Assert.AreEqual(clone.Path, item.Path); + Assert.AreEqual(clone.IsMasterTemplate, item.IsMasterTemplate); Assert.AreEqual(clone.CreateDate, item.CreateDate); Assert.AreEqual(clone.Alias, item.Alias); - Assert.AreEqual(clone.CreatorId, item.CreatorId); Assert.AreEqual(clone.Id, item.Id); Assert.AreEqual(clone.Key, item.Key); - Assert.AreEqual(clone.Level, item.Level); Assert.AreEqual(clone.MasterTemplateAlias, item.MasterTemplateAlias); Assert.AreEqual(clone.MasterTemplateId.Value, item.MasterTemplateId.Value); Assert.AreEqual(clone.Name, item.Name); - Assert.AreEqual(clone.ParentId, item.ParentId); - Assert.AreEqual(clone.SortOrder, item.SortOrder); Assert.AreEqual(clone.UpdateDate, item.UpdateDate); //This double verifies by reflection @@ -56,17 +53,13 @@ namespace Umbraco.Tests.Models { var ss = new SerializationService(new JsonNetSerializer()); - var item = new Template("-1,2,3", "Test", "test") + var item = new Template("Test", "test") { Id = 3, CreateDate = DateTime.Now, Key = Guid.NewGuid(), UpdateDate = DateTime.Now, Content = "blah", - CreatorId = 66, - Level = 55, - ParentId = 2, - SortOrder = 99, MasterTemplateAlias = "master", MasterTemplateId = new Lazy(() => 88) }; diff --git a/src/Umbraco.Tests/Mvc/SurfaceControllerTests.cs b/src/Umbraco.Tests/Mvc/SurfaceControllerTests.cs index 572ff5aa92..b4fd390ac4 100644 --- a/src/Umbraco.Tests/Mvc/SurfaceControllerTests.cs +++ b/src/Umbraco.Tests/Mvc/SurfaceControllerTests.cs @@ -4,6 +4,7 @@ using System.Web.Mvc; using Moq; using NUnit.Framework; using Umbraco.Core; +using Umbraco.Core.Logging; using Umbraco.Core.Models; using Umbraco.Core.ObjectResolution; using Umbraco.Tests.TestHelpers; @@ -116,7 +117,8 @@ namespace Umbraco.Tests.Mvc public class TestSurfaceController : SurfaceController { - public TestSurfaceController(UmbracoContext umbracoContext) : base(umbracoContext) + public TestSurfaceController(UmbracoContext umbracoContext) + : base(umbracoContext) { } diff --git a/src/Umbraco.Tests/ObjectExtensionsTests.cs b/src/Umbraco.Tests/ObjectExtensionsTests.cs index 4e78b2da1f..c9d90e342b 100644 --- a/src/Umbraco.Tests/ObjectExtensionsTests.cs +++ b/src/Umbraco.Tests/ObjectExtensionsTests.cs @@ -6,7 +6,6 @@ using System.Threading; using System.Web.UI.WebControls; using NUnit.Framework; using Umbraco.Core; -using Umbraco.Tests.TestHelpers; namespace Umbraco.Tests { @@ -16,7 +15,6 @@ namespace Umbraco.Tests [TestFixtureSetUp] public void FixtureSetup() { - TestHelper.SetupLog4NetForTests(); } [Test] diff --git a/src/Umbraco.Tests/Persistence/BaseTableByTableTest.cs b/src/Umbraco.Tests/Persistence/BaseTableByTableTest.cs index d69a49d27f..8fd0c8230a 100644 --- a/src/Umbraco.Tests/Persistence/BaseTableByTableTest.cs +++ b/src/Umbraco.Tests/Persistence/BaseTableByTableTest.cs @@ -1,42 +1,67 @@ using System; +using System.IO; +using Moq; using NUnit.Framework; using Umbraco.Core; using Umbraco.Core.Cache; using Umbraco.Core.Configuration; +using Umbraco.Core.Configuration.UmbracoSettings; +using Umbraco.Core.Logging; using Umbraco.Core.Models.Rdbms; using Umbraco.Core.ObjectResolution; using Umbraco.Core.Persistence; using Umbraco.Core.Persistence.SqlSyntax; using Umbraco.Core.Persistence.UnitOfWork; +using Umbraco.Core.Profiling; using Umbraco.Core.Publishing; using Umbraco.Core.Services; using Umbraco.Tests.TestHelpers; +using GlobalSettings = Umbraco.Core.Configuration.GlobalSettings; namespace Umbraco.Tests.Persistence { [TestFixture] public abstract class BaseTableByTableTest { + private ILogger _logger; + private DatabaseSchemaHelper _schemaHelper; + + public abstract Database Database { get; } + + protected abstract ISqlSyntaxProvider SqlSyntaxProvider { get; } + + protected DatabaseSchemaHelper DatabaseSchemaHelper + { + get { return _schemaHelper ?? (_schemaHelper = new DatabaseSchemaHelper(Database, _logger, SqlSyntaxProvider)); } + } + [SetUp] public virtual void Initialize() { - TestHelper.SetupLog4NetForTests(); + _logger = new Logger(new FileInfo(TestHelper.MapPathForTest("~/unit-test-log4net.config"))); + TestHelper.InitializeContentDirectories(); string path = TestHelper.CurrentAssemblyDirectory; AppDomain.CurrentDomain.SetData("DataDirectory", path); - RepositoryResolver.Current = new RepositoryResolver(new RepositoryFactory(true)); - //disable cache var cacheHelper = CacheHelper.CreateDisabledCacheHelper(); + + var dbContext = new DatabaseContext( + new DefaultDatabaseFactory(GlobalSettings.UmbracoConnectionName, _logger), + _logger, SqlSyntaxProvider, "System.Data.SqlServerCe.4.0"); + + var repositoryFactory = new RepositoryFactory(cacheHelper, _logger, SqlSyntaxProvider, SettingsForTests.GenerateMockSettings()); + ApplicationContext.Current = new ApplicationContext( //assign the db context - new DatabaseContext(new DefaultDatabaseFactory()), + dbContext, //assign the service context - new ServiceContext(new PetaPocoUnitOfWorkProvider(), new FileUnitOfWorkProvider(), new PublishingStrategy(), cacheHelper), - cacheHelper) + new ServiceContext(repositoryFactory, new PetaPocoUnitOfWorkProvider(_logger), new FileUnitOfWorkProvider(), new PublishingStrategy(), cacheHelper, _logger), + cacheHelper, + new ProfilingLogger(new Logger(new FileInfo(TestHelper.MapPathForTest("~/unit-test-log4net.config"))), Mock.Of())) { IsReady = true }; @@ -47,23 +72,23 @@ namespace Umbraco.Tests.Persistence [TearDown] public virtual void TearDown() { - SqlSyntaxContext.SqlSyntaxProvider = null; AppDomain.CurrentDomain.SetData("DataDirectory", null); //reset the app context ApplicationContext.Current = null; - RepositoryResolver.Reset(); + Resolution.Reset(); + //RepositoryResolver.Reset(); } - public abstract Database Database { get; } + [Test] public void Can_Create_umbracoNode_Table() { using (Transaction transaction = Database.GetTransaction()) { - Database.CreateTable(); + DatabaseSchemaHelper.CreateTable(); //transaction.Complete(); } @@ -74,7 +99,7 @@ namespace Umbraco.Tests.Persistence { using (Transaction transaction = Database.GetTransaction()) { - Database.CreateTable(); + DatabaseSchemaHelper.CreateTable(); //transaction.Complete(); } @@ -86,7 +111,7 @@ namespace Umbraco.Tests.Persistence using (Transaction transaction = Database.GetTransaction()) { - Database.CreateTable(); + DatabaseSchemaHelper.CreateTable(); //transaction.Complete(); } @@ -98,8 +123,8 @@ namespace Umbraco.Tests.Persistence using (Transaction transaction = Database.GetTransaction()) { - Database.CreateTable(); - Database.CreateTable(); + DatabaseSchemaHelper.CreateTable(); + DatabaseSchemaHelper.CreateTable(); //transaction.Complete(); } @@ -111,9 +136,9 @@ namespace Umbraco.Tests.Persistence using (Transaction transaction = Database.GetTransaction()) { - Database.CreateTable(); - Database.CreateTable(); - Database.CreateTable(); + DatabaseSchemaHelper.CreateTable(); + DatabaseSchemaHelper.CreateTable(); + DatabaseSchemaHelper.CreateTable(); //transaction.Complete(); } @@ -125,8 +150,8 @@ namespace Umbraco.Tests.Persistence using (Transaction transaction = Database.GetTransaction()) { - Database.CreateTable(); - Database.CreateTable(); + DatabaseSchemaHelper.CreateTable(); + DatabaseSchemaHelper.CreateTable(); //transaction.Complete(); } @@ -138,10 +163,10 @@ namespace Umbraco.Tests.Persistence using (Transaction transaction = Database.GetTransaction()) { - Database.CreateTable(); - Database.CreateTable(); - Database.CreateTable(); - Database.CreateTable(); + DatabaseSchemaHelper.CreateTable(); + DatabaseSchemaHelper.CreateTable(); + DatabaseSchemaHelper.CreateTable(); + DatabaseSchemaHelper.CreateTable(); //transaction.Complete(); } @@ -153,10 +178,10 @@ namespace Umbraco.Tests.Persistence using (Transaction transaction = Database.GetTransaction()) { - Database.CreateTable(); - Database.CreateTable(); - Database.CreateTable(); - Database.CreateTable(); + DatabaseSchemaHelper.CreateTable(); + DatabaseSchemaHelper.CreateTable(); + DatabaseSchemaHelper.CreateTable(); + DatabaseSchemaHelper.CreateTable(); //transaction.Complete(); } @@ -168,8 +193,8 @@ namespace Umbraco.Tests.Persistence using (Transaction transaction = Database.GetTransaction()) { - Database.CreateTable(); - Database.CreateTable(); + DatabaseSchemaHelper.CreateTable(); + DatabaseSchemaHelper.CreateTable(); //transaction.Complete(); } @@ -181,9 +206,9 @@ namespace Umbraco.Tests.Persistence using (Transaction transaction = Database.GetTransaction()) { - Database.CreateTable(); - Database.CreateTable(); - Database.CreateTable(); + DatabaseSchemaHelper.CreateTable(); + DatabaseSchemaHelper.CreateTable(); + DatabaseSchemaHelper.CreateTable(); //transaction.Complete(); } @@ -195,7 +220,7 @@ namespace Umbraco.Tests.Persistence using (Transaction transaction = Database.GetTransaction()) { - Database.CreateTable(); + DatabaseSchemaHelper.CreateTable(); //transaction.Complete(); } @@ -207,8 +232,8 @@ namespace Umbraco.Tests.Persistence using (Transaction transaction = Database.GetTransaction()) { - Database.CreateTable(); - Database.CreateTable(); + DatabaseSchemaHelper.CreateTable(); + DatabaseSchemaHelper.CreateTable(); //transaction.Complete(); } @@ -220,8 +245,8 @@ namespace Umbraco.Tests.Persistence using (Transaction transaction = Database.GetTransaction()) { - Database.CreateTable(); - Database.CreateTable(); + DatabaseSchemaHelper.CreateTable(); + DatabaseSchemaHelper.CreateTable(); //transaction.Complete(); } @@ -233,11 +258,11 @@ namespace Umbraco.Tests.Persistence using (Transaction transaction = Database.GetTransaction()) { - Database.CreateTable(); - Database.CreateTable(); - Database.CreateTable(); - Database.CreateTable(); - Database.CreateTable(); + DatabaseSchemaHelper.CreateTable(); + DatabaseSchemaHelper.CreateTable(); + DatabaseSchemaHelper.CreateTable(); + DatabaseSchemaHelper.CreateTable(); + DatabaseSchemaHelper.CreateTable(); //transaction.Complete(); } @@ -249,10 +274,10 @@ namespace Umbraco.Tests.Persistence using (Transaction transaction = Database.GetTransaction()) { - Database.CreateTable(); - Database.CreateTable(); - Database.CreateTable(); - Database.CreateTable(); + DatabaseSchemaHelper.CreateTable(); + DatabaseSchemaHelper.CreateTable(); + DatabaseSchemaHelper.CreateTable(); + DatabaseSchemaHelper.CreateTable(); //transaction.Complete(); } @@ -264,8 +289,8 @@ namespace Umbraco.Tests.Persistence using (Transaction transaction = Database.GetTransaction()) { - Database.CreateTable(); - Database.CreateTable(); + DatabaseSchemaHelper.CreateTable(); + DatabaseSchemaHelper.CreateTable(); //transaction.Complete(); } @@ -277,7 +302,7 @@ namespace Umbraco.Tests.Persistence using (Transaction transaction = Database.GetTransaction()) { - Database.CreateTable(); + DatabaseSchemaHelper.CreateTable(); //transaction.Complete(); } @@ -289,7 +314,7 @@ namespace Umbraco.Tests.Persistence using (Transaction transaction = Database.GetTransaction()) { - Database.CreateTable(); + DatabaseSchemaHelper.CreateTable(); //transaction.Complete(); } @@ -301,7 +326,7 @@ namespace Umbraco.Tests.Persistence using (Transaction transaction = Database.GetTransaction()) { - Database.CreateTable(); + DatabaseSchemaHelper.CreateTable(); //transaction.Complete(); } @@ -313,10 +338,10 @@ namespace Umbraco.Tests.Persistence using (Transaction transaction = Database.GetTransaction()) { - Database.CreateTable(); - Database.CreateTable(); - Database.CreateTable(); - Database.CreateTable(); + DatabaseSchemaHelper.CreateTable(); + DatabaseSchemaHelper.CreateTable(); + DatabaseSchemaHelper.CreateTable(); + DatabaseSchemaHelper.CreateTable(); //transaction.Complete(); } @@ -328,11 +353,11 @@ namespace Umbraco.Tests.Persistence using (Transaction transaction = Database.GetTransaction()) { - Database.CreateTable(); - Database.CreateTable(); - Database.CreateTable(); - Database.CreateTable(); - Database.CreateTable(); + DatabaseSchemaHelper.CreateTable(); + DatabaseSchemaHelper.CreateTable(); + DatabaseSchemaHelper.CreateTable(); + DatabaseSchemaHelper.CreateTable(); + DatabaseSchemaHelper.CreateTable(); //transaction.Complete(); } @@ -344,9 +369,9 @@ namespace Umbraco.Tests.Persistence using (Transaction transaction = Database.GetTransaction()) { - Database.CreateTable(); - Database.CreateTable(); - Database.CreateTable(); + DatabaseSchemaHelper.CreateTable(); + DatabaseSchemaHelper.CreateTable(); + DatabaseSchemaHelper.CreateTable(); //transaction.Complete(); } @@ -358,11 +383,11 @@ namespace Umbraco.Tests.Persistence using (Transaction transaction = Database.GetTransaction()) { - Database.CreateTable(); - Database.CreateTable(); - Database.CreateTable(); - Database.CreateTable(); - Database.CreateTable(); + DatabaseSchemaHelper.CreateTable(); + DatabaseSchemaHelper.CreateTable(); + DatabaseSchemaHelper.CreateTable(); + DatabaseSchemaHelper.CreateTable(); + DatabaseSchemaHelper.CreateTable(); //transaction.Complete(); } @@ -374,12 +399,12 @@ namespace Umbraco.Tests.Persistence using (Transaction transaction = Database.GetTransaction()) { - Database.CreateTable(); - Database.CreateTable(); - Database.CreateTable(); - Database.CreateTable(); - Database.CreateTable(); - Database.CreateTable(); + DatabaseSchemaHelper.CreateTable(); + DatabaseSchemaHelper.CreateTable(); + DatabaseSchemaHelper.CreateTable(); + DatabaseSchemaHelper.CreateTable(); + DatabaseSchemaHelper.CreateTable(); + DatabaseSchemaHelper.CreateTable(); //transaction.Complete(); } @@ -391,11 +416,11 @@ namespace Umbraco.Tests.Persistence using (Transaction transaction = Database.GetTransaction()) { - Database.CreateTable(); - Database.CreateTable(); - Database.CreateTable(); - Database.CreateTable(); - Database.CreateTable(); + DatabaseSchemaHelper.CreateTable(); + DatabaseSchemaHelper.CreateTable(); + DatabaseSchemaHelper.CreateTable(); + DatabaseSchemaHelper.CreateTable(); + DatabaseSchemaHelper.CreateTable(); //transaction.Complete(); } @@ -407,9 +432,9 @@ namespace Umbraco.Tests.Persistence using (Transaction transaction = Database.GetTransaction()) { - Database.CreateTable(); - Database.CreateTable(); - Database.CreateTable(); + DatabaseSchemaHelper.CreateTable(); + DatabaseSchemaHelper.CreateTable(); + DatabaseSchemaHelper.CreateTable(); //transaction.Complete(); } @@ -421,9 +446,9 @@ namespace Umbraco.Tests.Persistence using (Transaction transaction = Database.GetTransaction()) { - Database.CreateTable(); - Database.CreateTable(); - Database.CreateTable(); + DatabaseSchemaHelper.CreateTable(); + DatabaseSchemaHelper.CreateTable(); + DatabaseSchemaHelper.CreateTable(); //transaction.Complete(); } @@ -435,7 +460,7 @@ namespace Umbraco.Tests.Persistence using (Transaction transaction = Database.GetTransaction()) { - Database.CreateTable(); + DatabaseSchemaHelper.CreateTable(); //transaction.Complete(); } @@ -447,8 +472,8 @@ namespace Umbraco.Tests.Persistence using (Transaction transaction = Database.GetTransaction()) { - Database.CreateTable(); - Database.CreateTable(); + DatabaseSchemaHelper.CreateTable(); + DatabaseSchemaHelper.CreateTable(); //transaction.Complete(); } @@ -460,8 +485,8 @@ namespace Umbraco.Tests.Persistence using (Transaction transaction = Database.GetTransaction()) { - Database.CreateTable(); - Database.CreateTable(); + DatabaseSchemaHelper.CreateTable(); + DatabaseSchemaHelper.CreateTable(); //transaction.Complete(); } @@ -473,7 +498,7 @@ namespace Umbraco.Tests.Persistence using (Transaction transaction = Database.GetTransaction()) { - Database.CreateTable(); + DatabaseSchemaHelper.CreateTable(); //transaction.Complete(); } @@ -485,15 +510,15 @@ namespace Umbraco.Tests.Persistence using (Transaction transaction = Database.GetTransaction()) { - Database.CreateTable(); - Database.CreateTable(); - Database.CreateTable(); - Database.CreateTable(); - Database.CreateTable(); - Database.CreateTable(); - Database.CreateTable(); - Database.CreateTable(); - Database.CreateTable(); + DatabaseSchemaHelper.CreateTable(); + DatabaseSchemaHelper.CreateTable(); + DatabaseSchemaHelper.CreateTable(); + DatabaseSchemaHelper.CreateTable(); + DatabaseSchemaHelper.CreateTable(); + DatabaseSchemaHelper.CreateTable(); + DatabaseSchemaHelper.CreateTable(); + DatabaseSchemaHelper.CreateTable(); + DatabaseSchemaHelper.CreateTable(); //transaction.Complete(); } @@ -505,11 +530,11 @@ namespace Umbraco.Tests.Persistence using (Transaction transaction = Database.GetTransaction()) { - Database.CreateTable(); - Database.CreateTable(); - Database.CreateTable(); - Database.CreateTable(); - Database.CreateTable(); + DatabaseSchemaHelper.CreateTable(); + DatabaseSchemaHelper.CreateTable(); + DatabaseSchemaHelper.CreateTable(); + DatabaseSchemaHelper.CreateTable(); + DatabaseSchemaHelper.CreateTable(); //transaction.Complete(); } @@ -521,7 +546,7 @@ namespace Umbraco.Tests.Persistence using (Transaction transaction = Database.GetTransaction()) { - Database.CreateTable(); + DatabaseSchemaHelper.CreateTable(); //transaction.Complete(); } @@ -533,7 +558,7 @@ namespace Umbraco.Tests.Persistence using (Transaction transaction = Database.GetTransaction()) { - Database.CreateTable(); + DatabaseSchemaHelper.CreateTable(); //transaction.Complete(); } @@ -545,8 +570,8 @@ namespace Umbraco.Tests.Persistence using (Transaction transaction = Database.GetTransaction()) { - Database.CreateTable(); - Database.CreateTable(); + DatabaseSchemaHelper.CreateTable(); + DatabaseSchemaHelper.CreateTable(); //transaction.Complete(); } @@ -558,7 +583,7 @@ namespace Umbraco.Tests.Persistence using (Transaction transaction = Database.GetTransaction()) { - Database.CreateTable(); + DatabaseSchemaHelper.CreateTable(); //transaction.Complete(); } @@ -570,9 +595,9 @@ namespace Umbraco.Tests.Persistence using (Transaction transaction = Database.GetTransaction()) { - Database.CreateTable(); - Database.CreateTable(); - Database.CreateTable(); + DatabaseSchemaHelper.CreateTable(); + DatabaseSchemaHelper.CreateTable(); + DatabaseSchemaHelper.CreateTable(); //transaction.Complete(); } @@ -584,10 +609,10 @@ namespace Umbraco.Tests.Persistence using (Transaction transaction = Database.GetTransaction()) { - Database.CreateTable(); - Database.CreateTable(); - Database.CreateTable(); - Database.CreateTable(); + DatabaseSchemaHelper.CreateTable(); + DatabaseSchemaHelper.CreateTable(); + DatabaseSchemaHelper.CreateTable(); + DatabaseSchemaHelper.CreateTable(); //transaction.Complete(); } @@ -599,10 +624,10 @@ namespace Umbraco.Tests.Persistence using (Transaction transaction = Database.GetTransaction()) { - Database.CreateTable(); - Database.CreateTable(); - Database.CreateTable(); - Database.CreateTable(); + DatabaseSchemaHelper.CreateTable(); + DatabaseSchemaHelper.CreateTable(); + DatabaseSchemaHelper.CreateTable(); + DatabaseSchemaHelper.CreateTable(); //transaction.Complete(); } diff --git a/src/Umbraco.Tests/Persistence/Caching/InMemoryCacheProviderTest.cs b/src/Umbraco.Tests/Persistence/Caching/InMemoryCacheProviderTest.cs deleted file mode 100644 index 775e6ee078..0000000000 --- a/src/Umbraco.Tests/Persistence/Caching/InMemoryCacheProviderTest.cs +++ /dev/null @@ -1,118 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using NUnit.Framework; -using Umbraco.Core; -using Umbraco.Core.Persistence.Caching; -using Umbraco.Tests.TestHelpers.Entities; - -namespace Umbraco.Tests.Persistence.Caching -{ - [TestFixture] - public class InMemoryCacheProviderTest - { - private IRepositoryCacheProvider _registry; - - [SetUp] - public void Initiate_Registry() - { - _registry = InMemoryCacheProvider.Current; - - //Fill the registry with random entities - var entity1 = new MockedEntity { Id = 1, Key = 1.ToGuid(), Alias = "mocked1", Name = "Mocked1", Value = Guid.NewGuid().ToString("n") }; - var entity2 = new MockedEntity { Id = 2, Key = 2.ToGuid(), Alias = "mocked2", Name = "Mocked2", Value = Guid.NewGuid().ToString("n") }; - var entity3 = new MockedEntity { Id = 3, Key = 3.ToGuid(), Alias = "mocked3", Name = "Mocked3", Value = Guid.NewGuid().ToString("n") }; - var entity4 = new MockedEntity { Id = 4, Key = 4.ToGuid(), Alias = "mocked4", Name = "Mocked4", Value = Guid.NewGuid().ToString("n") }; - var entity5 = new MockedEntity { Id = 5, Key = 5.ToGuid(), Alias = "mocked5", Name = "Mocked5", Value = Guid.NewGuid().ToString("n") }; - var entity6 = new MockedEntity { Id = 6, Key = 6.ToGuid(), Alias = "mocked6", Name = "Mocked6", Value = Guid.NewGuid().ToString("n") }; - - _registry.Save(typeof(MockedEntity), entity1); - _registry.Save(typeof(MockedEntity), entity2); - _registry.Save(typeof(MockedEntity), entity3); - _registry.Save(typeof(MockedEntity), entity4); - _registry.Save(typeof(MockedEntity), entity5); - _registry.Save(typeof(MockedEntity), entity6); - } - - [Test] - public void Can_Clear_By_Type() - { - var customObj1 = new CustomMockedEntity { Id = 5, Key = 5.ToGuid(), Alias = "mocked5", Name = "Mocked5", Value = Guid.NewGuid().ToString("n") }; - var customObj2 = new CustomMockedEntity { Id = 6, Key = 6.ToGuid(), Alias = "mocked6", Name = "Mocked6", Value = Guid.NewGuid().ToString("n") }; - - _registry.Save(typeof(CustomMockedEntity), customObj1); - _registry.Save(typeof(CustomMockedEntity), customObj2); - - Assert.AreEqual(2, _registry.GetAllByType(typeof(CustomMockedEntity)).Count()); - - _registry.Clear(typeof(CustomMockedEntity)); - - Assert.AreEqual(0, _registry.GetAllByType(typeof(CustomMockedEntity)).Count()); - } - - [Test] - public void Can_Get_Entity_From_Registry() - { - // Arrange - var mockedEntity = new MockedEntity { Id = 20, Key = 20.ToGuid(), Alias = "getMocked", Name = "GetMocked", Value = "Getting entity by id test" }; - _registry.Save(typeof(MockedEntity), mockedEntity); - - // Act - var entity = _registry.GetById(mockedEntity.GetType(), mockedEntity.Key); - - // Assert - Assert.That(entity, Is.Not.Null); - Assert.That(entity.Id, Is.EqualTo(mockedEntity.Id)); - Assert.That(entity.GetType(), Is.EqualTo(mockedEntity.GetType())); - } - - [Test] - public void Can_Get_Entities_By_Ids_From_Registry() - { - // Arrange - var mockedEntity1 = new MockedEntity { Id = 30, Key = 30.ToGuid(), Alias = "getMocked1", Name = "GetMocked1", Value = "Entity 1 - Getting entity by ids test" }; - var mockedEntity2 = new MockedEntity { Id = 31, Key = 31.ToGuid(), Alias = "getMocked2", Name = "GetMocked2", Value = "Entity 2 - Getting entity by ids test" }; - _registry.Save(typeof(MockedEntity), mockedEntity1); - _registry.Save(typeof(MockedEntity), mockedEntity2); - - // Act - var entities = _registry.GetByIds(typeof(MockedEntity), new List { mockedEntity1.Key, mockedEntity2.Key }).ToList(); - - // Assert - Assert.That(entities, Is.Not.Null); - Assert.That(entities.Count(), Is.EqualTo(2)); - Assert.That(entities.Any(x => x.Id == mockedEntity1.Id), Is.True); - Assert.That(entities.Any(x => x.Id == mockedEntity2.Id), Is.True); - } - - [Test] - public void Can_Get_Entities_By_Type_From_Registry() - { - var entities = _registry.GetAllByType(typeof(MockedEntity)); - - Assert.That(entities, Is.Not.Null); - Assert.That(entities.Any(), Is.True); - Assert.That(entities.Count(), Is.GreaterThanOrEqualTo(6)); - } - - [Test] - public void Can_Delete_Entity_From_Registry() - { - // Arrange - var mockedEntity = new MockedEntity { Id = 40, Key = 40.ToGuid(), Alias = "deleteMocked", Name = "DeleteMocked", Value = "Deleting entity test" }; - _registry.Save(typeof(MockedEntity), mockedEntity); - var entitiesBeforeDeletion = _registry.GetAllByType(typeof(MockedEntity)); - int countBefore = entitiesBeforeDeletion.Count(); - - // Act - var entity = _registry.GetById(mockedEntity.GetType(), mockedEntity.Key); - _registry.Delete(typeof(MockedEntity), entity); - var entitiesAfterDeletion = _registry.GetAllByType(typeof(MockedEntity)); - int countAfter = entitiesAfterDeletion.Count(); - - // Assert - Assert.That(countBefore, Is.GreaterThan(countAfter)); - Assert.That(entitiesAfterDeletion.Count(x => x.Id == mockedEntity.Id), Is.EqualTo(0)); - } - } -} \ No newline at end of file diff --git a/src/Umbraco.Tests/Persistence/Caching/RuntimeCacheProviderTest.cs b/src/Umbraco.Tests/Persistence/Caching/RuntimeCacheProviderTest.cs deleted file mode 100644 index bbf4bc381a..0000000000 --- a/src/Umbraco.Tests/Persistence/Caching/RuntimeCacheProviderTest.cs +++ /dev/null @@ -1,138 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using NUnit.Framework; -using Umbraco.Core; -using Umbraco.Core.Persistence.Caching; -using Umbraco.Tests.TestHelpers.Entities; - -namespace Umbraco.Tests.Persistence.Caching -{ - [TestFixture] - public class RuntimeCacheProviderTest - { - private IRepositoryCacheProvider _registry; - - [SetUp] - public void Initiate_Registry() - { - _registry = RuntimeCacheProvider.Current; - - //Fill the registry with random entities - var entity1 = new MockedEntity { Id = 1, Key = 1.ToGuid(), Alias = "mocked1", Name = "Mocked1", Value = Guid.NewGuid().ToString("n") }; - var entity2 = new MockedEntity { Id = 2, Key = 2.ToGuid(), Alias = "mocked2", Name = "Mocked2", Value = Guid.NewGuid().ToString("n") }; - var entity3 = new MockedEntity { Id = 3, Key = 3.ToGuid(), Alias = "mocked3", Name = "Mocked3", Value = Guid.NewGuid().ToString("n") }; - var entity4 = new MockedEntity { Id = 4, Key = 4.ToGuid(), Alias = "mocked4", Name = "Mocked4", Value = Guid.NewGuid().ToString("n") }; - var entity5 = new MockedEntity { Id = 5, Key = 5.ToGuid(), Alias = "mocked5", Name = "Mocked5", Value = Guid.NewGuid().ToString("n") }; - var entity6 = new MockedEntity { Id = 6, Key = 6.ToGuid(), Alias = "mocked6", Name = "Mocked6", Value = Guid.NewGuid().ToString("n") }; - - _registry.Save(typeof(MockedEntity), entity1); - _registry.Save(typeof(MockedEntity), entity2); - _registry.Save(typeof(MockedEntity), entity3); - _registry.Save(typeof(MockedEntity), entity4); - _registry.Save(typeof(MockedEntity), entity5); - _registry.Save(typeof(MockedEntity), entity6); - } - - [Test] - public void Tracked_Keys_Removed_When_Cache_Removed() - { - _registry = RuntimeCacheProvider.Current; - - //Fill the registry with random entities - var entity1 = new MockedEntity { Id = 1, Key = 1.ToGuid(), Alias = "mocked1", Name = "Mocked1", Value = Guid.NewGuid().ToString("n") }; - var entity2 = new MockedEntity { Id = 2, Key = 2.ToGuid(), Alias = "mocked2", Name = "Mocked2", Value = Guid.NewGuid().ToString("n") }; - var entity3 = new MockedEntity { Id = 3, Key = 3.ToGuid(), Alias = "mocked3", Name = "Mocked3", Value = Guid.NewGuid().ToString("n") }; - - _registry.Save(typeof(MockedEntity), entity1); - _registry.Save(typeof(MockedEntity), entity2); - _registry.Save(typeof(MockedEntity), entity3); - - //now clear the runtime cache internally - ((RuntimeCacheProvider)_registry).ClearDataCache(); - - Assert.AreEqual(0, _registry.GetAllByType(typeof (MockedEntity)).Count()); - } - - [Test] - public void Can_Clear_By_Type() - { - var customObj1 = new CustomMockedEntity { Id = 5, Key = 5.ToGuid(), Alias = "mocked5", Name = "Mocked5", Value = Guid.NewGuid().ToString("n") }; - var customObj2 = new CustomMockedEntity { Id = 6, Key = 6.ToGuid(), Alias = "mocked6", Name = "Mocked6", Value = Guid.NewGuid().ToString("n") }; - - _registry.Save(typeof(CustomMockedEntity), customObj1); - _registry.Save(typeof(CustomMockedEntity), customObj2); - - Assert.AreEqual(2, _registry.GetAllByType(typeof(CustomMockedEntity)).Count()); - - _registry.Clear(typeof(CustomMockedEntity)); - - Assert.AreEqual(0, _registry.GetAllByType(typeof(CustomMockedEntity)).Count()); - } - - [Test] - public void Can_Get_Entity_From_Registry() - { - // Arrange - var mockedEntity = new MockedEntity { Id = 20, Key = 20.ToGuid(), Alias = "getMocked", Name = "GetMocked", Value = "Getting entity by id test" }; - _registry.Save(typeof(MockedEntity), mockedEntity); - - // Act - var entity = _registry.GetById(mockedEntity.GetType(), mockedEntity.Key); - - // Assert - Assert.That(entity, Is.Not.Null); - Assert.That(entity.Id, Is.EqualTo(mockedEntity.Id)); - Assert.That(entity.GetType(), Is.EqualTo(mockedEntity.GetType())); - } - - [Test] - public void Can_Get_Entities_By_Ids_From_Registry() - { - // Arrange - var mockedEntity1 = new MockedEntity { Id = 30, Key = 30.ToGuid(), Alias = "getMocked1", Name = "GetMocked1", Value = "Entity 1 - Getting entity by ids test" }; - var mockedEntity2 = new MockedEntity { Id = 31, Key = 31.ToGuid(), Alias = "getMocked2", Name = "GetMocked2", Value = "Entity 2 - Getting entity by ids test" }; - _registry.Save(typeof(MockedEntity), mockedEntity1); - _registry.Save(typeof(MockedEntity), mockedEntity2); - - // Act - var entities = _registry.GetByIds(typeof(MockedEntity), new List { mockedEntity1.Key, mockedEntity2.Key }).ToList(); - - // Assert - Assert.That(entities, Is.Not.Null); - Assert.That(entities.Count(), Is.EqualTo(2)); - Assert.That(entities.Any(x => x.Id == mockedEntity1.Id), Is.True); - Assert.That(entities.Any(x => x.Id == mockedEntity2.Id), Is.True); - } - - [Test] - public void Can_Get_Entities_By_Type_From_Registry() - { - var entities = _registry.GetAllByType(typeof(MockedEntity)); - - Assert.That(entities, Is.Not.Null); - Assert.That(entities.Any(), Is.True); - Assert.That(entities.Count(), Is.GreaterThanOrEqualTo(6)); - } - - [Test] - public void Can_Delete_Entity_From_Registry() - { - // Arrange - var mockedEntity = new MockedEntity { Id = 40, Key = 40.ToGuid(), Alias = "deleteMocked", Name = "DeleteMocked", Value = "Deleting entity test" }; - _registry.Save(typeof(MockedEntity), mockedEntity); - var entitiesBeforeDeletion = _registry.GetAllByType(typeof(MockedEntity)); - int countBefore = entitiesBeforeDeletion.Count(); - - // Act - var entity = _registry.GetById(mockedEntity.GetType(), mockedEntity.Key); - _registry.Delete(typeof(MockedEntity), entity); - var entitiesAfterDeletion = _registry.GetAllByType(typeof(MockedEntity)); - int countAfter = entitiesAfterDeletion.Count(); - - // Assert - Assert.That(countBefore, Is.GreaterThan(countAfter)); - Assert.That(entitiesAfterDeletion.Count(x => x.Id == mockedEntity.Id), Is.EqualTo(0)); - } - } -} \ No newline at end of file diff --git a/src/Umbraco.Tests/Persistence/DatabaseContextTests.cs b/src/Umbraco.Tests/Persistence/DatabaseContextTests.cs index aab58248ae..a1f6dd3b89 100644 --- a/src/Umbraco.Tests/Persistence/DatabaseContextTests.cs +++ b/src/Umbraco.Tests/Persistence/DatabaseContextTests.cs @@ -2,8 +2,10 @@ using System.Configuration; using System.Data.SqlServerCe; using System.IO; +using Moq; using NUnit.Framework; using Umbraco.Core; +using Umbraco.Core.Logging; using Umbraco.Core.Persistence; using Umbraco.Core.Persistence.SqlSyntax; using Umbraco.Tests.TestHelpers; @@ -19,7 +21,9 @@ namespace Umbraco.Tests.Persistence [SetUp] public void Setup() { - _dbContext = new DatabaseContext(new DefaultDatabaseFactory()); + _dbContext = new DatabaseContext( + 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 ApplicationContext.Current = new ApplicationContext(CacheHelper.CreateDisabledCacheHelper()) @@ -76,17 +80,22 @@ namespace Umbraco.Tests.Persistence var engine = new SqlCeEngine(settings.ConnectionString.Replace("UmbracoPetaPocoTests", "DatabaseContextTests")); engine.CreateDatabase(); + var dbFactory = new DefaultDatabaseFactory(engine.LocalConnectionString, "System.Data.SqlServerCe.4.0", Mock.Of()); //re-map the dbcontext to the new conn string - _dbContext = new DatabaseContext(new DefaultDatabaseFactory(engine.LocalConnectionString, "System.Data.SqlServerCe.4.0")); + _dbContext = new DatabaseContext( + dbFactory, + Mock.Of(), + new SqlCeSyntaxProvider(), + dbFactory.ProviderName); - SqlSyntaxContext.SqlSyntaxProvider = SqlCeSyntax.Provider; + var schemaHelper = new DatabaseSchemaHelper(_dbContext.Database, Mock.Of(), new SqlCeSyntaxProvider()); //Create the umbraco database - _dbContext.Database.CreateDatabaseSchema(false); + schemaHelper.CreateDatabaseSchema(false, new ApplicationContext(CacheHelper.CreateDisabledCacheHelper())); - bool umbracoNodeTable = _dbContext.Database.TableExist("umbracoNode"); - bool umbracoUserTable = _dbContext.Database.TableExist("umbracoUser"); - bool cmsTagsTable = _dbContext.Database.TableExist("cmsTags"); + bool umbracoNodeTable = schemaHelper.TableExist("umbracoNode"); + bool umbracoUserTable = schemaHelper.TableExist("umbracoUser"); + bool cmsTagsTable = schemaHelper.TableExist("cmsTags"); Assert.That(umbracoNodeTable, Is.True); Assert.That(umbracoUserTable, Is.True); diff --git a/src/Umbraco.Tests/Persistence/FaultHandling/ConnectionRetryTest.cs b/src/Umbraco.Tests/Persistence/FaultHandling/ConnectionRetryTest.cs index eb688312be..841db8198c 100644 --- a/src/Umbraco.Tests/Persistence/FaultHandling/ConnectionRetryTest.cs +++ b/src/Umbraco.Tests/Persistence/FaultHandling/ConnectionRetryTest.cs @@ -1,5 +1,7 @@ using System.Data.SqlClient; +using Moq; using NUnit.Framework; +using Umbraco.Core.Logging; using Umbraco.Core.Persistence; namespace Umbraco.Tests.Persistence.FaultHandling @@ -13,7 +15,7 @@ namespace Umbraco.Tests.Persistence.FaultHandling // Arrange const string providerName = "System.Data.SqlClient"; const string connectionString = @"server=.\SQLEXPRESS;database=EmptyForTest;user id=x;password=umbraco"; - var factory = new DefaultDatabaseFactory(connectionString, providerName); + var factory = new DefaultDatabaseFactory(connectionString, providerName, Mock.Of()); var database = factory.CreateDatabase(); //Act @@ -27,7 +29,7 @@ namespace Umbraco.Tests.Persistence.FaultHandling // Arrange const string providerName = "System.Data.SqlClient"; const string connectionString = @"server=.\SQLEXPRESS;database=EmptyForTest;user id=umbraco;password=umbraco"; - var factory = new DefaultDatabaseFactory(connectionString, providerName); + var factory = new DefaultDatabaseFactory(connectionString, providerName, Mock.Of()); var database = factory.CreateDatabase(); //Act diff --git a/src/Umbraco.Tests/Persistence/Mappers/ContentMapperTest.cs b/src/Umbraco.Tests/Persistence/Mappers/ContentMapperTest.cs index 0bb3bf3444..f0822ce4f4 100644 --- a/src/Umbraco.Tests/Persistence/Mappers/ContentMapperTest.cs +++ b/src/Umbraco.Tests/Persistence/Mappers/ContentMapperTest.cs @@ -11,7 +11,7 @@ namespace Umbraco.Tests.Persistence.Mappers public void Can_Map_Id_Property() { // Arrange - SqlSyntaxContext.SqlSyntaxProvider = SqlCeSyntax.Provider; + SqlSyntaxContext.SqlSyntaxProvider = new SqlCeSyntaxProvider(); // Act string column = new ContentMapper().Map("Id"); @@ -24,7 +24,7 @@ namespace Umbraco.Tests.Persistence.Mappers public void Can_Map_Trashed_Property() { // Arrange - SqlSyntaxContext.SqlSyntaxProvider = SqlCeSyntax.Provider; + SqlSyntaxContext.SqlSyntaxProvider = new SqlCeSyntaxProvider(); // Act string column = new ContentMapper().Map("Trashed"); @@ -37,7 +37,7 @@ namespace Umbraco.Tests.Persistence.Mappers public void Can_Map_Published_Property() { // Arrange - SqlSyntaxContext.SqlSyntaxProvider = SqlCeSyntax.Provider; + SqlSyntaxContext.SqlSyntaxProvider = new SqlCeSyntaxProvider(); // Act string column = new ContentMapper().Map("Published"); @@ -50,7 +50,7 @@ namespace Umbraco.Tests.Persistence.Mappers public void Can_Map_Version_Property() { // Arrange - SqlSyntaxContext.SqlSyntaxProvider = SqlCeSyntax.Provider; + SqlSyntaxContext.SqlSyntaxProvider = new SqlCeSyntaxProvider(); // Act string column = new ContentMapper().Map("Version"); diff --git a/src/Umbraco.Tests/Persistence/Mappers/ContentTypeMapperTest.cs b/src/Umbraco.Tests/Persistence/Mappers/ContentTypeMapperTest.cs index b86eec2a95..3f9d4197c6 100644 --- a/src/Umbraco.Tests/Persistence/Mappers/ContentTypeMapperTest.cs +++ b/src/Umbraco.Tests/Persistence/Mappers/ContentTypeMapperTest.cs @@ -11,7 +11,7 @@ namespace Umbraco.Tests.Persistence.Mappers public void Can_Map_Id_Property() { // Arrange - SqlSyntaxContext.SqlSyntaxProvider = SqlCeSyntax.Provider; + SqlSyntaxContext.SqlSyntaxProvider = new SqlCeSyntaxProvider(); // Act string column = new ContentTypeMapper().Map("Id"); @@ -24,7 +24,7 @@ namespace Umbraco.Tests.Persistence.Mappers public void Can_Map_Name_Property() { // Arrange - SqlSyntaxContext.SqlSyntaxProvider = SqlCeSyntax.Provider; + SqlSyntaxContext.SqlSyntaxProvider = new SqlCeSyntaxProvider(); // Act string column = new ContentTypeMapper().Map("Name"); @@ -37,7 +37,7 @@ namespace Umbraco.Tests.Persistence.Mappers public void Can_Map_Thumbnail_Property() { // Arrange - SqlSyntaxContext.SqlSyntaxProvider = SqlCeSyntax.Provider; + SqlSyntaxContext.SqlSyntaxProvider = new SqlCeSyntaxProvider(); // Act string column = new ContentTypeMapper().Map("Thumbnail"); @@ -50,7 +50,7 @@ namespace Umbraco.Tests.Persistence.Mappers public void Can_Map_Description_Property() { // Arrange - SqlSyntaxContext.SqlSyntaxProvider = SqlCeSyntax.Provider; + SqlSyntaxContext.SqlSyntaxProvider = new SqlCeSyntaxProvider(); // Act string column = new ContentTypeMapper().Map("Description"); diff --git a/src/Umbraco.Tests/Persistence/Mappers/DataTypeDefinitionMapperTest.cs b/src/Umbraco.Tests/Persistence/Mappers/DataTypeDefinitionMapperTest.cs index 6832ba310d..d095ace4d9 100644 --- a/src/Umbraco.Tests/Persistence/Mappers/DataTypeDefinitionMapperTest.cs +++ b/src/Umbraco.Tests/Persistence/Mappers/DataTypeDefinitionMapperTest.cs @@ -11,7 +11,7 @@ namespace Umbraco.Tests.Persistence.Mappers public void Can_Map_Id_Property() { // Arrange - SqlSyntaxContext.SqlSyntaxProvider = SqlCeSyntax.Provider; + SqlSyntaxContext.SqlSyntaxProvider = new SqlCeSyntaxProvider(); // Act string column = new DataTypeDefinitionMapper().Map("Id"); @@ -24,7 +24,7 @@ namespace Umbraco.Tests.Persistence.Mappers public void Can_Map_Key_Property() { // Arrange - SqlSyntaxContext.SqlSyntaxProvider = SqlCeSyntax.Provider; + SqlSyntaxContext.SqlSyntaxProvider = new SqlCeSyntaxProvider(); // Act string column = new DataTypeDefinitionMapper().Map("Key"); @@ -37,7 +37,7 @@ namespace Umbraco.Tests.Persistence.Mappers public void Can_Map_DatabaseType_Property() { // Arrange - SqlSyntaxContext.SqlSyntaxProvider = SqlCeSyntax.Provider; + SqlSyntaxContext.SqlSyntaxProvider = new SqlCeSyntaxProvider(); // Act string column = new DataTypeDefinitionMapper().Map("DatabaseType"); @@ -50,7 +50,7 @@ namespace Umbraco.Tests.Persistence.Mappers public void Can_Map_PropertyEditorAlias_Property() { // Arrange - SqlSyntaxContext.SqlSyntaxProvider = SqlCeSyntax.Provider; + SqlSyntaxContext.SqlSyntaxProvider = new SqlCeSyntaxProvider(); // Act string column = new DataTypeDefinitionMapper().Map("PropertyEditorAlias"); diff --git a/src/Umbraco.Tests/Persistence/Mappers/DictionaryMapperTest.cs b/src/Umbraco.Tests/Persistence/Mappers/DictionaryMapperTest.cs index f62957493e..3b62429a68 100644 --- a/src/Umbraco.Tests/Persistence/Mappers/DictionaryMapperTest.cs +++ b/src/Umbraco.Tests/Persistence/Mappers/DictionaryMapperTest.cs @@ -11,7 +11,7 @@ namespace Umbraco.Tests.Persistence.Mappers public void Can_Map_Id_Property() { // Arrange - SqlSyntaxContext.SqlSyntaxProvider = SqlCeSyntax.Provider; + SqlSyntaxContext.SqlSyntaxProvider = new SqlCeSyntaxProvider(); // Act string column = new DictionaryMapper().Map("Id"); @@ -24,7 +24,7 @@ namespace Umbraco.Tests.Persistence.Mappers public void Can_Map_Key_Property() { // Arrange - SqlSyntaxContext.SqlSyntaxProvider = SqlCeSyntax.Provider; + SqlSyntaxContext.SqlSyntaxProvider = new SqlCeSyntaxProvider(); // Act string column = new DictionaryMapper().Map("Key"); @@ -37,7 +37,7 @@ namespace Umbraco.Tests.Persistence.Mappers public void Can_Map_ItemKey_Property() { // Arrange - SqlSyntaxContext.SqlSyntaxProvider = SqlCeSyntax.Provider; + SqlSyntaxContext.SqlSyntaxProvider = new SqlCeSyntaxProvider(); // Act string column = new DictionaryMapper().Map("ItemKey"); diff --git a/src/Umbraco.Tests/Persistence/Mappers/DictionaryTranslationMapperTest.cs b/src/Umbraco.Tests/Persistence/Mappers/DictionaryTranslationMapperTest.cs index 906eef79be..b2f68e7f1f 100644 --- a/src/Umbraco.Tests/Persistence/Mappers/DictionaryTranslationMapperTest.cs +++ b/src/Umbraco.Tests/Persistence/Mappers/DictionaryTranslationMapperTest.cs @@ -11,7 +11,7 @@ namespace Umbraco.Tests.Persistence.Mappers public void Can_Map_Key_Property() { // Arrange - SqlSyntaxContext.SqlSyntaxProvider = SqlCeSyntax.Provider; + SqlSyntaxContext.SqlSyntaxProvider = new SqlCeSyntaxProvider(); // Act string column = new DictionaryTranslationMapper().Map("Key"); @@ -24,7 +24,7 @@ namespace Umbraco.Tests.Persistence.Mappers public void Can_Map_Language_Property() { // Arrange - SqlSyntaxContext.SqlSyntaxProvider = SqlCeSyntax.Provider; + SqlSyntaxContext.SqlSyntaxProvider = new SqlCeSyntaxProvider(); // Act string column = new DictionaryTranslationMapper().Map("Language"); @@ -37,7 +37,7 @@ namespace Umbraco.Tests.Persistence.Mappers public void Can_Map_Value_Property() { // Arrange - SqlSyntaxContext.SqlSyntaxProvider = SqlCeSyntax.Provider; + SqlSyntaxContext.SqlSyntaxProvider = new SqlCeSyntaxProvider(); // Act string column = new DictionaryTranslationMapper().Map("Value"); diff --git a/src/Umbraco.Tests/Persistence/Mappers/LanguageMapperTest.cs b/src/Umbraco.Tests/Persistence/Mappers/LanguageMapperTest.cs index 6fa2df4720..ab1fe89f6c 100644 --- a/src/Umbraco.Tests/Persistence/Mappers/LanguageMapperTest.cs +++ b/src/Umbraco.Tests/Persistence/Mappers/LanguageMapperTest.cs @@ -11,7 +11,7 @@ namespace Umbraco.Tests.Persistence.Mappers public void Can_Map_Id_Property() { // Arrange - SqlSyntaxContext.SqlSyntaxProvider = SqlCeSyntax.Provider; + SqlSyntaxContext.SqlSyntaxProvider = new SqlCeSyntaxProvider(); // Act string column = new LanguageMapper().Map("Id"); @@ -24,7 +24,7 @@ namespace Umbraco.Tests.Persistence.Mappers public void Can_Map_IsoCode_Property() { // Arrange - SqlSyntaxContext.SqlSyntaxProvider = SqlCeSyntax.Provider; + SqlSyntaxContext.SqlSyntaxProvider = new SqlCeSyntaxProvider(); // Act string column = new LanguageMapper().Map("IsoCode"); @@ -37,7 +37,7 @@ namespace Umbraco.Tests.Persistence.Mappers public void Can_Map_CultureName_Property() { // Arrange - SqlSyntaxContext.SqlSyntaxProvider = SqlCeSyntax.Provider; + SqlSyntaxContext.SqlSyntaxProvider = new SqlCeSyntaxProvider(); // Act string column = new LanguageMapper().Map("CultureName"); diff --git a/src/Umbraco.Tests/Persistence/Mappers/MediaMapperTest.cs b/src/Umbraco.Tests/Persistence/Mappers/MediaMapperTest.cs index 485df588ca..cbdce90568 100644 --- a/src/Umbraco.Tests/Persistence/Mappers/MediaMapperTest.cs +++ b/src/Umbraco.Tests/Persistence/Mappers/MediaMapperTest.cs @@ -11,7 +11,7 @@ namespace Umbraco.Tests.Persistence.Mappers public void Can_Map_Id_Property() { // Arrange - SqlSyntaxContext.SqlSyntaxProvider = SqlCeSyntax.Provider; + SqlSyntaxContext.SqlSyntaxProvider = new SqlCeSyntaxProvider(); // Act string column = new MediaMapper().Map("Id"); @@ -24,7 +24,7 @@ namespace Umbraco.Tests.Persistence.Mappers public void Can_Map_Trashed_Property() { // Arrange - SqlSyntaxContext.SqlSyntaxProvider = SqlCeSyntax.Provider; + SqlSyntaxContext.SqlSyntaxProvider = new SqlCeSyntaxProvider(); // Act string column = new MediaMapper().Map("Trashed"); @@ -37,7 +37,7 @@ namespace Umbraco.Tests.Persistence.Mappers public void Can_Map_UpdateDate_Property() { // Arrange - SqlSyntaxContext.SqlSyntaxProvider = SqlCeSyntax.Provider; + SqlSyntaxContext.SqlSyntaxProvider = new SqlCeSyntaxProvider(); // Act string column = new MediaMapper().Map("UpdateDate"); @@ -50,7 +50,7 @@ namespace Umbraco.Tests.Persistence.Mappers public void Can_Map_Version_Property() { // Arrange - SqlSyntaxContext.SqlSyntaxProvider = SqlCeSyntax.Provider; + SqlSyntaxContext.SqlSyntaxProvider = new SqlCeSyntaxProvider(); // Act string column = new MediaMapper().Map("Version"); diff --git a/src/Umbraco.Tests/Persistence/Mappers/PropertyGroupMapperTest.cs b/src/Umbraco.Tests/Persistence/Mappers/PropertyGroupMapperTest.cs index 52f6b0b058..a8101cad79 100644 --- a/src/Umbraco.Tests/Persistence/Mappers/PropertyGroupMapperTest.cs +++ b/src/Umbraco.Tests/Persistence/Mappers/PropertyGroupMapperTest.cs @@ -11,7 +11,7 @@ namespace Umbraco.Tests.Persistence.Mappers public void Can_Map_Id_Property() { // Arrange - SqlSyntaxContext.SqlSyntaxProvider = SqlCeSyntax.Provider; + SqlSyntaxContext.SqlSyntaxProvider = new SqlCeSyntaxProvider(); // Act string column = new PropertyGroupMapper().Map("Id"); @@ -24,7 +24,7 @@ namespace Umbraco.Tests.Persistence.Mappers public void Can_Map_ParentId_Property() { // Arrange - SqlSyntaxContext.SqlSyntaxProvider = SqlCeSyntax.Provider; + SqlSyntaxContext.SqlSyntaxProvider = new SqlCeSyntaxProvider(); // Act string column = new PropertyGroupMapper().Map("ParentId"); @@ -37,7 +37,7 @@ namespace Umbraco.Tests.Persistence.Mappers public void Can_Map_SortOrder_Property() { // Arrange - SqlSyntaxContext.SqlSyntaxProvider = SqlCeSyntax.Provider; + SqlSyntaxContext.SqlSyntaxProvider = new SqlCeSyntaxProvider(); // Act string column = new PropertyGroupMapper().Map("SortOrder"); @@ -50,7 +50,7 @@ namespace Umbraco.Tests.Persistence.Mappers public void Can_Map_Name_Property() { // Arrange - SqlSyntaxContext.SqlSyntaxProvider = SqlCeSyntax.Provider; + SqlSyntaxContext.SqlSyntaxProvider = new SqlCeSyntaxProvider(); // Act string column = new PropertyGroupMapper().Map("Name"); diff --git a/src/Umbraco.Tests/Persistence/Mappers/PropertyTypeMapperTest.cs b/src/Umbraco.Tests/Persistence/Mappers/PropertyTypeMapperTest.cs index b107e0b279..de06be3f4e 100644 --- a/src/Umbraco.Tests/Persistence/Mappers/PropertyTypeMapperTest.cs +++ b/src/Umbraco.Tests/Persistence/Mappers/PropertyTypeMapperTest.cs @@ -11,7 +11,7 @@ namespace Umbraco.Tests.Persistence.Mappers public void Can_Map_Id_Property() { // Arrange - SqlSyntaxContext.SqlSyntaxProvider = SqlCeSyntax.Provider; + SqlSyntaxContext.SqlSyntaxProvider = new SqlCeSyntaxProvider(); // Act string column = new PropertyTypeMapper().Map("Id"); @@ -24,7 +24,7 @@ namespace Umbraco.Tests.Persistence.Mappers public void Can_Map_Alias_Property() { // Arrange - SqlSyntaxContext.SqlSyntaxProvider = SqlCeSyntax.Provider; + SqlSyntaxContext.SqlSyntaxProvider = new SqlCeSyntaxProvider(); // Act string column = new PropertyTypeMapper().Map("Alias"); @@ -37,7 +37,7 @@ namespace Umbraco.Tests.Persistence.Mappers public void Can_Map_DataTypeDefinitionId_Property() { // Arrange - SqlSyntaxContext.SqlSyntaxProvider = SqlCeSyntax.Provider; + SqlSyntaxContext.SqlSyntaxProvider = new SqlCeSyntaxProvider(); // Act string column = new PropertyTypeMapper().Map("DataTypeDefinitionId"); @@ -50,7 +50,7 @@ namespace Umbraco.Tests.Persistence.Mappers public void Can_Map_SortOrder_Property() { // Arrange - SqlSyntaxContext.SqlSyntaxProvider = SqlCeSyntax.Provider; + SqlSyntaxContext.SqlSyntaxProvider = new SqlCeSyntaxProvider(); // Act string column = new PropertyTypeMapper().Map("SortOrder"); @@ -63,7 +63,7 @@ namespace Umbraco.Tests.Persistence.Mappers public void Can_Map_PropertyEditorAlias_Property() { // Arrange - SqlSyntaxContext.SqlSyntaxProvider = SqlCeSyntax.Provider; + SqlSyntaxContext.SqlSyntaxProvider = new SqlCeSyntaxProvider(); // Act string column = new PropertyTypeMapper().Map("PropertyEditorAlias"); @@ -76,7 +76,7 @@ namespace Umbraco.Tests.Persistence.Mappers public void Can_Map_DataTypeDatabaseType_Property() { // Arrange - SqlSyntaxContext.SqlSyntaxProvider = SqlCeSyntax.Provider; + SqlSyntaxContext.SqlSyntaxProvider = new SqlCeSyntaxProvider(); // Act string column = new PropertyTypeMapper().Map("DataTypeDatabaseType"); diff --git a/src/Umbraco.Tests/Persistence/Mappers/RelationMapperTest.cs b/src/Umbraco.Tests/Persistence/Mappers/RelationMapperTest.cs index d7191e0936..9e9e20a19e 100644 --- a/src/Umbraco.Tests/Persistence/Mappers/RelationMapperTest.cs +++ b/src/Umbraco.Tests/Persistence/Mappers/RelationMapperTest.cs @@ -11,7 +11,7 @@ namespace Umbraco.Tests.Persistence.Mappers public void Can_Map_Id_Property() { // Arrange - SqlSyntaxContext.SqlSyntaxProvider = SqlCeSyntax.Provider; + SqlSyntaxContext.SqlSyntaxProvider = new SqlCeSyntaxProvider(); // Act string column = new RelationMapper().Map("Id"); @@ -24,7 +24,7 @@ namespace Umbraco.Tests.Persistence.Mappers public void Can_Map_ChildId_Property() { // Arrange - SqlSyntaxContext.SqlSyntaxProvider = SqlCeSyntax.Provider; + SqlSyntaxContext.SqlSyntaxProvider = new SqlCeSyntaxProvider(); // Act string column = new RelationMapper().Map("ChildId"); @@ -37,7 +37,7 @@ namespace Umbraco.Tests.Persistence.Mappers public void Can_Map_Datetime_Property() { // Arrange - SqlSyntaxContext.SqlSyntaxProvider = SqlCeSyntax.Provider; + SqlSyntaxContext.SqlSyntaxProvider = new SqlCeSyntaxProvider(); // Act string column = new RelationMapper().Map("CreateDate"); @@ -50,7 +50,7 @@ namespace Umbraco.Tests.Persistence.Mappers public void Can_Map_Comment_Property() { // Arrange - SqlSyntaxContext.SqlSyntaxProvider = SqlCeSyntax.Provider; + SqlSyntaxContext.SqlSyntaxProvider = new SqlCeSyntaxProvider(); // Act string column = new RelationMapper().Map("Comment"); @@ -63,7 +63,7 @@ namespace Umbraco.Tests.Persistence.Mappers public void Can_Map_RelationType_Property() { // Arrange - SqlSyntaxContext.SqlSyntaxProvider = SqlCeSyntax.Provider; + SqlSyntaxContext.SqlSyntaxProvider = new SqlCeSyntaxProvider(); // Act string column = new RelationMapper().Map("RelationTypeId"); diff --git a/src/Umbraco.Tests/Persistence/Mappers/RelationTypeMapperTest.cs b/src/Umbraco.Tests/Persistence/Mappers/RelationTypeMapperTest.cs index 9860cfeb0f..b023825203 100644 --- a/src/Umbraco.Tests/Persistence/Mappers/RelationTypeMapperTest.cs +++ b/src/Umbraco.Tests/Persistence/Mappers/RelationTypeMapperTest.cs @@ -11,7 +11,7 @@ namespace Umbraco.Tests.Persistence.Mappers public void Can_Map_Id_Property() { // Arrange - SqlSyntaxContext.SqlSyntaxProvider = SqlCeSyntax.Provider; + SqlSyntaxContext.SqlSyntaxProvider = new SqlCeSyntaxProvider(); // Act string column = new RelationTypeMapper().Map("Id"); @@ -24,7 +24,7 @@ namespace Umbraco.Tests.Persistence.Mappers public void Can_Map_Alias_Property() { // Arrange - SqlSyntaxContext.SqlSyntaxProvider = SqlCeSyntax.Provider; + SqlSyntaxContext.SqlSyntaxProvider = new SqlCeSyntaxProvider(); // Act string column = new RelationTypeMapper().Map("Alias"); @@ -37,7 +37,7 @@ namespace Umbraco.Tests.Persistence.Mappers public void Can_Map_ChildObjectType_Property() { // Arrange - SqlSyntaxContext.SqlSyntaxProvider = SqlCeSyntax.Provider; + SqlSyntaxContext.SqlSyntaxProvider = new SqlCeSyntaxProvider(); // Act string column = new RelationTypeMapper().Map("ChildObjectType"); @@ -50,7 +50,7 @@ namespace Umbraco.Tests.Persistence.Mappers public void Can_Map_IsBidirectional_Property() { // Arrange - SqlSyntaxContext.SqlSyntaxProvider = SqlCeSyntax.Provider; + SqlSyntaxContext.SqlSyntaxProvider = new SqlCeSyntaxProvider(); // Act string column = new RelationTypeMapper().Map("IsBidirectional"); diff --git a/src/Umbraco.Tests/Persistence/MySqlDatabaseCreationTest.cs b/src/Umbraco.Tests/Persistence/MySqlDatabaseCreationTest.cs index 0895d1722b..be290795cb 100644 --- a/src/Umbraco.Tests/Persistence/MySqlDatabaseCreationTest.cs +++ b/src/Umbraco.Tests/Persistence/MySqlDatabaseCreationTest.cs @@ -1,4 +1,6 @@ -using NUnit.Framework; +using Moq; +using NUnit.Framework; +using Umbraco.Core.Logging; using Umbraco.Core.Persistence; using Umbraco.Core.Persistence.SqlSyntax; using Umbraco.Tests.TestHelpers; @@ -22,7 +24,7 @@ namespace Umbraco.Tests.Persistence public override ISqlSyntaxProvider SyntaxProvider { - get { return MySqlSyntax.Provider; } + get { return new MySqlSyntaxProvider(Mock.Of()); } } #endregion diff --git a/src/Umbraco.Tests/Persistence/MySqlTableByTableTest.cs b/src/Umbraco.Tests/Persistence/MySqlTableByTableTest.cs index 48103cf7b6..17d12de478 100644 --- a/src/Umbraco.Tests/Persistence/MySqlTableByTableTest.cs +++ b/src/Umbraco.Tests/Persistence/MySqlTableByTableTest.cs @@ -1,7 +1,9 @@ using System; +using Moq; using NUnit.Framework; using Umbraco.Core; using Umbraco.Core.Configuration; +using Umbraco.Core.Logging; using Umbraco.Core.ObjectResolution; using Umbraco.Core.Persistence; using Umbraco.Core.Persistence.SqlSyntax; @@ -19,13 +21,16 @@ namespace Umbraco.Tests.Persistence #region Overrides of BaseTableByTableTest + protected override ISqlSyntaxProvider SqlSyntaxProvider + { + get { return new MySqlSyntaxProvider(Mock.Of()); } + } + [SetUp] public override void Initialize() { base.Initialize(); - SqlSyntaxContext.SqlSyntaxProvider = MySqlSyntax.Provider; - _database = new Database("Server = 169.254.120.3; Database = testdb; Uid = umbraco; Pwd = umbraco", "MySql.Data.MySqlClient"); } diff --git a/src/Umbraco.Tests/Persistence/PetaPocoExtensionsTest.cs b/src/Umbraco.Tests/Persistence/PetaPocoExtensionsTest.cs index 9d17fc17f6..9a5b994522 100644 --- a/src/Umbraco.Tests/Persistence/PetaPocoExtensionsTest.cs +++ b/src/Umbraco.Tests/Persistence/PetaPocoExtensionsTest.cs @@ -232,7 +232,7 @@ namespace Umbraco.Tests.Persistence } // Act - using (DisposableTimer.TraceDuration("starting insert", "finished insert")) + using (ProfilingLogger.TraceDuration("starting insert", "finished insert")) { db.BulkInsertRecords(servers); } diff --git a/src/Umbraco.Tests/Persistence/Querying/ContentTypeSqlMappingTests.cs b/src/Umbraco.Tests/Persistence/Querying/ContentTypeSqlMappingTests.cs index f8493cdea9..c8b4a54b96 100644 --- a/src/Umbraco.Tests/Persistence/Querying/ContentTypeSqlMappingTests.cs +++ b/src/Umbraco.Tests/Persistence/Querying/ContentTypeSqlMappingTests.cs @@ -33,8 +33,8 @@ namespace Umbraco.Tests.Persistence.Querying DatabaseContext.Database.Execute(new Sql(string.Format("SET IDENTITY_INSERT {0} OFF ", SqlSyntaxContext.SqlSyntaxProvider.GetQuotedTableName("umbracoNode")))); DatabaseContext.Database.Execute(new Sql(string.Format("SET IDENTITY_INSERT {0} ON ", SqlSyntaxContext.SqlSyntaxProvider.GetQuotedTableName("cmsTemplate")))); - DatabaseContext.Database.Insert("cmsTemplate", "pk", false, new TemplateDto { NodeId = 55554, Alias = "testTemplate1", Design = "", Master = null, PrimaryKey = 22221}); - DatabaseContext.Database.Insert("cmsTemplate", "pk", false, new TemplateDto { NodeId = 55555, Alias = "testTemplate2", Design = "", Master = null, PrimaryKey = 22222 }); + DatabaseContext.Database.Insert("cmsTemplate", "pk", false, new TemplateDto { NodeId = 55554, Alias = "testTemplate1", Design = "", PrimaryKey = 22221}); + DatabaseContext.Database.Insert("cmsTemplate", "pk", false, new TemplateDto { NodeId = 55555, Alias = "testTemplate2", Design = "", PrimaryKey = 22222 }); DatabaseContext.Database.Execute(new Sql(string.Format("SET IDENTITY_INSERT {0} OFF ", SqlSyntaxContext.SqlSyntaxProvider.GetQuotedTableName("cmsTemplate")))); DatabaseContext.Database.Execute(new Sql(string.Format("SET IDENTITY_INSERT {0} ON ", SqlSyntaxContext.SqlSyntaxProvider.GetQuotedTableName("cmsContentType")))); @@ -58,7 +58,7 @@ namespace Umbraco.Tests.Persistence.Querying IDictionary> allAssociatedTemplates; IDictionary> allParentContentTypeIds; var contentTypes = ContentTypeRepository.ContentTypeQueryMapper.MapContentTypes( - new[] {99997, 99998}, DatabaseContext.Database, out allAssociatedTemplates, out allParentContentTypeIds) + new[] {99997, 99998}, DatabaseContext.Database, SqlSyntaxProvider, out allAssociatedTemplates, out allParentContentTypeIds) .ToArray(); var contentType1 = contentTypes.SingleOrDefault(x => x.Id == 99997); @@ -111,7 +111,7 @@ namespace Umbraco.Tests.Persistence.Querying IDictionary> allParentContentTypeIds; var contentTypes = ContentTypeRepository.ContentTypeQueryMapper.MapMediaTypes( - new[] { 99997, 99998 }, DatabaseContext.Database, out allParentContentTypeIds) + new[] { 99997, 99998 }, DatabaseContext.Database, SqlSyntaxProvider, out allParentContentTypeIds) .ToArray(); var contentType1 = contentTypes.SingleOrDefault(x => x.Id == 99997); @@ -172,7 +172,7 @@ namespace Umbraco.Tests.Persistence.Querying IDictionary allPropTypeCollection; IDictionary allPropGroupCollection; - ContentTypeRepository.ContentTypeQueryMapper.MapGroupsAndProperties(new[] { 99999 }, DatabaseContext.Database, out allPropTypeCollection, out allPropGroupCollection); + ContentTypeRepository.ContentTypeQueryMapper.MapGroupsAndProperties(new[] { 99999 }, DatabaseContext.Database, SqlSyntaxProvider, out allPropTypeCollection, out allPropGroupCollection); var propGroupCollection = allPropGroupCollection[99999]; var propTypeCollection = allPropTypeCollection[99999]; diff --git a/src/Umbraco.Tests/Persistence/Querying/ExpressionTests.cs b/src/Umbraco.Tests/Persistence/Querying/ExpressionTests.cs index 4a2e3f74dc..3aa48e0e8e 100644 --- a/src/Umbraco.Tests/Persistence/Querying/ExpressionTests.cs +++ b/src/Umbraco.Tests/Persistence/Querying/ExpressionTests.cs @@ -1,6 +1,8 @@ using System; using System.Linq.Expressions; +using Moq; using NUnit.Framework; +using Umbraco.Core.Logging; using Umbraco.Core.Models; using Umbraco.Core.Models.Membership; using Umbraco.Core.Models.Rdbms; @@ -85,7 +87,7 @@ namespace Umbraco.Tests.Persistence.Querying public void Model_Expression_Value_Does_Not_Get_Double_Escaped() { //mysql escapes backslashes, so we'll test with that - SqlSyntaxContext.SqlSyntaxProvider = MySqlSyntax.Provider; + SqlSyntaxContext.SqlSyntaxProvider = new MySqlSyntaxProvider(Mock.Of()); Expression> predicate = user => user.Username.Equals("mydomain\\myuser"); var modelToSqlExpressionHelper = new ModelToSqlExpressionHelper(); @@ -102,7 +104,7 @@ namespace Umbraco.Tests.Persistence.Querying public void Poco_Expression_Value_Does_Not_Get_Double_Escaped() { //mysql escapes backslashes, so we'll test with that - SqlSyntaxContext.SqlSyntaxProvider = MySqlSyntax.Provider; + SqlSyntaxContext.SqlSyntaxProvider = new MySqlSyntaxProvider(Mock.Of()); Expression> predicate = user => user.Login.StartsWith("mydomain\\myuser"); var modelToSqlExpressionHelper = new PocoToSqlExpressionHelper(); diff --git a/src/Umbraco.Tests/Persistence/Repositories/ContentRepositoryTest.cs b/src/Umbraco.Tests/Persistence/Repositories/ContentRepositoryTest.cs index 0689cb729c..9dcd1a60ce 100644 --- a/src/Umbraco.Tests/Persistence/Repositories/ContentRepositoryTest.cs +++ b/src/Umbraco.Tests/Persistence/Repositories/ContentRepositoryTest.cs @@ -2,12 +2,16 @@ using System.Collections.Generic; using System.Linq; using System.Xml.Linq; +using Moq; using NUnit.Framework; using Umbraco.Core; +using Umbraco.Core.Configuration.UmbracoSettings; +using Umbraco.Core.IO; +using Umbraco.Core.Logging; using Umbraco.Core.Models; using Umbraco.Core.Models.Rdbms; using Umbraco.Core.Persistence; -using Umbraco.Core.Persistence.Caching; + using Umbraco.Core.Persistence.Querying; using Umbraco.Core.Persistence.Repositories; using Umbraco.Core.Persistence.UnitOfWork; @@ -37,17 +41,17 @@ namespace Umbraco.Tests.Persistence.Repositories private ContentRepository CreateRepository(IDatabaseUnitOfWork unitOfWork, out ContentTypeRepository contentTypeRepository) { - var templateRepository = new TemplateRepository(unitOfWork, NullCacheProvider.Current); - var tagRepository = new TagRepository(unitOfWork, NullCacheProvider.Current); - contentTypeRepository = new ContentTypeRepository(unitOfWork, NullCacheProvider.Current, templateRepository); - var repository = new ContentRepository(unitOfWork, NullCacheProvider.Current, contentTypeRepository, templateRepository, tagRepository, CacheHelper.CreateDisabledCacheHelper()); + var templateRepository = new TemplateRepository(unitOfWork, CacheHelper.CreateDisabledCacheHelper(), Mock.Of(), SqlSyntaxProvider, Mock.Of(), Mock.Of(), Mock.Of()); + var tagRepository = new TagRepository(unitOfWork, CacheHelper.CreateDisabledCacheHelper(), Mock.Of(), SqlSyntaxProvider); + contentTypeRepository = new ContentTypeRepository(unitOfWork, CacheHelper.CreateDisabledCacheHelper(), Mock.Of(), SqlSyntaxProvider, templateRepository); + var repository = new ContentRepository(unitOfWork, CacheHelper.CreateDisabledCacheHelper(), Mock.Of(), SqlSyntaxProvider, contentTypeRepository, templateRepository, tagRepository); return repository; } [Test] public void Rebuild_All_Xml_Structures() { - var provider = new PetaPocoUnitOfWorkProvider(); + var provider = new PetaPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); ContentTypeRepository contentTypeRepository; using (var repository = CreateRepository(unitOfWork, out contentTypeRepository)) @@ -94,7 +98,7 @@ namespace Umbraco.Tests.Persistence.Repositories [Test] public void Rebuild_All_Xml_Structures_For_Content_Type() { - var provider = new PetaPocoUnitOfWorkProvider(); + var provider = new PetaPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); ContentTypeRepository contentTypeRepository; using (var repository = CreateRepository(unitOfWork, out contentTypeRepository)) @@ -160,7 +164,7 @@ namespace Umbraco.Tests.Persistence.Repositories public void Ensures_Permissions_Are_Set_If_Parent_Entity_Permissions_Exist() { // Arrange - var provider = new PetaPocoUnitOfWorkProvider(); + var provider = new PetaPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); ContentTypeRepository contentTypeRepository; @@ -195,25 +199,11 @@ namespace Umbraco.Tests.Persistence.Repositories } - [Test] - public void Can_Instantiate_Repository_From_Resolver() - { - // Arrange - var provider = new PetaPocoUnitOfWorkProvider(); - var unitOfWork = provider.GetUnitOfWork(); - - // Act - var repository = RepositoryResolver.Current.ResolveByType(unitOfWork); - - // Assert - Assert.That(repository, Is.Not.Null); - } - [Test] public void Can_Perform_Add_On_ContentRepository() { // Arrange - var provider = new PetaPocoUnitOfWorkProvider(); + var provider = new PetaPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); ContentTypeRepository contentTypeRepository; using (var repository = CreateRepository(unitOfWork, out contentTypeRepository)) @@ -237,7 +227,7 @@ namespace Umbraco.Tests.Persistence.Repositories public void Can_Save_Content_With_AtSign_In_Name_On_ContentRepository() { // Arrange - var provider = new PetaPocoUnitOfWorkProvider(); + var provider = new PetaPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); ContentTypeRepository contentTypeRepository; using (var repository = CreateRepository(unitOfWork, out contentTypeRepository)) @@ -271,7 +261,7 @@ namespace Umbraco.Tests.Persistence.Repositories public void Can_Perform_Multiple_Adds_On_ContentRepository() { // Arrange - var provider = new PetaPocoUnitOfWorkProvider(); + var provider = new PetaPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); ContentTypeRepository contentTypeRepository; using (var repository = CreateRepository(unitOfWork, out contentTypeRepository)) @@ -297,41 +287,12 @@ namespace Umbraco.Tests.Persistence.Repositories } - [Test] - public void Can_Perform_Multiple_Adds_On_ContentRepository_With_RepositoryResolver() - { - // Arrange - var provider = new PetaPocoUnitOfWorkProvider(); - var unitOfWork = provider.GetUnitOfWork(); - ContentTypeRepository contentTypeRepository; - using (var repository = CreateRepository(unitOfWork, out contentTypeRepository)) - { - ContentType contentType = MockedContentTypes.CreateSimpleContentType("umbTextpage1", "Textpage"); - Content textpage = MockedContent.CreateSimpleContent(contentType); - - // Act - contentTypeRepository.AddOrUpdate(contentType); - repository.AddOrUpdate(textpage); - unitOfWork.Commit(); - - var repository2 = RepositoryResolver.Current.ResolveByType(unitOfWork); - Content subpage = MockedContent.CreateSimpleContent(contentType, "Text Page 1", textpage.Id); - repository2.AddOrUpdate(subpage); - unitOfWork.Commit(); - - // Assert - Assert.That(contentType.HasIdentity, Is.True); - Assert.That(textpage.HasIdentity, Is.True); - Assert.That(subpage.HasIdentity, Is.True); - Assert.That(textpage.Id, Is.EqualTo(subpage.ParentId)); - } - } [Test] public void Can_Verify_Fresh_Entity_Is_Not_Dirty() { // Arrange - var provider = new PetaPocoUnitOfWorkProvider(); + var provider = new PetaPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); ContentTypeRepository contentTypeRepository; using (var repository = CreateRepository(unitOfWork, out contentTypeRepository)) @@ -349,7 +310,7 @@ namespace Umbraco.Tests.Persistence.Repositories public void Can_Perform_Update_On_ContentRepository() { // Arrange - var provider = new PetaPocoUnitOfWorkProvider(); + var provider = new PetaPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); ContentTypeRepository contentTypeRepository; using (var repository = CreateRepository(unitOfWork, out contentTypeRepository)) @@ -372,7 +333,7 @@ namespace Umbraco.Tests.Persistence.Repositories public void Can_Perform_Delete_On_ContentRepository() { // Arrange - var provider = new PetaPocoUnitOfWorkProvider(); + var provider = new PetaPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); ContentTypeRepository contentTypeRepository; using (var repository = CreateRepository(unitOfWork, out contentTypeRepository)) @@ -387,11 +348,10 @@ namespace Umbraco.Tests.Persistence.Repositories unitOfWork.Commit(); var id = content.Id; - var repository2 = RepositoryResolver.Current.ResolveByType(unitOfWork); - repository2.Delete(content); + repository.Delete(content); unitOfWork.Commit(); - var content1 = repository2.Get(id); + var content1 = repository.Get(id); // Assert Assert.That(content1, Is.Null); @@ -402,7 +362,7 @@ namespace Umbraco.Tests.Persistence.Repositories public void Can_Perform_Get_On_ContentRepository() { // Arrange - var provider = new PetaPocoUnitOfWorkProvider(); + var provider = new PetaPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); ContentTypeRepository contentTypeRepository; using (var repository = CreateRepository(unitOfWork, out contentTypeRepository)) @@ -428,7 +388,7 @@ namespace Umbraco.Tests.Persistence.Repositories public void Can_Perform_GetByQuery_On_ContentRepository() { // Arrange - var provider = new PetaPocoUnitOfWorkProvider(); + var provider = new PetaPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); ContentTypeRepository contentTypeRepository; using (var repository = CreateRepository(unitOfWork, out contentTypeRepository)) @@ -446,7 +406,7 @@ namespace Umbraco.Tests.Persistence.Repositories public void Can_Perform_Get_All_With_Many_Version() { // Arrange - var provider = new PetaPocoUnitOfWorkProvider(); + var provider = new PetaPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); ContentTypeRepository contentTypeRepository; using (var repository = CreateRepository(unitOfWork, out contentTypeRepository)) @@ -477,7 +437,7 @@ namespace Umbraco.Tests.Persistence.Repositories public void Can_Perform_GetPagedResultsByQuery_ForFirstPage_On_ContentRepository() { // Arrange - var provider = new PetaPocoUnitOfWorkProvider(); + var provider = new PetaPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); ContentTypeRepository contentTypeRepository; using (var repository = CreateRepository(unitOfWork, out contentTypeRepository)) @@ -498,7 +458,7 @@ namespace Umbraco.Tests.Persistence.Repositories public void Can_Perform_GetPagedResultsByQuery_ForSecondPage_On_ContentRepository() { // Arrange - var provider = new PetaPocoUnitOfWorkProvider(); + var provider = new PetaPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); ContentTypeRepository contentTypeRepository; using (var repository = CreateRepository(unitOfWork, out contentTypeRepository)) @@ -519,7 +479,7 @@ namespace Umbraco.Tests.Persistence.Repositories public void Can_Perform_GetPagedResultsByQuery_WithSinglePage_On_ContentRepository() { // Arrange - var provider = new PetaPocoUnitOfWorkProvider(); + var provider = new PetaPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); ContentTypeRepository contentTypeRepository; using (var repository = CreateRepository(unitOfWork, out contentTypeRepository)) @@ -540,7 +500,7 @@ namespace Umbraco.Tests.Persistence.Repositories public void Can_Perform_GetPagedResultsByQuery_WithDescendingOrder_On_ContentRepository() { // Arrange - var provider = new PetaPocoUnitOfWorkProvider(); + var provider = new PetaPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); ContentTypeRepository contentTypeRepository; using (var repository = CreateRepository(unitOfWork, out contentTypeRepository)) @@ -561,7 +521,7 @@ namespace Umbraco.Tests.Persistence.Repositories public void Can_Perform_GetPagedResultsByQuery_WithFilterMatchingSome_On_ContentRepository() { // Arrange - var provider = new PetaPocoUnitOfWorkProvider(); + var provider = new PetaPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); ContentTypeRepository contentTypeRepository; using (var repository = CreateRepository(unitOfWork, out contentTypeRepository)) @@ -582,7 +542,7 @@ namespace Umbraco.Tests.Persistence.Repositories public void Can_Perform_GetPagedResultsByQuery_WithFilterMatchingAll_On_ContentRepository() { // Arrange - var provider = new PetaPocoUnitOfWorkProvider(); + var provider = new PetaPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); ContentTypeRepository contentTypeRepository; using (var repository = CreateRepository(unitOfWork, out contentTypeRepository)) @@ -603,7 +563,7 @@ namespace Umbraco.Tests.Persistence.Repositories public void Can_Perform_GetAll_By_Param_Ids_On_ContentRepository() { // Arrange - var provider = new PetaPocoUnitOfWorkProvider(); + var provider = new PetaPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); ContentTypeRepository contentTypeRepository; using (var repository = CreateRepository(unitOfWork, out contentTypeRepository)) @@ -622,7 +582,7 @@ namespace Umbraco.Tests.Persistence.Repositories public void Can_Perform_GetAll_On_ContentRepository() { // Arrange - var provider = new PetaPocoUnitOfWorkProvider(); + var provider = new PetaPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); ContentTypeRepository contentTypeRepository; using (var repository = CreateRepository(unitOfWork, out contentTypeRepository)) @@ -643,7 +603,7 @@ namespace Umbraco.Tests.Persistence.Repositories public void Can_Perform_Exists_On_ContentRepository() { // Arrange - var provider = new PetaPocoUnitOfWorkProvider(); + var provider = new PetaPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); ContentTypeRepository contentTypeRepository; using (var repository = CreateRepository(unitOfWork, out contentTypeRepository)) @@ -662,7 +622,7 @@ namespace Umbraco.Tests.Persistence.Repositories public void Can_Perform_Count_On_ContentRepository() { // Arrange - var provider = new PetaPocoUnitOfWorkProvider(); + var provider = new PetaPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); ContentTypeRepository contentTypeRepository; using (var repository = CreateRepository(unitOfWork, out contentTypeRepository)) @@ -681,7 +641,7 @@ namespace Umbraco.Tests.Persistence.Repositories public void Can_Verify_Keys_Set() { // Arrange - var provider = new PetaPocoUnitOfWorkProvider(); + var provider = new PetaPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); ContentTypeRepository contentTypeRepository; using (var repository = CreateRepository(unitOfWork, out contentTypeRepository)) @@ -702,7 +662,7 @@ namespace Umbraco.Tests.Persistence.Repositories public void Can_Get_Content_By_Guid_Key() { // Arrange - var provider = new PetaPocoUnitOfWorkProvider(); + var provider = new PetaPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); ContentTypeRepository contentTypeRepository; using (var repository = CreateRepository(unitOfWork, out contentTypeRepository)) @@ -722,7 +682,7 @@ namespace Umbraco.Tests.Persistence.Repositories public void Can_Create_Different_Language_Version() { // Arrange - var provider = new PetaPocoUnitOfWorkProvider(); + var provider = new PetaPocoUnitOfWorkProvider(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 5d94e604a4..79061564cc 100644 --- a/src/Umbraco.Tests/Persistence/Repositories/ContentTypeRepositoryTest.cs +++ b/src/Umbraco.Tests/Persistence/Repositories/ContentTypeRepositoryTest.cs @@ -1,13 +1,17 @@ using System; using System.Collections.Generic; using System.Linq; +using Moq; using NUnit.Framework; using Umbraco.Core; +using Umbraco.Core.Configuration.UmbracoSettings; +using Umbraco.Core.IO; +using Umbraco.Core.Logging; using Umbraco.Core.Models; using Umbraco.Core.Models.EntityBase; using Umbraco.Core.Models.Rdbms; using Umbraco.Core.Persistence; -using Umbraco.Core.Persistence.Caching; + using Umbraco.Core.Persistence.Repositories; using Umbraco.Core.Persistence.UnitOfWork; using Umbraco.Tests.TestHelpers; @@ -35,43 +39,30 @@ namespace Umbraco.Tests.Persistence.Repositories private ContentRepository CreateRepository(IDatabaseUnitOfWork unitOfWork, out ContentTypeRepository contentTypeRepository) { - var templateRepository = new TemplateRepository(unitOfWork, NullCacheProvider.Current); - var tagRepository = new TagRepository(unitOfWork, NullCacheProvider.Current); - contentTypeRepository = new ContentTypeRepository(unitOfWork, NullCacheProvider.Current, templateRepository); - var repository = new ContentRepository(unitOfWork, NullCacheProvider.Current, contentTypeRepository, templateRepository, tagRepository, CacheHelper.CreateDisabledCacheHelper()); + var templateRepository = new TemplateRepository(unitOfWork, CacheHelper.CreateDisabledCacheHelper(), Mock.Of(), SqlSyntaxProvider, Mock.Of(), Mock.Of(), Mock.Of()); + var tagRepository = new TagRepository(unitOfWork, CacheHelper.CreateDisabledCacheHelper(), Mock.Of(), SqlSyntaxProvider); + contentTypeRepository = new ContentTypeRepository(unitOfWork, CacheHelper.CreateDisabledCacheHelper(), Mock.Of(), SqlSyntaxProvider, templateRepository); + var repository = new ContentRepository(unitOfWork, CacheHelper.CreateDisabledCacheHelper(), Mock.Of(), SqlSyntaxProvider, contentTypeRepository, templateRepository, tagRepository); return repository; } private ContentTypeRepository CreateRepository(IDatabaseUnitOfWork unitOfWork) { - var templateRepository = new TemplateRepository(unitOfWork, NullCacheProvider.Current); - var contentTypeRepository = new ContentTypeRepository(unitOfWork, NullCacheProvider.Current, templateRepository); + var templateRepository = new TemplateRepository(unitOfWork, CacheHelper.CreateDisabledCacheHelper(), Mock.Of(), SqlSyntaxProvider, Mock.Of(), Mock.Of(), Mock.Of()); + var contentTypeRepository = new ContentTypeRepository(unitOfWork, CacheHelper.CreateDisabledCacheHelper(), Mock.Of(), SqlSyntaxProvider, templateRepository); return contentTypeRepository; } //TODO Add test to verify SetDefaultTemplates updates both AllowedTemplates and DefaultTemplate(id). - [Test] - public void Can_Instantiate_Repository_From_Resolver() - { - // Arrange - var provider = new PetaPocoUnitOfWorkProvider(); - var unitOfWork = provider.GetUnitOfWork(); - - // Act - var repository = RepositoryResolver.Current.ResolveByType(unitOfWork); - - // Assert - Assert.That(repository, Is.Not.Null); - } [Test] public void Maps_Templates_Correctly() { // Arrange - var provider = new PetaPocoUnitOfWorkProvider(); + var provider = new PetaPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); - using (var templateRepo = new TemplateRepository(unitOfWork)) + using (var templateRepo = new TemplateRepository(unitOfWork, CacheHelper.CreateDisabledCacheHelper(), Mock.Of(), SqlSyntaxProvider, Mock.Of(), Mock.Of(), Mock.Of())) using (var repository = CreateRepository(unitOfWork)) { var templates = new[] @@ -105,7 +96,7 @@ namespace Umbraco.Tests.Persistence.Repositories public void Can_Perform_Add_On_ContentTypeRepository() { // Arrange - var provider = new PetaPocoUnitOfWorkProvider(); + var provider = new PetaPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); using (var repository = CreateRepository(unitOfWork)) { @@ -127,7 +118,7 @@ namespace Umbraco.Tests.Persistence.Repositories public void Can_Perform_Update_On_ContentTypeRepository() { // Arrange - var provider = new PetaPocoUnitOfWorkProvider(); + var provider = new PetaPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); using (var repository = CreateRepository(unitOfWork)) { @@ -164,7 +155,7 @@ namespace Umbraco.Tests.Persistence.Repositories public void Can_Perform_Delete_On_ContentTypeRepository() { // Arrange - var provider = new PetaPocoUnitOfWorkProvider(); + var provider = new PetaPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); using (var repository = CreateRepository(unitOfWork)) { @@ -188,7 +179,7 @@ namespace Umbraco.Tests.Persistence.Repositories public void Can_Perform_Delete_With_Heirarchy_On_ContentTypeRepository() { // Arrange - var provider = new PetaPocoUnitOfWorkProvider(); + var provider = new PetaPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); using (var repository = CreateRepository(unitOfWork)) { @@ -218,7 +209,7 @@ namespace Umbraco.Tests.Persistence.Repositories public void Can_Perform_Get_On_ContentTypeRepository() { // Arrange - var provider = new PetaPocoUnitOfWorkProvider(); + var provider = new PetaPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); using (var repository = CreateRepository(unitOfWork)) { @@ -236,7 +227,7 @@ namespace Umbraco.Tests.Persistence.Repositories public void Can_Perform_GetAll_On_ContentTypeRepository() { // Arrange - var provider = new PetaPocoUnitOfWorkProvider(); + var provider = new PetaPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); using (var repository = CreateRepository(unitOfWork)) { @@ -258,7 +249,7 @@ namespace Umbraco.Tests.Persistence.Repositories public void Can_Perform_Exists_On_ContentTypeRepository() { // Arrange - var provider = new PetaPocoUnitOfWorkProvider(); + var provider = new PetaPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); using (var repository = CreateRepository(unitOfWork)) { @@ -275,7 +266,7 @@ namespace Umbraco.Tests.Persistence.Repositories public void Can_Update_ContentType_With_PropertyType_Removed() { // Arrange - var provider = new PetaPocoUnitOfWorkProvider(); + var provider = new PetaPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); using (var repository = CreateRepository(unitOfWork)) { @@ -299,7 +290,7 @@ namespace Umbraco.Tests.Persistence.Repositories public void Can_Verify_PropertyTypes_On_SimpleTextpage() { // Arrange - var provider = new PetaPocoUnitOfWorkProvider(); + var provider = new PetaPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); using (var repository = CreateRepository(unitOfWork)) { @@ -317,7 +308,7 @@ namespace Umbraco.Tests.Persistence.Repositories public void Can_Verify_PropertyTypes_On_Textpage() { // Arrange - var provider = new PetaPocoUnitOfWorkProvider(); + var provider = new PetaPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); using (var repository = CreateRepository(unitOfWork)) { @@ -335,7 +326,7 @@ namespace Umbraco.Tests.Persistence.Repositories public void Can_Verify_PropertyType_With_No_Group() { // Arrange - var provider = new PetaPocoUnitOfWorkProvider(); + var provider = new PetaPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); using (var repository = CreateRepository(unitOfWork)) { @@ -371,7 +362,7 @@ namespace Umbraco.Tests.Persistence.Repositories public void Can_Verify_AllowedChildContentTypes_On_ContentType() { // Arrange - var provider = new PetaPocoUnitOfWorkProvider(); + var provider = new PetaPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); using (var repository = CreateRepository(unitOfWork)) { @@ -415,7 +406,7 @@ namespace Umbraco.Tests.Persistence.Repositories public void Can_Verify_Removal_Of_Used_PropertyType_From_ContentType() { // Arrange - var provider = new PetaPocoUnitOfWorkProvider(); + var provider = new PetaPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); ContentTypeRepository repository; using (var contentRepository = CreateRepository(unitOfWork, out repository)) @@ -442,7 +433,7 @@ namespace Umbraco.Tests.Persistence.Repositories public void Can_Verify_Addition_Of_PropertyType_After_ContentType_Is_Used() { // Arrange - var provider = new PetaPocoUnitOfWorkProvider(); + var provider = new PetaPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); ContentTypeRepository repository; using (var contentRepository = CreateRepository(unitOfWork, out repository)) @@ -470,7 +461,7 @@ namespace Umbraco.Tests.Persistence.Repositories public void Can_Verify_Usage_Of_New_PropertyType_On_Content() { // Arrange - var provider = new PetaPocoUnitOfWorkProvider(); + var provider = new PetaPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); ContentTypeRepository repository; using (var contentRepository = CreateRepository(unitOfWork, out repository)) @@ -506,7 +497,7 @@ namespace Umbraco.Tests.Persistence.Repositories () { // Arrange - var provider = new PetaPocoUnitOfWorkProvider(); + var provider = new PetaPocoUnitOfWorkProvider(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 2e37bff92e..9c9b084a48 100644 --- a/src/Umbraco.Tests/Persistence/Repositories/DataTypeDefinitionRepositoryTest.cs +++ b/src/Umbraco.Tests/Persistence/Repositories/DataTypeDefinitionRepositoryTest.cs @@ -1,9 +1,13 @@ using System; using System.Data; using System.Linq; +using Moq; using NUnit.Framework; using Umbraco.Core; using Umbraco.Core.Cache; +using Umbraco.Core.Configuration.UmbracoSettings; +using Umbraco.Core.IO; +using Umbraco.Core.Logging; using Umbraco.Core.Models; using Umbraco.Core.Models.Membership; using Umbraco.Core.Models.Rdbms; @@ -12,7 +16,6 @@ using Umbraco.Core.Persistence.Querying; using Umbraco.Core.Persistence.Repositories; using Umbraco.Core.Persistence.UnitOfWork; using Umbraco.Tests.TestHelpers; -using NullCacheProvider = Umbraco.Core.Persistence.Caching.NullCacheProvider; namespace Umbraco.Tests.Persistence.Repositories { @@ -29,16 +32,18 @@ namespace Umbraco.Tests.Persistence.Repositories private DataTypeDefinitionRepository CreateRepository(IDatabaseUnitOfWork unitOfWork) { var dataTypeDefinitionRepository = new DataTypeDefinitionRepository( - unitOfWork, NullCacheProvider.Current, CacheHelper.CreateDisabledCacheHelper(), - new ContentTypeRepository(unitOfWork, NullCacheProvider.Current, - new TemplateRepository(unitOfWork, NullCacheProvider.Current))); + unitOfWork, CacheHelper.CreateDisabledCacheHelper(), + CacheHelper.CreateDisabledCacheHelper(), + Mock.Of(), SqlSyntaxProvider, + new ContentTypeRepository(unitOfWork, CacheHelper.CreateDisabledCacheHelper(), Mock.Of(), SqlSyntaxProvider, + new TemplateRepository(unitOfWork, CacheHelper.CreateDisabledCacheHelper(), Mock.Of(), SqlSyntaxProvider, Mock.Of(), Mock.Of(), Mock.Of()))); return dataTypeDefinitionRepository; } [Test] public void Can_Create() { - var provider = new PetaPocoUnitOfWorkProvider(); + var provider = new PetaPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); int id; using (var repository = CreateRepository(unitOfWork)) @@ -65,7 +70,7 @@ namespace Umbraco.Tests.Persistence.Repositories [Test] public void Cannot_Create_Duplicate_Name() { - var provider = new PetaPocoUnitOfWorkProvider(); + var provider = new PetaPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); int id; using (var repository = CreateRepository(unitOfWork)) @@ -86,25 +91,13 @@ namespace Umbraco.Tests.Persistence.Repositories } } - [Test] - public void Can_Instantiate_Repository_From_Resolver() - { - // Arrange - var provider = new PetaPocoUnitOfWorkProvider(); - var unitOfWork = provider.GetUnitOfWork(); - - // Act - var repository = RepositoryResolver.Current.ResolveByType(unitOfWork); - - // Assert - Assert.That(repository, Is.Not.Null); - } + [Test] public void Can_Perform_Get_On_DataTypeDefinitionRepository() { // Arrange - var provider = new PetaPocoUnitOfWorkProvider(); + var provider = new PetaPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); using (var repository = CreateRepository(unitOfWork)) { @@ -123,7 +116,7 @@ namespace Umbraco.Tests.Persistence.Repositories public void Can_Perform_GetAll_On_DataTypeDefinitionRepository() { // Arrange - var provider = new PetaPocoUnitOfWorkProvider(); + var provider = new PetaPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); using (var repository = CreateRepository(unitOfWork)) { @@ -143,7 +136,7 @@ namespace Umbraco.Tests.Persistence.Repositories public void Can_Perform_GetAll_With_Params_On_DataTypeDefinitionRepository() { // Arrange - var provider = new PetaPocoUnitOfWorkProvider(); + var provider = new PetaPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); using (var repository = CreateRepository(unitOfWork)) { @@ -163,7 +156,7 @@ namespace Umbraco.Tests.Persistence.Repositories public void Can_Perform_GetByQuery_On_DataTypeDefinitionRepository() { // Arrange - var provider = new PetaPocoUnitOfWorkProvider(); + var provider = new PetaPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); using (var repository = CreateRepository(unitOfWork)) { @@ -183,7 +176,7 @@ namespace Umbraco.Tests.Persistence.Repositories public void Can_Perform_Count_On_DataTypeDefinitionRepository() { // Arrange - var provider = new PetaPocoUnitOfWorkProvider(); + var provider = new PetaPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); using (var repository = CreateRepository(unitOfWork)) { @@ -201,7 +194,7 @@ namespace Umbraco.Tests.Persistence.Repositories public void Can_Perform_Add_On_DataTypeDefinitionRepository() { // Arrange - var provider = new PetaPocoUnitOfWorkProvider(); + var provider = new PetaPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); using (var repository = CreateRepository(unitOfWork)) { @@ -228,7 +221,7 @@ namespace Umbraco.Tests.Persistence.Repositories public void Can_Perform_Update_On_DataTypeDefinitionRepository() { // Arrange - var provider = new PetaPocoUnitOfWorkProvider(); + var provider = new PetaPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); using (var repository = CreateRepository(unitOfWork)) { @@ -262,7 +255,7 @@ namespace Umbraco.Tests.Persistence.Repositories public void Can_Perform_Delete_On_DataTypeDefinitionRepository() { // Arrange - var provider = new PetaPocoUnitOfWorkProvider(); + var provider = new PetaPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); using (var repository = CreateRepository(unitOfWork)) { @@ -294,7 +287,7 @@ namespace Umbraco.Tests.Persistence.Repositories public void Can_Perform_Exists_On_DataTypeDefinitionRepository() { // Arrange - var provider = new PetaPocoUnitOfWorkProvider(); + var provider = new PetaPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); using (var repository = CreateRepository(unitOfWork)) { @@ -312,7 +305,7 @@ namespace Umbraco.Tests.Persistence.Repositories [Test] public void Can_Get_Pre_Value_Collection() { - var provider = new PetaPocoUnitOfWorkProvider(); + var provider = new PetaPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); int dtid; @@ -337,7 +330,7 @@ namespace Umbraco.Tests.Persistence.Repositories [Test] public void Can_Get_Pre_Value_As_String() { - var provider = new PetaPocoUnitOfWorkProvider(); + var provider = new PetaPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); int dtid; @@ -362,15 +355,17 @@ namespace Umbraco.Tests.Persistence.Repositories [Test] public void Can_Get_Pre_Value_Collection_With_Cache() { - var provider = new PetaPocoUnitOfWorkProvider(); + var provider = new PetaPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); var cache = new CacheHelper(new ObjectCacheRuntimeCacheProvider(), new StaticCacheProvider(), new StaticCacheProvider()); Func creator = () => new DataTypeDefinitionRepository( - unitOfWork, NullCacheProvider.Current, cache, - new ContentTypeRepository(unitOfWork, NullCacheProvider.Current, - new TemplateRepository(unitOfWork, NullCacheProvider.Current))); + unitOfWork, CacheHelper.CreateDisabledCacheHelper(), + cache, + Mock.Of(), SqlSyntaxProvider, + new ContentTypeRepository(unitOfWork, CacheHelper.CreateDisabledCacheHelper(), Mock.Of(), SqlSyntaxProvider, + new TemplateRepository(unitOfWork, CacheHelper.CreateDisabledCacheHelper(), Mock.Of(), SqlSyntaxProvider, Mock.Of(), Mock.Of(), Mock.Of()))); DataTypeDefinition dtd; using (var repository = creator()) @@ -399,15 +394,17 @@ namespace Umbraco.Tests.Persistence.Repositories [Test] public void Can_Get_Pre_Value_As_String_With_Cache() { - var provider = new PetaPocoUnitOfWorkProvider(); + var provider = new PetaPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); var cache = new CacheHelper(new ObjectCacheRuntimeCacheProvider(), new StaticCacheProvider(), new StaticCacheProvider()); Func creator = () => new DataTypeDefinitionRepository( - unitOfWork, NullCacheProvider.Current, cache, - new ContentTypeRepository(unitOfWork, NullCacheProvider.Current, - new TemplateRepository(unitOfWork, NullCacheProvider.Current))); + unitOfWork, CacheHelper.CreateDisabledCacheHelper(), + cache, + Mock.Of(), SqlSyntaxProvider, + new ContentTypeRepository(unitOfWork, CacheHelper.CreateDisabledCacheHelper(), Mock.Of(), SqlSyntaxProvider, + new TemplateRepository(unitOfWork, CacheHelper.CreateDisabledCacheHelper(), Mock.Of(), SqlSyntaxProvider, Mock.Of(), Mock.Of(), Mock.Of()))); DataTypeDefinition dtd; using (var repository = creator()) diff --git a/src/Umbraco.Tests/Persistence/Repositories/DictionaryRepositoryTest.cs b/src/Umbraco.Tests/Persistence/Repositories/DictionaryRepositoryTest.cs index a81d91fc11..b520997ba9 100644 --- a/src/Umbraco.Tests/Persistence/Repositories/DictionaryRepositoryTest.cs +++ b/src/Umbraco.Tests/Persistence/Repositories/DictionaryRepositoryTest.cs @@ -1,11 +1,15 @@ using System.Collections.Generic; 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.Caching; + using Umbraco.Core.Persistence.Querying; using Umbraco.Core.Persistence.Repositories; +using Umbraco.Core.Persistence.SqlSyntax; using Umbraco.Core.Persistence.UnitOfWork; using Umbraco.Tests.TestHelpers; @@ -25,46 +29,136 @@ namespace Umbraco.Tests.Persistence.Repositories private DictionaryRepository CreateRepository(IDatabaseUnitOfWork unitOfWork, out LanguageRepository languageRepository) { - languageRepository = new LanguageRepository(unitOfWork, NullCacheProvider.Current); - var dictionaryRepository = new DictionaryRepository(unitOfWork, NullCacheProvider.Current, languageRepository); + languageRepository = new LanguageRepository(unitOfWork, CacheHelper.CreateDisabledCacheHelper(), Mock.Of(), SqlSyntaxProvider); + var dictionaryRepository = new DictionaryRepository(unitOfWork, CacheHelper.CreateDisabledCacheHelper(), Mock.Of(), new SqlCeSyntaxProvider(), languageRepository); return dictionaryRepository; } + [Test] - public void Can_Instantiate_Repository_From_Resolver() + public void Can_Perform_Get_By_Key_On_DictionaryRepository() { // Arrange - var provider = new PetaPocoUnitOfWorkProvider(); + var provider = new PetaPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); + LanguageRepository languageRepository; + using (var repository = CreateRepository(unitOfWork, out languageRepository)) + { + var dictionaryItem = (IDictionaryItem)new DictionaryItem("Testing1235") + { + Translations = new List + { + new DictionaryTranslation(ServiceContext.LocalizationService.GetLanguageByCultureCode("en-US"), "Hello world") + } + }; - // Act - var repository = RepositoryResolver.Current.ResolveByType(unitOfWork); + repository.AddOrUpdate(dictionaryItem); + unitOfWork.Commit(); + + //re-get + dictionaryItem = repository.Get("Testing1235"); + + // Assert + Assert.That(dictionaryItem, Is.Not.Null); + Assert.That(dictionaryItem.ItemKey, Is.EqualTo("Testing1235")); + Assert.That(dictionaryItem.Translations.Any(), Is.True); + Assert.That(dictionaryItem.Translations.Any(x => x == null), Is.False); + Assert.That(dictionaryItem.Translations.First().Value, Is.EqualTo("Hello world")); + } + + } + + [Test] + public void Can_Perform_Get_By_UniqueId_On_DictionaryRepository() + { + // Arrange + var provider = new PetaPocoUnitOfWorkProvider(Logger); + var unitOfWork = provider.GetUnitOfWork(); + LanguageRepository languageRepository; + using (var repository = CreateRepository(unitOfWork, out languageRepository)) + { + var dictionaryItem = (IDictionaryItem)new DictionaryItem("Testing1235") + { + Translations = new List + { + new DictionaryTranslation(ServiceContext.LocalizationService.GetLanguageByCultureCode("en-US"), "Hello world") + } + }; + + repository.AddOrUpdate(dictionaryItem); + unitOfWork.Commit(); + + //re-get + dictionaryItem = repository.Get(dictionaryItem.Key); + + // Assert + Assert.That(dictionaryItem, Is.Not.Null); + Assert.That(dictionaryItem.ItemKey, Is.EqualTo("Testing1235")); + Assert.That(dictionaryItem.Translations.Any(), Is.True); + Assert.That(dictionaryItem.Translations.Any(x => x == null), Is.False); + Assert.That(dictionaryItem.Translations.First().Value, Is.EqualTo("Hello world")); + } - // Assert - Assert.That(repository, Is.Not.Null); } [Test] public void Can_Perform_Get_On_DictionaryRepository() { // Arrange - var provider = new PetaPocoUnitOfWorkProvider(); + var provider = new PetaPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); LanguageRepository languageRepository; using (var repository = CreateRepository(unitOfWork, out languageRepository)) { - // Act - var dictionaryItem = repository.Get(1); + var dictionaryItem = (IDictionaryItem)new DictionaryItem("Testing1235") + { + Translations = new List + { + new DictionaryTranslation(ServiceContext.LocalizationService.GetLanguageByCultureCode("en-US"), "Hello world") + } + }; + + repository.AddOrUpdate(dictionaryItem); + unitOfWork.Commit(); + + //re-get + dictionaryItem = repository.Get(dictionaryItem.Id); + // Assert Assert.That(dictionaryItem, Is.Not.Null); - Assert.That(dictionaryItem.ItemKey, Is.EqualTo("Read More")); + Assert.That(dictionaryItem.ItemKey, Is.EqualTo("Testing1235")); Assert.That(dictionaryItem.Translations.Any(), Is.True); Assert.That(dictionaryItem.Translations.Any(x => x == null), Is.False); - Assert.That(dictionaryItem.Translations.First().Value, Is.EqualTo("Read More")); - Assert.That(dictionaryItem.Translations.Last().Value, Is.EqualTo("Læs mere")); + Assert.That(dictionaryItem.Translations.First().Value, Is.EqualTo("Hello world")); } - + + } + + [Test] + public void Can_Perform_Get_On_DictionaryRepository_When_No_Language_Assigned() + { + // Arrange + var provider = new PetaPocoUnitOfWorkProvider(Logger); + var unitOfWork = provider.GetUnitOfWork(); + LanguageRepository languageRepository; + using (var repository = CreateRepository(unitOfWork, out languageRepository)) + { + var dictionaryItem = (IDictionaryItem) new DictionaryItem("Testing1235"); + + repository.AddOrUpdate(dictionaryItem); + unitOfWork.Commit(); + + //re-get + dictionaryItem = repository.Get(dictionaryItem.Id); + + + // Assert + Assert.That(dictionaryItem, Is.Not.Null); + Assert.That(dictionaryItem.ItemKey, Is.EqualTo("Testing1235")); + Assert.That(dictionaryItem.Translations.Any(), Is.False); + } + } [Test] @@ -81,7 +175,7 @@ namespace Umbraco.Tests.Persistence.Repositories itemMissingLanguage.Translations = translations; ServiceContext.LocalizationService.Save(itemMissingLanguage);//Id 3? - var provider = new PetaPocoUnitOfWorkProvider(); + var provider = new PetaPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); LanguageRepository languageRepository; using (var repository = CreateRepository(unitOfWork, out languageRepository)) @@ -103,7 +197,7 @@ namespace Umbraco.Tests.Persistence.Repositories public void Can_Perform_GetAll_On_DictionaryRepository() { // Arrange - var provider = new PetaPocoUnitOfWorkProvider(); + var provider = new PetaPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); LanguageRepository languageRepository; using (var repository = CreateRepository(unitOfWork, out languageRepository)) @@ -125,7 +219,7 @@ namespace Umbraco.Tests.Persistence.Repositories public void Can_Perform_GetAll_With_Params_On_DictionaryRepository() { // Arrange - var provider = new PetaPocoUnitOfWorkProvider(); + var provider = new PetaPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); LanguageRepository languageRepository; using (var repository = CreateRepository(unitOfWork, out languageRepository)) @@ -146,7 +240,7 @@ namespace Umbraco.Tests.Persistence.Repositories public void Can_Perform_GetByQuery_On_DictionaryRepository() { // Arrange - var provider = new PetaPocoUnitOfWorkProvider(); + var provider = new PetaPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); LanguageRepository languageRepository; using (var repository = CreateRepository(unitOfWork, out languageRepository)) @@ -167,7 +261,7 @@ namespace Umbraco.Tests.Persistence.Repositories public void Can_Perform_Count_On_DictionaryRepository() { // Arrange - var provider = new PetaPocoUnitOfWorkProvider(); + var provider = new PetaPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); LanguageRepository languageRepository; using (var repository = CreateRepository(unitOfWork, out languageRepository)) @@ -186,7 +280,7 @@ namespace Umbraco.Tests.Persistence.Repositories public void Can_Perform_Add_On_DictionaryRepository() { // Arrange - var provider = new PetaPocoUnitOfWorkProvider(); + var provider = new PetaPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); LanguageRepository languageRepository; using (var repository = CreateRepository(unitOfWork, out languageRepository)) @@ -217,7 +311,7 @@ namespace Umbraco.Tests.Persistence.Repositories public void Can_Perform_Update_On_DictionaryRepository() { // Arrange - var provider = new PetaPocoUnitOfWorkProvider(); + var provider = new PetaPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); LanguageRepository languageRepository; using (var repository = CreateRepository(unitOfWork, out languageRepository)) @@ -245,10 +339,10 @@ namespace Umbraco.Tests.Persistence.Repositories public void Can_Perform_Update_WithNewTranslation_On_DictionaryRepository() { // Arrange - var provider = new PetaPocoUnitOfWorkProvider(); + var provider = new PetaPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); - var languageRepository = new LanguageRepository(unitOfWork); - var repository = new DictionaryRepository(unitOfWork, languageRepository); + var languageRepository = new LanguageRepository(unitOfWork, CacheHelper.CreateDisabledCacheHelper(), Mock.Of(), SqlSyntaxProvider); + var repository = new DictionaryRepository(unitOfWork, CacheHelper.CreateDisabledCacheHelper(), Mock.Of(), new SqlCeSyntaxProvider(), languageRepository); var languageNo = new Language("nb-NO") { CultureName = "nb-NO" }; ServiceContext.LocalizationService.Save(languageNo); @@ -274,7 +368,7 @@ namespace Umbraco.Tests.Persistence.Repositories public void Can_Perform_Delete_On_DictionaryRepository() { // Arrange - var provider = new PetaPocoUnitOfWorkProvider(); + var provider = new PetaPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); LanguageRepository languageRepository; using (var repository = CreateRepository(unitOfWork, out languageRepository)) @@ -296,7 +390,7 @@ namespace Umbraco.Tests.Persistence.Repositories public void Can_Perform_Exists_On_DictionaryRepository() { // Arrange - var provider = new PetaPocoUnitOfWorkProvider(); + var provider = new PetaPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); LanguageRepository languageRepository; using (var repository = CreateRepository(unitOfWork, out languageRepository)) diff --git a/src/Umbraco.Tests/Persistence/Repositories/LanguageRepositoryTest.cs b/src/Umbraco.Tests/Persistence/Repositories/LanguageRepositoryTest.cs index bbc5d1ff22..e07dc79141 100644 --- a/src/Umbraco.Tests/Persistence/Repositories/LanguageRepositoryTest.cs +++ b/src/Umbraco.Tests/Persistence/Repositories/LanguageRepositoryTest.cs @@ -1,8 +1,12 @@ -using System.Linq; +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.Caching; + using Umbraco.Core.Persistence.Querying; using Umbraco.Core.Persistence.Repositories; using Umbraco.Core.Persistence.UnitOfWork; @@ -24,28 +28,16 @@ namespace Umbraco.Tests.Persistence.Repositories private LanguageRepository CreateRepository(IDatabaseUnitOfWork unitOfWork) { - return new LanguageRepository(unitOfWork, NullCacheProvider.Current); + return new LanguageRepository(unitOfWork, CacheHelper.CreateDisabledCacheHelper(), Mock.Of(), SqlSyntaxProvider); } - [Test] - public void Can_Instantiate_Repository_From_Resolver() - { - // Arrange - var provider = new PetaPocoUnitOfWorkProvider(); - var unitOfWork = provider.GetUnitOfWork(); - - // Act - var repository = RepositoryResolver.Current.ResolveByType(unitOfWork); - - // Assert - Assert.That(repository, Is.Not.Null); - } + [Test] public void Can_Perform_Get_On_LanguageRepository() { // Arrange - var provider = new PetaPocoUnitOfWorkProvider(); + var provider = new PetaPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); using (var repository = CreateRepository(unitOfWork)) { @@ -60,11 +52,63 @@ namespace Umbraco.Tests.Persistence.Repositories } } + [Test] + public void Can_Perform_Get_By_Iso_Code_On_LanguageRepository() + { + var provider = new PetaPocoUnitOfWorkProvider(Logger); + var unitOfWork = provider.GetUnitOfWork(); + using (var repository = CreateRepository(unitOfWork)) + { + var au = CultureInfo.GetCultureInfo("en-AU"); + var language = (ILanguage)new Language(au.Name) + { + CultureName = au.DisplayName + }; + repository.AddOrUpdate(language); + unitOfWork.Commit(); + + //re-get + language = repository.GetByIsoCode(au.Name); + + // Assert + Assert.That(language, Is.Not.Null); + Assert.That(language.HasIdentity, Is.True); + Assert.That(language.CultureName, Is.EqualTo(au.DisplayName)); + Assert.That(language.IsoCode, Is.EqualTo(au.Name)); + } + } + + [Test] + public void Can_Perform_Get_By_Culture_Name_On_LanguageRepository() + { + var provider = new PetaPocoUnitOfWorkProvider(Logger); + var unitOfWork = provider.GetUnitOfWork(); + using (var repository = CreateRepository(unitOfWork)) + { + var au = CultureInfo.GetCultureInfo("en-AU"); + var language = (ILanguage)new Language(au.Name) + { + CultureName = au.DisplayName + }; + repository.AddOrUpdate(language); + unitOfWork.Commit(); + + //re-get + language = repository.GetByCultureName(au.DisplayName); + + // Assert + Assert.That(language, Is.Not.Null); + Assert.That(language.HasIdentity, Is.True); + Assert.That(language.CultureName, Is.EqualTo(au.DisplayName)); + Assert.That(language.IsoCode, Is.EqualTo(au.Name)); + } + } + [Test] public void Get_WhenIdDoesntExist_ReturnsNull() { // Arrange - var provider = new PetaPocoUnitOfWorkProvider(); + var provider = new PetaPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); using (var repository = CreateRepository(unitOfWork)) { @@ -80,7 +124,7 @@ namespace Umbraco.Tests.Persistence.Repositories public void Can_Perform_GetAll_On_LanguageRepository() { // Arrange - var provider = new PetaPocoUnitOfWorkProvider(); + var provider = new PetaPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); using (var repository = CreateRepository(unitOfWork)) { @@ -100,7 +144,7 @@ namespace Umbraco.Tests.Persistence.Repositories public void Can_Perform_GetAll_With_Params_On_LanguageRepository() { // Arrange - var provider = new PetaPocoUnitOfWorkProvider(); + var provider = new PetaPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); using (var repository = CreateRepository(unitOfWork)) { @@ -120,7 +164,7 @@ namespace Umbraco.Tests.Persistence.Repositories public void Can_Perform_GetByQuery_On_LanguageRepository() { // Arrange - var provider = new PetaPocoUnitOfWorkProvider(); + var provider = new PetaPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); using (var repository = CreateRepository(unitOfWork)) { @@ -140,7 +184,7 @@ namespace Umbraco.Tests.Persistence.Repositories public void Can_Perform_Count_On_LanguageRepository() { // Arrange - var provider = new PetaPocoUnitOfWorkProvider(); + var provider = new PetaPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); using (var repository = CreateRepository(unitOfWork)) { @@ -158,7 +202,7 @@ namespace Umbraco.Tests.Persistence.Repositories public void Can_Perform_Add_On_LanguageRepository() { // Arrange - var provider = new PetaPocoUnitOfWorkProvider(); + var provider = new PetaPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); using (var repository = CreateRepository(unitOfWork)) { @@ -178,7 +222,7 @@ namespace Umbraco.Tests.Persistence.Repositories public void Can_Perform_Update_On_LanguageRepository() { // Arrange - var provider = new PetaPocoUnitOfWorkProvider(); + var provider = new PetaPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); using (var repository = CreateRepository(unitOfWork)) { @@ -204,7 +248,7 @@ namespace Umbraco.Tests.Persistence.Repositories public void Can_Perform_Delete_On_LanguageRepository() { // Arrange - var provider = new PetaPocoUnitOfWorkProvider(); + var provider = new PetaPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); using (var repository = CreateRepository(unitOfWork)) { @@ -225,7 +269,7 @@ namespace Umbraco.Tests.Persistence.Repositories public void Can_Perform_Exists_On_LanguageRepository() { // Arrange - var provider = new PetaPocoUnitOfWorkProvider(); + var provider = new PetaPocoUnitOfWorkProvider(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 377b9e57e7..005b1a211a 100644 --- a/src/Umbraco.Tests/Persistence/Repositories/MacroRepositoryTest.cs +++ b/src/Umbraco.Tests/Persistence/Repositories/MacroRepositoryTest.cs @@ -1,9 +1,12 @@ using System.Data.SqlServerCe; 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.Caching; + using Umbraco.Core.Persistence.Querying; using Umbraco.Core.Persistence.Repositories; using Umbraco.Core.Persistence.UnitOfWork; @@ -27,11 +30,11 @@ namespace Umbraco.Tests.Persistence.Repositories public void Cannot_Add_Duplicate_Macros() { // Arrange - var provider = new PetaPocoUnitOfWorkProvider(); + var provider = new PetaPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); // Act - using (var repository = new MacroRepository(unitOfWork, NullCacheProvider.Current)) + using (var repository = new MacroRepository(unitOfWork, CacheHelper.CreateDisabledCacheHelper(), Mock.Of(), SqlSyntaxProvider)) { var macro = new Macro("test1", "Test", "~/usercontrol/blah.ascx", "MyAssembly", "test.xslt", "~/views/macropartials/test.cshtml"); repository.AddOrUpdate(macro); @@ -45,11 +48,11 @@ namespace Umbraco.Tests.Persistence.Repositories public void Cannot_Update_To_Duplicate_Macro_Alias() { // Arrange - var provider = new PetaPocoUnitOfWorkProvider(); + var provider = new PetaPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); // Act - using (var repository = new MacroRepository(unitOfWork, NullCacheProvider.Current)) + using (var repository = new MacroRepository(unitOfWork, CacheHelper.CreateDisabledCacheHelper(), Mock.Of(), SqlSyntaxProvider)) { var macro = repository.Get(1); macro.Alias = "test2"; @@ -63,11 +66,11 @@ namespace Umbraco.Tests.Persistence.Repositories public void Can_Instantiate_Repository() { // Arrange - var provider = new PetaPocoUnitOfWorkProvider(); + var provider = new PetaPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); // Act - using (var repository = new MacroRepository(unitOfWork, NullCacheProvider.Current)) + using (var repository = new MacroRepository(unitOfWork, CacheHelper.CreateDisabledCacheHelper(), Mock.Of(), SqlSyntaxProvider)) { // Assert Assert.That(repository, Is.Not.Null); @@ -78,9 +81,9 @@ namespace Umbraco.Tests.Persistence.Repositories public void Can_Perform_Get_On_Repository() { // Arrange - var provider = new PetaPocoUnitOfWorkProvider(); + var provider = new PetaPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); - using (var repository = new MacroRepository(unitOfWork, NullCacheProvider.Current)) + using (var repository = new MacroRepository(unitOfWork, CacheHelper.CreateDisabledCacheHelper(), Mock.Of(), SqlSyntaxProvider)) { // Act var macro = repository.Get(1); @@ -108,9 +111,9 @@ namespace Umbraco.Tests.Persistence.Repositories public void Can_Perform_GetAll_On_Repository() { // Arrange - var provider = new PetaPocoUnitOfWorkProvider(); + var provider = new PetaPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); - using (var repository = new MacroRepository(unitOfWork, NullCacheProvider.Current)) + using (var repository = new MacroRepository(unitOfWork, CacheHelper.CreateDisabledCacheHelper(), Mock.Of(), SqlSyntaxProvider)) { // Act var macros = repository.GetAll(); @@ -125,9 +128,9 @@ namespace Umbraco.Tests.Persistence.Repositories public void Can_Perform_GetByQuery_On_Repository() { // Arrange - var provider = new PetaPocoUnitOfWorkProvider(); + var provider = new PetaPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); - using (var repository = new MacroRepository(unitOfWork, NullCacheProvider.Current)) + using (var repository = new MacroRepository(unitOfWork, CacheHelper.CreateDisabledCacheHelper(), Mock.Of(), SqlSyntaxProvider)) { // Act var query = Query.Builder.Where(x => x.Alias.ToUpper() == "TEST1"); @@ -142,9 +145,9 @@ namespace Umbraco.Tests.Persistence.Repositories public void Can_Perform_Count_On_Repository() { // Arrange - var provider = new PetaPocoUnitOfWorkProvider(); + var provider = new PetaPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); - using (var repository = new MacroRepository(unitOfWork, NullCacheProvider.Current)) + using (var repository = new MacroRepository(unitOfWork, CacheHelper.CreateDisabledCacheHelper(), Mock.Of(), SqlSyntaxProvider)) { // Act var query = Query.Builder.Where(x => x.Name.StartsWith("Test")); @@ -159,9 +162,9 @@ namespace Umbraco.Tests.Persistence.Repositories public void Can_Perform_Add_On_Repository() { // Arrange - var provider = new PetaPocoUnitOfWorkProvider(); + var provider = new PetaPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); - using (var repository = new MacroRepository(unitOfWork, NullCacheProvider.Current)) + using (var repository = new MacroRepository(unitOfWork, CacheHelper.CreateDisabledCacheHelper(), Mock.Of(), SqlSyntaxProvider)) { // Act var macro = new Macro("test", "Test", "~/usercontrol/blah.ascx", "MyAssembly", "test.xslt", "~/views/macropartials/test.cshtml"); @@ -180,9 +183,9 @@ namespace Umbraco.Tests.Persistence.Repositories public void Can_Perform_Update_On_Repository() { // Arrange - var provider = new PetaPocoUnitOfWorkProvider(); + var provider = new PetaPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); - using (var repository = new MacroRepository(unitOfWork, NullCacheProvider.Current)) + using (var repository = new MacroRepository(unitOfWork, CacheHelper.CreateDisabledCacheHelper(), Mock.Of(), SqlSyntaxProvider)) { // Act var macro = repository.Get(2); @@ -221,9 +224,9 @@ namespace Umbraco.Tests.Persistence.Repositories public void Can_Perform_Delete_On_Repository() { // Arrange - var provider = new PetaPocoUnitOfWorkProvider(); + var provider = new PetaPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); - using (var repository = new MacroRepository(unitOfWork, NullCacheProvider.Current)) + using (var repository = new MacroRepository(unitOfWork, CacheHelper.CreateDisabledCacheHelper(), Mock.Of(), SqlSyntaxProvider)) { // Act var macro = repository.Get(3); @@ -242,9 +245,9 @@ namespace Umbraco.Tests.Persistence.Repositories public void Can_Perform_Exists_On_Repository() { // Arrange - var provider = new PetaPocoUnitOfWorkProvider(); + var provider = new PetaPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); - using (var repository = new MacroRepository(unitOfWork, NullCacheProvider.Current)) + using (var repository = new MacroRepository(unitOfWork, CacheHelper.CreateDisabledCacheHelper(), Mock.Of(), SqlSyntaxProvider)) { // Act var exists = repository.Exists(3); @@ -260,9 +263,9 @@ namespace Umbraco.Tests.Persistence.Repositories public void Can_Add_Property_For_Macro() { // Arrange - var provider = new PetaPocoUnitOfWorkProvider(); + var provider = new PetaPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); - using (var repository = new MacroRepository(unitOfWork, NullCacheProvider.Current)) + using (var repository = new MacroRepository(unitOfWork, CacheHelper.CreateDisabledCacheHelper(), Mock.Of(), SqlSyntaxProvider)) { var macro = repository.Get(1); macro.Properties.Add(new MacroProperty("new1", "New1", 3, "test")); @@ -287,9 +290,9 @@ namespace Umbraco.Tests.Persistence.Repositories public void Can_Add_New_Macro_With_Property() { // Arrange - var provider = new PetaPocoUnitOfWorkProvider(); + var provider = new PetaPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); - using (var repository = new MacroRepository(unitOfWork, NullCacheProvider.Current)) + using (var repository = new MacroRepository(unitOfWork, CacheHelper.CreateDisabledCacheHelper(), Mock.Of(), SqlSyntaxProvider)) { var macro = new Macro("newmacro", "A new macro", "~/usercontrol/test1.ascx", "MyAssembly1", "test1.xslt", "~/views/macropartials/test1.cshtml"); macro.Properties.Add(new MacroProperty("blah1", "New1", 4, "test.editor")); @@ -312,9 +315,9 @@ namespace Umbraco.Tests.Persistence.Repositories public void Can_Remove_Macro_Property() { // Arrange - var provider = new PetaPocoUnitOfWorkProvider(); + var provider = new PetaPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); - using (var repository = new MacroRepository(unitOfWork, NullCacheProvider.Current)) + using (var repository = new MacroRepository(unitOfWork, CacheHelper.CreateDisabledCacheHelper(), Mock.Of(), SqlSyntaxProvider)) { var macro = new Macro("newmacro", "A new macro", "~/usercontrol/test1.ascx", "MyAssembly1", "test1.xslt", "~/views/macropartials/test1.cshtml"); macro.Properties.Add(new MacroProperty("blah1", "New1", 4, "test.editor")); @@ -337,9 +340,9 @@ namespace Umbraco.Tests.Persistence.Repositories public void Can_Add_Remove_Macro_Properties() { // Arrange - var provider = new PetaPocoUnitOfWorkProvider(); + var provider = new PetaPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); - using (var repository = new MacroRepository(unitOfWork, NullCacheProvider.Current)) + using (var repository = new MacroRepository(unitOfWork, CacheHelper.CreateDisabledCacheHelper(), Mock.Of(), SqlSyntaxProvider)) { var macro = new Macro("newmacro", "A new macro", "~/usercontrol/test1.ascx", "MyAssembly1", "test1.xslt", "~/views/macropartials/test1.cshtml"); var prop1 = new MacroProperty("blah1", "New1", 4, "test.editor"); @@ -368,9 +371,9 @@ namespace Umbraco.Tests.Persistence.Repositories public void Can_Update_Property_For_Macro() { // Arrange - var provider = new PetaPocoUnitOfWorkProvider(); + var provider = new PetaPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); - using (var repository = new MacroRepository(unitOfWork, NullCacheProvider.Current)) + using (var repository = new MacroRepository(unitOfWork, CacheHelper.CreateDisabledCacheHelper(), Mock.Of(), SqlSyntaxProvider)) { var macro = repository.Get(1); macro.Properties.Add(new MacroProperty("new1", "New1", 3, "test")); @@ -396,9 +399,9 @@ namespace Umbraco.Tests.Persistence.Repositories public void Can_Update_Macro_Property_Alias() { // Arrange - var provider = new PetaPocoUnitOfWorkProvider(); + var provider = new PetaPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); - using (var repository = new MacroRepository(unitOfWork, NullCacheProvider.Current)) + using (var repository = new MacroRepository(unitOfWork, CacheHelper.CreateDisabledCacheHelper(), Mock.Of(), SqlSyntaxProvider)) { var macro = repository.Get(1); macro.Properties.Add(new MacroProperty("new1", "New1", 3, "test")); @@ -425,9 +428,9 @@ namespace Umbraco.Tests.Persistence.Repositories public void CreateTestData() { - var provider = new PetaPocoUnitOfWorkProvider(); + var provider = new PetaPocoUnitOfWorkProvider(Logger); using (var unitOfWork = provider.GetUnitOfWork()) - using (var repository = new MacroRepository(unitOfWork)) + using (var repository = new MacroRepository(unitOfWork, CacheHelper.CreateDisabledCacheHelper(), Mock.Of(), SqlSyntaxProvider)) { repository.AddOrUpdate(new Macro("test1", "Test1", "~/usercontrol/test1.ascx", "MyAssembly1", "test1.xslt", "~/views/macropartials/test1.cshtml")); repository.AddOrUpdate(new Macro("test2", "Test2", "~/usercontrol/test2.ascx", "MyAssembly2", "test2.xslt", "~/views/macropartials/test2.cshtml")); diff --git a/src/Umbraco.Tests/Persistence/Repositories/MediaRepositoryTest.cs b/src/Umbraco.Tests/Persistence/Repositories/MediaRepositoryTest.cs index d99cd5b682..60113dd660 100644 --- a/src/Umbraco.Tests/Persistence/Repositories/MediaRepositoryTest.cs +++ b/src/Umbraco.Tests/Persistence/Repositories/MediaRepositoryTest.cs @@ -1,12 +1,14 @@ using System; using System.Linq; using System.Xml.Linq; +using Moq; using NUnit.Framework; +using Umbraco.Core.Logging; using Umbraco.Core.Models; using Umbraco.Core.Models.EntityBase; using Umbraco.Core.Models.Rdbms; using Umbraco.Core.Persistence; -using Umbraco.Core.Persistence.Caching; + using Umbraco.Core.Persistence.Querying; using Umbraco.Core.Persistence.Repositories; using Umbraco.Core.Persistence.UnitOfWork; @@ -20,6 +22,10 @@ namespace Umbraco.Tests.Persistence.Repositories [TestFixture] public class MediaRepositoryTest : BaseDatabaseFactoryTest { + public MediaRepositoryTest() + { + } + [SetUp] public override void Initialize() { @@ -30,16 +36,16 @@ namespace Umbraco.Tests.Persistence.Repositories private MediaRepository CreateRepository(IDatabaseUnitOfWork unitOfWork, out MediaTypeRepository mediaTypeRepository) { - mediaTypeRepository = new MediaTypeRepository(unitOfWork, NullCacheProvider.Current); - var tagRepository = new TagRepository(unitOfWork, NullCacheProvider.Current); - var repository = new MediaRepository(unitOfWork, NullCacheProvider.Current, mediaTypeRepository, tagRepository); + mediaTypeRepository = new MediaTypeRepository(unitOfWork, CacheHelper.CreateDisabledCacheHelper(), Mock.Of(), SqlSyntaxProvider); + var tagRepository = new TagRepository(unitOfWork, CacheHelper.CreateDisabledCacheHelper(), Mock.Of(), SqlSyntaxProvider); + var repository = new MediaRepository(unitOfWork, CacheHelper.CreateDisabledCacheHelper(), Mock.Of(), SqlSyntaxProvider, mediaTypeRepository, tagRepository); return repository; } [Test] public void Rebuild_All_Xml_Structures() { - var provider = new PetaPocoUnitOfWorkProvider(); + var provider = new PetaPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); MediaTypeRepository mediaTypeRepository; using (var repository = CreateRepository(unitOfWork, out mediaTypeRepository)) @@ -67,7 +73,7 @@ namespace Umbraco.Tests.Persistence.Repositories [Test] public void Rebuild_All_Xml_Structures_For_Content_Type() { - var provider = new PetaPocoUnitOfWorkProvider(); + var provider = new PetaPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); MediaTypeRepository mediaTypeRepository; using (var repository = CreateRepository(unitOfWork, out mediaTypeRepository)) @@ -103,26 +109,12 @@ namespace Umbraco.Tests.Persistence.Repositories Assert.AreEqual(62, unitOfWork.Database.ExecuteScalar("SELECT COUNT(*) FROM cmsContentXml")); } } - - [Test] - public void Can_Instantiate_Repository_From_Resolver() - { - // Arrange - var provider = new PetaPocoUnitOfWorkProvider(); - var unitOfWork = provider.GetUnitOfWork(); - - // Act - var repository = RepositoryResolver.Current.ResolveByType(unitOfWork); - - // Assert - Assert.That(repository, Is.Not.Null); - } - + [Test] public void Can_Perform_Add_On_MediaRepository() { // Arrange - var provider = new PetaPocoUnitOfWorkProvider(); + var provider = new PetaPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); MediaTypeRepository mediaTypeRepository; using (var repository = CreateRepository(unitOfWork, out mediaTypeRepository)) @@ -146,7 +138,7 @@ namespace Umbraco.Tests.Persistence.Repositories public void Can_Perform_Multiple_Adds_On_MediaRepository() { // Arrange - var provider = new PetaPocoUnitOfWorkProvider(); + var provider = new PetaPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); MediaTypeRepository mediaTypeRepository; using (var repository = CreateRepository(unitOfWork, out mediaTypeRepository)) @@ -177,7 +169,7 @@ namespace Umbraco.Tests.Persistence.Repositories public void Can_Perform_Multiple_Adds_On_MediaRepository_With_RepositoryResolver() { // Arrange - var provider = new PetaPocoUnitOfWorkProvider(); + var provider = new PetaPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); MediaTypeRepository mediaTypeRepository; using (var repository = CreateRepository(unitOfWork, out mediaTypeRepository)) @@ -208,7 +200,7 @@ namespace Umbraco.Tests.Persistence.Repositories public void Can_Verify_Fresh_Entity_Is_Not_Dirty() { // Arrange - var provider = new PetaPocoUnitOfWorkProvider(); + var provider = new PetaPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); MediaTypeRepository mediaTypeRepository; using (var repository = CreateRepository(unitOfWork, out mediaTypeRepository)) @@ -227,7 +219,7 @@ namespace Umbraco.Tests.Persistence.Repositories public void Can_Perform_Update_On_MediaRepository() { // Arrange - var provider = new PetaPocoUnitOfWorkProvider(); + var provider = new PetaPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); MediaTypeRepository mediaTypeRepository; using (var repository = CreateRepository(unitOfWork, out mediaTypeRepository)) @@ -251,7 +243,7 @@ namespace Umbraco.Tests.Persistence.Repositories public void Can_Perform_Delete_On_MediaRepository() { // Arrange - var provider = new PetaPocoUnitOfWorkProvider(); + var provider = new PetaPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); MediaTypeRepository mediaTypeRepository; using (var repository = CreateRepository(unitOfWork, out mediaTypeRepository)) @@ -275,7 +267,7 @@ namespace Umbraco.Tests.Persistence.Repositories public void Can_Perform_Get_On_MediaRepository() { // Arrange - var provider = new PetaPocoUnitOfWorkProvider(); + var provider = new PetaPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); MediaTypeRepository mediaTypeRepository; using (var repository = CreateRepository(unitOfWork, out mediaTypeRepository)) @@ -302,7 +294,7 @@ namespace Umbraco.Tests.Persistence.Repositories public void Can_Perform_GetByQuery_On_MediaRepository() { // Arrange - var provider = new PetaPocoUnitOfWorkProvider(); + var provider = new PetaPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); MediaTypeRepository mediaTypeRepository; using (var repository = CreateRepository(unitOfWork, out mediaTypeRepository)) @@ -320,7 +312,7 @@ namespace Umbraco.Tests.Persistence.Repositories public void Can_Perform_GetPagedResultsByQuery_ForFirstPage_On_MediaRepository() { // Arrange - var provider = new PetaPocoUnitOfWorkProvider(); + var provider = new PetaPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); MediaTypeRepository mediaTypeRepository; using (var repository = CreateRepository(unitOfWork, out mediaTypeRepository)) @@ -341,7 +333,7 @@ namespace Umbraco.Tests.Persistence.Repositories public void Can_Perform_GetPagedResultsByQuery_ForSecondPage_On_MediaRepository() { // Arrange - var provider = new PetaPocoUnitOfWorkProvider(); + var provider = new PetaPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); MediaTypeRepository mediaTypeRepository; using (var repository = CreateRepository(unitOfWork, out mediaTypeRepository)) @@ -362,7 +354,7 @@ namespace Umbraco.Tests.Persistence.Repositories public void Can_Perform_GetPagedResultsByQuery_WithSinglePage_On_MediaRepository() { // Arrange - var provider = new PetaPocoUnitOfWorkProvider(); + var provider = new PetaPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); MediaTypeRepository mediaTypeRepository; using (var repository = CreateRepository(unitOfWork, out mediaTypeRepository)) @@ -383,7 +375,7 @@ namespace Umbraco.Tests.Persistence.Repositories public void Can_Perform_GetPagedResultsByQuery_WithDescendingOrder_On_MediaRepository() { // Arrange - var provider = new PetaPocoUnitOfWorkProvider(); + var provider = new PetaPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); MediaTypeRepository mediaTypeRepository; using (var repository = CreateRepository(unitOfWork, out mediaTypeRepository)) @@ -404,7 +396,7 @@ namespace Umbraco.Tests.Persistence.Repositories public void Can_Perform_GetPagedResultsByQuery_WitAlternateOrder_On_MediaRepository() { // Arrange - var provider = new PetaPocoUnitOfWorkProvider(); + var provider = new PetaPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); MediaTypeRepository mediaTypeRepository; using (var repository = CreateRepository(unitOfWork, out mediaTypeRepository)) @@ -425,7 +417,7 @@ namespace Umbraco.Tests.Persistence.Repositories public void Can_Perform_GetPagedResultsByQuery_WithFilterMatchingSome_On_MediaRepository() { // Arrange - var provider = new PetaPocoUnitOfWorkProvider(); + var provider = new PetaPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); MediaTypeRepository mediaTypeRepository; using (var repository = CreateRepository(unitOfWork, out mediaTypeRepository)) @@ -446,7 +438,7 @@ namespace Umbraco.Tests.Persistence.Repositories public void Can_Perform_GetPagedResultsByQuery_WithFilterMatchingAll_On_MediaRepository() { // Arrange - var provider = new PetaPocoUnitOfWorkProvider(); + var provider = new PetaPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); MediaTypeRepository mediaTypeRepository; using (var repository = CreateRepository(unitOfWork, out mediaTypeRepository)) @@ -467,7 +459,7 @@ namespace Umbraco.Tests.Persistence.Repositories public void Can_Perform_GetAll_By_Param_Ids_On_MediaRepository() { // Arrange - var provider = new PetaPocoUnitOfWorkProvider(); + var provider = new PetaPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); MediaTypeRepository mediaTypeRepository; using (var repository = CreateRepository(unitOfWork, out mediaTypeRepository)) @@ -487,7 +479,7 @@ namespace Umbraco.Tests.Persistence.Repositories public void Can_Perform_GetAll_On_MediaRepository() { // Arrange - var provider = new PetaPocoUnitOfWorkProvider(); + var provider = new PetaPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); MediaTypeRepository mediaTypeRepository; using (var repository = CreateRepository(unitOfWork, out mediaTypeRepository)) @@ -507,7 +499,7 @@ namespace Umbraco.Tests.Persistence.Repositories public void Can_Perform_Exists_On_MediaRepository() { // Arrange - var provider = new PetaPocoUnitOfWorkProvider(); + var provider = new PetaPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); MediaTypeRepository mediaTypeRepository; using (var repository = CreateRepository(unitOfWork, out mediaTypeRepository)) @@ -529,7 +521,7 @@ namespace Umbraco.Tests.Persistence.Repositories public void Can_Perform_Count_On_MediaRepository() { // Arrange - var provider = new PetaPocoUnitOfWorkProvider(); + var provider = new PetaPocoUnitOfWorkProvider(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 cbf809fc12..7ad3bb59f9 100644 --- a/src/Umbraco.Tests/Persistence/Repositories/MediaTypeRepositoryTest.cs +++ b/src/Umbraco.Tests/Persistence/Repositories/MediaTypeRepositoryTest.cs @@ -1,12 +1,15 @@ using System; using System.Linq; +using Moq; using NUnit.Framework; using Umbraco.Core; +using Umbraco.Core.Logging; using Umbraco.Core.Models; using Umbraco.Core.Models.Rdbms; using Umbraco.Core.Persistence; -using Umbraco.Core.Persistence.Caching; + using Umbraco.Core.Persistence.Repositories; +using Umbraco.Core.Persistence.SqlSyntax; using Umbraco.Core.Persistence.UnitOfWork; using Umbraco.Tests.TestHelpers; using Umbraco.Tests.TestHelpers.Entities; @@ -25,28 +28,14 @@ namespace Umbraco.Tests.Persistence.Repositories private MediaTypeRepository CreateRepository(IDatabaseUnitOfWork unitOfWork) { - return new MediaTypeRepository(unitOfWork, NullCacheProvider.Current); - } - - [Test] - public void Can_Instantiate_Repository_From_Resolver() - { - // Arrange - var provider = new PetaPocoUnitOfWorkProvider(); - var unitOfWork = provider.GetUnitOfWork(); - - // Act - var repository = RepositoryResolver.Current.ResolveByType(unitOfWork); - - // Assert - Assert.That(repository, Is.Not.Null); + return new MediaTypeRepository(unitOfWork, CacheHelper.CreateDisabledCacheHelper(), Mock.Of(), SqlSyntaxProvider); } [Test] public void Can_Perform_Add_On_MediaTypeRepository() { // Arrange - var provider = new PetaPocoUnitOfWorkProvider(); + var provider = new PetaPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); using (var repository = CreateRepository(unitOfWork)) { @@ -69,7 +58,7 @@ namespace Umbraco.Tests.Persistence.Repositories public void Can_Perform_Update_On_MediaTypeRepository() { // Arrange - var provider = new PetaPocoUnitOfWorkProvider(); + var provider = new PetaPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); using (var repository = CreateRepository(unitOfWork)) { @@ -108,7 +97,7 @@ namespace Umbraco.Tests.Persistence.Repositories public void Can_Perform_Delete_On_MediaTypeRepository() { // Arrange - var provider = new PetaPocoUnitOfWorkProvider(); + var provider = new PetaPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); using (var repository = CreateRepository(unitOfWork)) { @@ -133,7 +122,7 @@ namespace Umbraco.Tests.Persistence.Repositories public void Can_Perform_Get_On_MediaTypeRepository() { // Arrange - var provider = new PetaPocoUnitOfWorkProvider(); + var provider = new PetaPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); using (var repository = CreateRepository(unitOfWork)) { @@ -152,7 +141,7 @@ namespace Umbraco.Tests.Persistence.Repositories public void Can_Perform_GetAll_On_MediaTypeRepository() { // Arrange - var provider = new PetaPocoUnitOfWorkProvider(); + var provider = new PetaPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); using (var repository = CreateRepository(unitOfWork)) { @@ -173,7 +162,7 @@ namespace Umbraco.Tests.Persistence.Repositories public void Can_Perform_Exists_On_MediaTypeRepository() { // Arrange - var provider = new PetaPocoUnitOfWorkProvider(); + var provider = new PetaPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); using (var repository = CreateRepository(unitOfWork)) { @@ -190,7 +179,7 @@ namespace Umbraco.Tests.Persistence.Repositories public void Can_Update_MediaType_With_PropertyType_Removed() { // Arrange - var provider = new PetaPocoUnitOfWorkProvider(); + var provider = new PetaPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); using (var repository = CreateRepository(unitOfWork)) { @@ -217,7 +206,7 @@ namespace Umbraco.Tests.Persistence.Repositories public void Can_Verify_PropertyTypes_On_Video_MediaType() { // Arrange - var provider = new PetaPocoUnitOfWorkProvider(); + var provider = new PetaPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); using (var repository = CreateRepository(unitOfWork)) { @@ -238,7 +227,7 @@ namespace Umbraco.Tests.Persistence.Repositories public void Can_Verify_PropertyTypes_On_File_MediaType() { // Arrange - var provider = new PetaPocoUnitOfWorkProvider(); + var provider = new PetaPocoUnitOfWorkProvider(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 dec18ef4e5..c8be935f36 100644 --- a/src/Umbraco.Tests/Persistence/Repositories/MemberRepositoryTest.cs +++ b/src/Umbraco.Tests/Persistence/Repositories/MemberRepositoryTest.cs @@ -1,12 +1,14 @@ using System; using System.Linq; using System.Xml.Linq; +using Moq; using NUnit.Framework; using Umbraco.Core; +using Umbraco.Core.Logging; using Umbraco.Core.Models; using Umbraco.Core.Models.Rdbms; using Umbraco.Core.Persistence; -using Umbraco.Core.Persistence.Caching; + using Umbraco.Core.Persistence.Querying; using Umbraco.Core.Persistence.Repositories; using Umbraco.Core.Persistence.UnitOfWork; @@ -33,17 +35,17 @@ namespace Umbraco.Tests.Persistence.Repositories private MemberRepository CreateRepository(IDatabaseUnitOfWork unitOfWork, out MemberTypeRepository memberTypeRepository, out MemberGroupRepository memberGroupRepository) { - memberTypeRepository = new MemberTypeRepository(unitOfWork, NullCacheProvider.Current); - memberGroupRepository = new MemberGroupRepository(unitOfWork, NullCacheProvider.Current, CacheHelper.CreateDisabledCacheHelper()); - var tagRepo = new TagRepository(unitOfWork, NullCacheProvider.Current); - var repository = new MemberRepository(unitOfWork, NullCacheProvider.Current, memberTypeRepository, memberGroupRepository, tagRepo); + memberTypeRepository = new MemberTypeRepository(unitOfWork, CacheHelper.CreateDisabledCacheHelper(), Mock.Of(), SqlSyntaxProvider); + memberGroupRepository = new MemberGroupRepository(unitOfWork, CacheHelper.CreateDisabledCacheHelper(), Mock.Of(), SqlSyntaxProvider, CacheHelper.CreateDisabledCacheHelper()); + var tagRepo = new TagRepository(unitOfWork, CacheHelper.CreateDisabledCacheHelper(), Mock.Of(), SqlSyntaxProvider); + var repository = new MemberRepository(unitOfWork, CacheHelper.CreateDisabledCacheHelper(), Mock.Of(), SqlSyntaxProvider, memberTypeRepository, memberGroupRepository, tagRepo); return repository; } [Test] public void Rebuild_All_Xml_Structures() { - var provider = new PetaPocoUnitOfWorkProvider(); + var provider = new PetaPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); MemberTypeRepository memberTypeRepository; MemberGroupRepository memberGroupRepository; @@ -71,7 +73,7 @@ namespace Umbraco.Tests.Persistence.Repositories [Test] public void Rebuild_All_Xml_Structures_For_Content_Type() { - var provider = new PetaPocoUnitOfWorkProvider(); + var provider = new PetaPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); MemberTypeRepository memberTypeRepository; MemberGroupRepository memberGroupRepository; @@ -110,24 +112,11 @@ namespace Umbraco.Tests.Persistence.Repositories } - [Test] - public void Can_Instantiate_Repository_From_Resolver() - { - // Arrange - var provider = new PetaPocoUnitOfWorkProvider(); - var unitOfWork = provider.GetUnitOfWork(); - - // Act - var repository = RepositoryResolver.Current.ResolveByType(unitOfWork); - - // Assert - Assert.That(repository, Is.Not.Null); - } [Test] public void MemberRepository_Can_Get_Member_By_Id() { - var provider = new PetaPocoUnitOfWorkProvider(); + var provider = new PetaPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); MemberTypeRepository memberTypeRepository; MemberGroupRepository memberGroupRepository; @@ -145,7 +134,7 @@ namespace Umbraco.Tests.Persistence.Repositories [Test] public void Can_Get_Members_By_Ids() { - var provider = new PetaPocoUnitOfWorkProvider(); + var provider = new PetaPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); MemberTypeRepository memberTypeRepository; MemberGroupRepository memberGroupRepository; @@ -167,7 +156,7 @@ namespace Umbraco.Tests.Persistence.Repositories [Test] public void MemberRepository_Can_Get_All_Members() { - var provider = new PetaPocoUnitOfWorkProvider(); + var provider = new PetaPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); MemberTypeRepository memberTypeRepository; MemberGroupRepository memberGroupRepository; @@ -192,7 +181,7 @@ namespace Umbraco.Tests.Persistence.Repositories public void MemberRepository_Can_Perform_GetByQuery_With_Key() { // Arrange - var provider = new PetaPocoUnitOfWorkProvider(); + var provider = new PetaPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); MemberTypeRepository memberTypeRepository; MemberGroupRepository memberGroupRepository; @@ -214,7 +203,7 @@ namespace Umbraco.Tests.Persistence.Repositories [Test] public void Can_Persist_Member() { - var provider = new PetaPocoUnitOfWorkProvider(); + var provider = new PetaPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); MemberTypeRepository memberTypeRepository; MemberGroupRepository memberGroupRepository; @@ -237,7 +226,7 @@ namespace Umbraco.Tests.Persistence.Repositories [Test] public void New_Member_Has_Built_In_Properties_By_Default() { - var provider = new PetaPocoUnitOfWorkProvider(); + var provider = new PetaPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); MemberTypeRepository memberTypeRepository; MemberGroupRepository memberGroupRepository; @@ -271,7 +260,7 @@ namespace Umbraco.Tests.Persistence.Repositories public void MemberRepository_Does_Not_Replace_Password_When_Null() { IMember sut; - var provider = new PetaPocoUnitOfWorkProvider(); + var provider = new PetaPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); MemberTypeRepository memberTypeRepository; MemberGroupRepository memberGroupRepository; @@ -300,7 +289,7 @@ namespace Umbraco.Tests.Persistence.Repositories public void MemberRepository_Can_Update_Email_And_Login_When_Changed() { IMember sut; - var provider = new PetaPocoUnitOfWorkProvider(); + var provider = new PetaPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); MemberTypeRepository memberTypeRepository; MemberGroupRepository memberGroupRepository; @@ -347,7 +336,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(); + var provider = new PetaPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); MemberTypeRepository memberTypeRepository; MemberGroupRepository memberGroupRepository; @@ -370,7 +359,7 @@ namespace Umbraco.Tests.Persistence.Repositories private IMemberType CreateTestMemberType(string alias = null) { - var provider = new PetaPocoUnitOfWorkProvider(); + var provider = new PetaPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); MemberTypeRepository memberTypeRepository; MemberGroupRepository memberGroupRepository; diff --git a/src/Umbraco.Tests/Persistence/Repositories/MemberTypeRepositoryTest.cs b/src/Umbraco.Tests/Persistence/Repositories/MemberTypeRepositoryTest.cs index 5eb452d720..2ec84225b5 100644 --- a/src/Umbraco.Tests/Persistence/Repositories/MemberTypeRepositoryTest.cs +++ b/src/Umbraco.Tests/Persistence/Repositories/MemberTypeRepositoryTest.cs @@ -1,10 +1,12 @@ using System; 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.Caching; + using Umbraco.Core.Persistence.Repositories; using Umbraco.Core.Persistence.UnitOfWork; using Umbraco.Tests.TestHelpers; @@ -30,27 +32,13 @@ namespace Umbraco.Tests.Persistence.Repositories private MemberTypeRepository CreateRepository(IDatabaseUnitOfWork unitOfWork) { - return new MemberTypeRepository(unitOfWork, NullCacheProvider.Current); - } - - [Test] - public void Can_Instantiate_Repository_From_Resolver() - { - // Arrange - var provider = new PetaPocoUnitOfWorkProvider(); - var unitOfWork = provider.GetUnitOfWork(); - - // Act - var repository = RepositoryResolver.Current.ResolveByType(unitOfWork); - - // Assert - Assert.That(repository, Is.Not.Null); + return new MemberTypeRepository(unitOfWork, CacheHelper.CreateDisabledCacheHelper(), Mock.Of(), SqlSyntaxProvider); } [Test] public void Can_Persist_Member_Type() { - var provider = new PetaPocoUnitOfWorkProvider(); + var provider = new PetaPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); using (var repository = CreateRepository(unitOfWork)) { @@ -74,7 +62,7 @@ namespace Umbraco.Tests.Persistence.Repositories [Test] public void Cannot_Persist_Member_Type_Without_Alias() { - var provider = new PetaPocoUnitOfWorkProvider(); + var provider = new PetaPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); using (var repository = CreateRepository(unitOfWork)) { @@ -89,7 +77,7 @@ namespace Umbraco.Tests.Persistence.Repositories [Test] public void Can_Get_All_Member_Types() { - var provider = new PetaPocoUnitOfWorkProvider(); + var provider = new PetaPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); using (var repository = CreateRepository(unitOfWork)) { @@ -114,7 +102,7 @@ namespace Umbraco.Tests.Persistence.Repositories [Test] public void Can_Get_All_Members_When_No_Properties_Assigned() { - var provider = new PetaPocoUnitOfWorkProvider(); + var provider = new PetaPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); using (var repository = CreateRepository(unitOfWork)) { @@ -140,7 +128,7 @@ namespace Umbraco.Tests.Persistence.Repositories [Test] public void Can_Get_Member_Type_By_Id() { - var provider = new PetaPocoUnitOfWorkProvider(); + var provider = new PetaPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); using (var repository = CreateRepository(unitOfWork)) { @@ -155,7 +143,7 @@ namespace Umbraco.Tests.Persistence.Repositories [Test] public void Built_In_Member_Type_Properties_Are_Automatically_Added_When_Creating() { - var provider = new PetaPocoUnitOfWorkProvider(); + var provider = new PetaPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); using (var repository = CreateRepository(unitOfWork)) { @@ -175,7 +163,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(); + var provider = new PetaPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); using (var repository = CreateRepository(unitOfWork)) { @@ -196,7 +184,7 @@ namespace Umbraco.Tests.Persistence.Repositories public void Can_Delete_MemberType() { // Arrange - var provider = new PetaPocoUnitOfWorkProvider(); + var provider = new PetaPocoUnitOfWorkProvider(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 c718c2c288..54387a03f9 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(); + var provider = new PetaPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); var repo = new NotificationsRepository(unitOfWork); @@ -40,7 +40,7 @@ namespace Umbraco.Tests.Persistence.Repositories [Test] public void GetUserNotifications() { - var provider = new PetaPocoUnitOfWorkProvider(); + var provider = new PetaPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); var repo = new NotificationsRepository(unitOfWork); @@ -66,7 +66,7 @@ namespace Umbraco.Tests.Persistence.Repositories [Test] public void GetEntityNotifications() { - var provider = new PetaPocoUnitOfWorkProvider(); + var provider = new PetaPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); var repo = new NotificationsRepository(unitOfWork); @@ -93,7 +93,7 @@ namespace Umbraco.Tests.Persistence.Repositories [Test] public void Delete_By_Entity() { - var provider = new PetaPocoUnitOfWorkProvider(); + var provider = new PetaPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); var repo = new NotificationsRepository(unitOfWork); @@ -120,7 +120,7 @@ namespace Umbraco.Tests.Persistence.Repositories [Test] public void Delete_By_User() { - var provider = new PetaPocoUnitOfWorkProvider(); + var provider = new PetaPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); var repo = new NotificationsRepository(unitOfWork); diff --git a/src/Umbraco.Tests/Persistence/Repositories/RelationRepositoryTest.cs b/src/Umbraco.Tests/Persistence/Repositories/RelationRepositoryTest.cs index 18dd4e0686..1c41460219 100644 --- a/src/Umbraco.Tests/Persistence/Repositories/RelationRepositoryTest.cs +++ b/src/Umbraco.Tests/Persistence/Repositories/RelationRepositoryTest.cs @@ -1,11 +1,13 @@ using System; using System.Linq; +using Moq; using NUnit.Framework; using Umbraco.Core; +using Umbraco.Core.Logging; using Umbraco.Core.Models; using Umbraco.Core.Models.Rdbms; using Umbraco.Core.Persistence; -using Umbraco.Core.Persistence.Caching; + using Umbraco.Core.Persistence.Querying; using Umbraco.Core.Persistence.Repositories; using Umbraco.Core.Persistence.UnitOfWork; @@ -28,30 +30,16 @@ namespace Umbraco.Tests.Persistence.Repositories private RelationRepository CreateRepository(IDatabaseUnitOfWork unitOfWork, out RelationTypeRepository relationTypeRepository) { - relationTypeRepository = new RelationTypeRepository(unitOfWork, NullCacheProvider.Current); - var repository = new RelationRepository(unitOfWork, NullCacheProvider.Current, relationTypeRepository); + relationTypeRepository = new RelationTypeRepository(unitOfWork, CacheHelper.CreateDisabledCacheHelper(), Mock.Of(), SqlSyntaxProvider); + var repository = new RelationRepository(unitOfWork, CacheHelper.CreateDisabledCacheHelper(), Mock.Of(), SqlSyntaxProvider, relationTypeRepository); return repository; } - [Test] - public void Can_Instantiate_Repository_From_Resolver() - { - // Arrange - var provider = new PetaPocoUnitOfWorkProvider(); - var unitOfWork = provider.GetUnitOfWork(); - - // Act - var repository = RepositoryResolver.Current.ResolveByType(unitOfWork); - - // Assert - Assert.That(repository, Is.Not.Null); - } - [Test] public void Can_Perform_Add_On_RelationRepository() { // Arrange - var provider = new PetaPocoUnitOfWorkProvider(); + var provider = new PetaPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); RelationTypeRepository repositoryType; using (var repository = CreateRepository(unitOfWork, out repositoryType)) @@ -73,7 +61,7 @@ namespace Umbraco.Tests.Persistence.Repositories public void Can_Perform_Update_On_RelationRepository() { // Arrange - var provider = new PetaPocoUnitOfWorkProvider(); + var provider = new PetaPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); RelationTypeRepository repositoryType; using (var repository = CreateRepository(unitOfWork, out repositoryType)) @@ -98,7 +86,7 @@ namespace Umbraco.Tests.Persistence.Repositories public void Can_Perform_Delete_On_RelationRepository() { // Arrange - var provider = new PetaPocoUnitOfWorkProvider(); + var provider = new PetaPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); RelationTypeRepository repositoryType; using (var repository = CreateRepository(unitOfWork, out repositoryType)) @@ -120,7 +108,7 @@ namespace Umbraco.Tests.Persistence.Repositories public void Can_Perform_Get_On_RelationRepository() { // Arrange - var provider = new PetaPocoUnitOfWorkProvider(); + var provider = new PetaPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); RelationTypeRepository repositoryType; using (var repository = CreateRepository(unitOfWork, out repositoryType)) @@ -142,7 +130,7 @@ namespace Umbraco.Tests.Persistence.Repositories public void Can_Perform_GetAll_On_RelationRepository() { // Arrange - var provider = new PetaPocoUnitOfWorkProvider(); + var provider = new PetaPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); RelationTypeRepository repositoryType; using (var repository = CreateRepository(unitOfWork, out repositoryType)) @@ -163,7 +151,7 @@ namespace Umbraco.Tests.Persistence.Repositories public void Can_Perform_GetAll_With_Params_On_RelationRepository() { // Arrange - var provider = new PetaPocoUnitOfWorkProvider(); + var provider = new PetaPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); RelationTypeRepository repositoryType; using (var repository = CreateRepository(unitOfWork, out repositoryType)) @@ -184,7 +172,7 @@ namespace Umbraco.Tests.Persistence.Repositories public void Can_Perform_Exists_On_RelationRepository() { // Arrange - var provider = new PetaPocoUnitOfWorkProvider(); + var provider = new PetaPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); RelationTypeRepository repositoryType; using (var repository = CreateRepository(unitOfWork, out repositoryType)) @@ -204,7 +192,7 @@ namespace Umbraco.Tests.Persistence.Repositories public void Can_Perform_Count_On_RelationRepository() { // Arrange - var provider = new PetaPocoUnitOfWorkProvider(); + var provider = new PetaPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); RelationTypeRepository repositoryType; using (var repository = CreateRepository(unitOfWork, out repositoryType)) @@ -223,14 +211,14 @@ namespace Umbraco.Tests.Persistence.Repositories public void Can_Perform_GetByQuery_On_RelationRepository() { // Arrange - var provider = new PetaPocoUnitOfWorkProvider(); + var provider = new PetaPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); RelationTypeRepository repositoryType; using (var repository = CreateRepository(unitOfWork, out repositoryType)) { - + // Act - var query = Query.Builder.Where(x => x.RelationTypeId == 2); + var query = Query.Builder.Where(x => x.RelationTypeId == RelationTypeDto.NodeIdSeed); var relations = repository.GetByQuery(query); // Assert @@ -245,7 +233,7 @@ namespace Umbraco.Tests.Persistence.Repositories public void Can_Delete_Content_And_Verify_Relation_Is_Removed() { // Arrange - var provider = new PetaPocoUnitOfWorkProvider(); + var provider = new PetaPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); RelationTypeRepository repositoryType; using (var repository = CreateRepository(unitOfWork, out repositoryType)) @@ -275,10 +263,10 @@ 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(); + var provider = new PetaPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); - var relationTypeRepository = new RelationTypeRepository(unitOfWork); - var relationRepository = new RelationRepository(unitOfWork, NullCacheProvider.Current, relationTypeRepository); + var relationTypeRepository = new RelationTypeRepository(unitOfWork, CacheHelper.CreateDisabledCacheHelper(), Mock.Of(), SqlSyntaxProvider); + var relationRepository = new RelationRepository(unitOfWork, CacheHelper.CreateDisabledCacheHelper(), Mock.Of(), SqlSyntaxProvider, relationTypeRepository); relationTypeRepository.AddOrUpdate(relateContent); relationTypeRepository.AddOrUpdate(relateContentType); diff --git a/src/Umbraco.Tests/Persistence/Repositories/RelationTypeRepositoryTest.cs b/src/Umbraco.Tests/Persistence/Repositories/RelationTypeRepositoryTest.cs index 1c92f11802..15bf31291d 100644 --- a/src/Umbraco.Tests/Persistence/Repositories/RelationTypeRepositoryTest.cs +++ b/src/Umbraco.Tests/Persistence/Repositories/RelationTypeRepositoryTest.cs @@ -1,10 +1,13 @@ using System; using System.Linq; +using Moq; using NUnit.Framework; using Umbraco.Core; +using Umbraco.Core.Logging; using Umbraco.Core.Models; +using Umbraco.Core.Models.Rdbms; using Umbraco.Core.Persistence; -using Umbraco.Core.Persistence.Caching; + using Umbraco.Core.Persistence.Querying; using Umbraco.Core.Persistence.Repositories; using Umbraco.Core.Persistence.UnitOfWork; @@ -26,28 +29,15 @@ namespace Umbraco.Tests.Persistence.Repositories private RelationTypeRepository CreateRepository(IDatabaseUnitOfWork unitOfWork) { - return new RelationTypeRepository(unitOfWork, NullCacheProvider.Current); + return new RelationTypeRepository(unitOfWork, CacheHelper.CreateDisabledCacheHelper(), Mock.Of(), SqlSyntaxProvider); } - [Test] - public void Can_Instantiate_Repository_From_Resolver() - { - // Arrange - var provider = new PetaPocoUnitOfWorkProvider(); - var unitOfWork = provider.GetUnitOfWork(); - - // Act - var repository = RepositoryResolver.Current.ResolveByType(unitOfWork); - - // Assert - Assert.That(repository, Is.Not.Null); - } [Test] public void Can_Perform_Add_On_RelationTypeRepository() { // Arrange - var provider = new PetaPocoUnitOfWorkProvider(); + var provider = new PetaPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); using (var repository = CreateRepository(unitOfWork)) { @@ -70,7 +60,7 @@ namespace Umbraco.Tests.Persistence.Repositories public void Can_Perform_Update_On_RelationTypeRepository() { // Arrange - var provider = new PetaPocoUnitOfWorkProvider(); + var provider = new PetaPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); using (var repository = CreateRepository(unitOfWork)) { @@ -96,7 +86,7 @@ namespace Umbraco.Tests.Persistence.Repositories public void Can_Perform_Delete_On_RelationTypeRepository() { // Arrange - var provider = new PetaPocoUnitOfWorkProvider(); + var provider = new PetaPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); using (var repository = CreateRepository(unitOfWork)) { @@ -117,13 +107,13 @@ namespace Umbraco.Tests.Persistence.Repositories public void Can_Perform_Get_On_RelationTypeRepository() { // Arrange - var provider = new PetaPocoUnitOfWorkProvider(); + var provider = new PetaPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); using (var repository = CreateRepository(unitOfWork)) { // Act - var relationType = repository.Get(2); + var relationType = repository.Get(RelationTypeDto.NodeIdSeed); // Assert Assert.That(relationType, Is.Not.Null); @@ -137,7 +127,7 @@ namespace Umbraco.Tests.Persistence.Repositories public void Can_Perform_GetAll_On_RelationTypeRepository() { // Arrange - var provider = new PetaPocoUnitOfWorkProvider(); + var provider = new PetaPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); using (var repository = CreateRepository(unitOfWork)) { @@ -149,7 +139,7 @@ namespace Umbraco.Tests.Persistence.Repositories Assert.That(relationTypes, Is.Not.Null); Assert.That(relationTypes.Any(), Is.True); Assert.That(relationTypes.Any(x => x == null), Is.False); - Assert.That(relationTypes.Count(), Is.EqualTo(3)); + Assert.That(relationTypes.Count(), Is.EqualTo(4)); } } @@ -157,7 +147,7 @@ namespace Umbraco.Tests.Persistence.Repositories public void Can_Perform_GetAll_With_Params_On_RelationTypeRepository() { // Arrange - var provider = new PetaPocoUnitOfWorkProvider(); + var provider = new PetaPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); using (var repository = CreateRepository(unitOfWork)) { @@ -177,7 +167,7 @@ namespace Umbraco.Tests.Persistence.Repositories public void Can_Perform_Exists_On_RelationTypeRepository() { // Arrange - var provider = new PetaPocoUnitOfWorkProvider(); + var provider = new PetaPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); using (var repository = CreateRepository(unitOfWork)) { @@ -196,7 +186,7 @@ namespace Umbraco.Tests.Persistence.Repositories public void Can_Perform_Count_On_RelationTypeRepository() { // Arrange - var provider = new PetaPocoUnitOfWorkProvider(); + var provider = new PetaPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); using (var repository = CreateRepository(unitOfWork)) { @@ -206,7 +196,7 @@ namespace Umbraco.Tests.Persistence.Repositories int count = repository.Count(query); // Assert - Assert.That(count, Is.EqualTo(3)); + Assert.That(count, Is.EqualTo(4)); } } @@ -214,7 +204,7 @@ namespace Umbraco.Tests.Persistence.Repositories public void Can_Perform_GetByQuery_On_RelationTypeRepository() { // Arrange - var provider = new PetaPocoUnitOfWorkProvider(); + var provider = new PetaPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); using (var repository = CreateRepository(unitOfWork)) { @@ -243,9 +233,9 @@ 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(); + var provider = new PetaPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); - var repository = new RelationTypeRepository(unitOfWork); + var repository = new RelationTypeRepository(unitOfWork, CacheHelper.CreateDisabledCacheHelper(), Mock.Of(), SqlSyntaxProvider); repository.AddOrUpdate(relateContent);//Id 2 repository.AddOrUpdate(relateContentType);//Id 3 diff --git a/src/Umbraco.Tests/Persistence/Repositories/ScriptRepositoryTest.cs b/src/Umbraco.Tests/Persistence/Repositories/ScriptRepositoryTest.cs index 566c2c3c62..c907a8a4da 100644 --- a/src/Umbraco.Tests/Persistence/Repositories/ScriptRepositoryTest.cs +++ b/src/Umbraco.Tests/Persistence/Repositories/ScriptRepositoryTest.cs @@ -1,7 +1,9 @@ using System.IO; using System.Linq; using System.Text; +using Moq; using NUnit.Framework; +using Umbraco.Core.Configuration.UmbracoSettings; using Umbraco.Core.IO; using Umbraco.Core.Models; using Umbraco.Core.Persistence; @@ -36,7 +38,7 @@ namespace Umbraco.Tests.Persistence.Repositories var unitOfWork = provider.GetUnitOfWork(); // Act - var repository = new ScriptRepository(unitOfWork, _fileSystem); + var repository = new ScriptRepository(unitOfWork, _fileSystem, Mock.Of()); // Assert Assert.That(repository, Is.Not.Null); @@ -48,7 +50,7 @@ namespace Umbraco.Tests.Persistence.Repositories // Arrange var provider = new FileUnitOfWorkProvider(); var unitOfWork = provider.GetUnitOfWork(); - var repository = new ScriptRepository(unitOfWork, _fileSystem); + var repository = new ScriptRepository(unitOfWork, _fileSystem, Mock.Of()); // Act var script = new Script("test-add-script.js") {Content = "/// "}; @@ -65,7 +67,7 @@ namespace Umbraco.Tests.Persistence.Repositories // Arrange var provider = new FileUnitOfWorkProvider(); var unitOfWork = provider.GetUnitOfWork(); - var repository = new ScriptRepository(unitOfWork, _fileSystem); + var repository = new ScriptRepository(unitOfWork, _fileSystem, Mock.Of()); // Act var script = new Script("test-updated-script.js") { Content = "/// " }; @@ -89,7 +91,7 @@ namespace Umbraco.Tests.Persistence.Repositories // Arrange var provider = new FileUnitOfWorkProvider(); var unitOfWork = provider.GetUnitOfWork(); - var repository = new ScriptRepository(unitOfWork, _fileSystem); + var repository = new ScriptRepository(unitOfWork, _fileSystem, Mock.Of()); // Act var script = repository.Get("test-script.js"); @@ -108,7 +110,7 @@ namespace Umbraco.Tests.Persistence.Repositories // Arrange var provider = new FileUnitOfWorkProvider(); var unitOfWork = provider.GetUnitOfWork(); - var repository = new ScriptRepository(unitOfWork, _fileSystem); + var repository = new ScriptRepository(unitOfWork, _fileSystem, Mock.Of()); // Act var exists = repository.Get("test-script.js"); @@ -125,7 +127,7 @@ namespace Umbraco.Tests.Persistence.Repositories // Arrange var provider = new FileUnitOfWorkProvider(); var unitOfWork = provider.GetUnitOfWork(); - var repository = new ScriptRepository(unitOfWork, _fileSystem); + var repository = new ScriptRepository(unitOfWork, _fileSystem, Mock.Of()); var script = new Script("test-script1.js") { Content = "/// " }; repository.AddOrUpdate(script); @@ -151,7 +153,7 @@ namespace Umbraco.Tests.Persistence.Repositories // Arrange var provider = new FileUnitOfWorkProvider(); var unitOfWork = provider.GetUnitOfWork(); - var repository = new ScriptRepository(unitOfWork, _fileSystem); + var repository = new ScriptRepository(unitOfWork, _fileSystem, Mock.Of()); var script = new Script("test-script1.js") { Content = "/// " }; repository.AddOrUpdate(script); @@ -177,7 +179,7 @@ namespace Umbraco.Tests.Persistence.Repositories // Arrange var provider = new FileUnitOfWorkProvider(); var unitOfWork = provider.GetUnitOfWork(); - var repository = new ScriptRepository(unitOfWork, _fileSystem); + var repository = new ScriptRepository(unitOfWork, _fileSystem, Mock.Of()); // Act var exists = repository.Exists("test-script.js"); diff --git a/src/Umbraco.Tests/Persistence/Repositories/ServerRegistrationRepositoryTest.cs b/src/Umbraco.Tests/Persistence/Repositories/ServerRegistrationRepositoryTest.cs index 6188c351a1..cbd8aa9deb 100644 --- a/src/Umbraco.Tests/Persistence/Repositories/ServerRegistrationRepositoryTest.cs +++ b/src/Umbraco.Tests/Persistence/Repositories/ServerRegistrationRepositoryTest.cs @@ -1,9 +1,12 @@ using System; using System.Data.SqlServerCe; using System.Linq; +using Moq; using NUnit.Framework; +using Umbraco.Core; +using Umbraco.Core.Logging; using Umbraco.Core.Models; -using Umbraco.Core.Persistence.Caching; + using Umbraco.Core.Persistence.Querying; using Umbraco.Core.Persistence.Repositories; using Umbraco.Core.Persistence.UnitOfWork; @@ -25,14 +28,14 @@ namespace Umbraco.Tests.Persistence.Repositories private ServerRegistrationRepository CreateRepositor(IDatabaseUnitOfWork unitOfWork) { - return new ServerRegistrationRepository(unitOfWork, NullCacheProvider.Current); + return new ServerRegistrationRepository(unitOfWork, CacheHelper.CreateDisabledCacheHelper(), Mock.Of(), SqlSyntaxProvider); } [Test] public void Cannot_Add_Duplicate_Computer_Names() { // Arrange - var provider = new PetaPocoUnitOfWorkProvider(); + var provider = new PetaPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); // Act @@ -50,7 +53,7 @@ namespace Umbraco.Tests.Persistence.Repositories public void Cannot_Update_To_Duplicate_Computer_Names() { // Arrange - var provider = new PetaPocoUnitOfWorkProvider(); + var provider = new PetaPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); // Act @@ -68,7 +71,7 @@ namespace Umbraco.Tests.Persistence.Repositories public void Can_Instantiate_Repository() { // Arrange - var provider = new PetaPocoUnitOfWorkProvider(); + var provider = new PetaPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); // Act @@ -83,7 +86,7 @@ namespace Umbraco.Tests.Persistence.Repositories public void Can_Perform_Get_On_Repository() { // Arrange - var provider = new PetaPocoUnitOfWorkProvider(); + var provider = new PetaPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); using (var repository = CreateRepositor(unitOfWork)) { @@ -103,7 +106,7 @@ namespace Umbraco.Tests.Persistence.Repositories public void Can_Perform_GetAll_On_Repository() { // Arrange - var provider = new PetaPocoUnitOfWorkProvider(); + var provider = new PetaPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); using (var repository = CreateRepositor(unitOfWork)) { @@ -120,7 +123,7 @@ namespace Umbraco.Tests.Persistence.Repositories public void Can_Perform_GetByQuery_On_Repository() { // Arrange - var provider = new PetaPocoUnitOfWorkProvider(); + var provider = new PetaPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); using (var repository = CreateRepositor(unitOfWork)) { @@ -137,7 +140,7 @@ namespace Umbraco.Tests.Persistence.Repositories public void Can_Perform_Count_On_Repository() { // Arrange - var provider = new PetaPocoUnitOfWorkProvider(); + var provider = new PetaPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); using (var repository = CreateRepositor(unitOfWork)) { @@ -154,7 +157,7 @@ namespace Umbraco.Tests.Persistence.Repositories public void Can_Perform_Add_On_Repository() { // Arrange - var provider = new PetaPocoUnitOfWorkProvider(); + var provider = new PetaPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); using (var repository = CreateRepositor(unitOfWork)) { @@ -173,7 +176,7 @@ namespace Umbraco.Tests.Persistence.Repositories public void Can_Perform_Update_On_Repository() { // Arrange - var provider = new PetaPocoUnitOfWorkProvider(); + var provider = new PetaPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); using (var repository = CreateRepositor(unitOfWork)) { @@ -198,7 +201,7 @@ namespace Umbraco.Tests.Persistence.Repositories public void Can_Perform_Delete_On_Repository() { // Arrange - var provider = new PetaPocoUnitOfWorkProvider(); + var provider = new PetaPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); using (var repository = CreateRepositor(unitOfWork)) { @@ -219,7 +222,7 @@ namespace Umbraco.Tests.Persistence.Repositories public void Can_Perform_Exists_On_Repository() { // Arrange - var provider = new PetaPocoUnitOfWorkProvider(); + var provider = new PetaPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); using (var repository = CreateRepositor(unitOfWork)) { @@ -241,9 +244,9 @@ namespace Umbraco.Tests.Persistence.Repositories public void CreateTestData() { - var provider = new PetaPocoUnitOfWorkProvider(); + var provider = new PetaPocoUnitOfWorkProvider(Logger); using (var unitOfWork = provider.GetUnitOfWork()) - using (var repository = new ServerRegistrationRepository(unitOfWork)) + using (var repository = new ServerRegistrationRepository(unitOfWork, CacheHelper.CreateDisabledCacheHelper(), Mock.Of(), SqlSyntaxProvider)) { repository.AddOrUpdate(new ServerRegistration("http://localhost", "COMPUTER1", DateTime.Now) { IsActive = true }); repository.AddOrUpdate(new ServerRegistration("http://www.mydomain.com", "COMPUTER2", DateTime.Now)); diff --git a/src/Umbraco.Tests/Persistence/Repositories/StylesheetRepositoryTest.cs b/src/Umbraco.Tests/Persistence/Repositories/StylesheetRepositoryTest.cs index d9f894a342..d130cf72b5 100644 --- a/src/Umbraco.Tests/Persistence/Repositories/StylesheetRepositoryTest.cs +++ b/src/Umbraco.Tests/Persistence/Repositories/StylesheetRepositoryTest.cs @@ -1,8 +1,10 @@ using System.IO; using System.Linq; using System.Text; +using Moq; using NUnit.Framework; using Umbraco.Core.IO; +using Umbraco.Core.Logging; using Umbraco.Core.Models; using Umbraco.Core.Persistence.Repositories; using Umbraco.Core.Persistence.UnitOfWork; @@ -32,10 +34,9 @@ namespace Umbraco.Tests.Persistence.Repositories // Arrange var provider = new FileUnitOfWorkProvider(); var unitOfWork = provider.GetUnitOfWork(); - var dbUnitOfWork = PetaPocoUnitOfWorkProvider.CreateUnitOfWork(); // Act - var repository = new StylesheetRepository(unitOfWork, dbUnitOfWork, _fileSystem); + var repository = new StylesheetRepository(unitOfWork, _fileSystem); // Assert @@ -43,14 +44,13 @@ namespace Umbraco.Tests.Persistence.Repositories } [Test] - public void Can_Perform_Add_On_StylesheetRepository() + public void Can_Perform_Add() { // Arrange var provider = new FileUnitOfWorkProvider(); var unitOfWork = provider.GetUnitOfWork(); - var dbUnitOfWork = PetaPocoUnitOfWorkProvider.CreateUnitOfWork(); - var repository = new StylesheetRepository(unitOfWork, dbUnitOfWork, _fileSystem); + var repository = new StylesheetRepository(unitOfWork, _fileSystem); // Act var stylesheet = new Stylesheet("test-add.css") { Content = "body { color:#000; } .bold {font-weight:bold;}" }; @@ -62,19 +62,18 @@ namespace Umbraco.Tests.Persistence.Repositories } [Test] - public void Can_Perform_Update_On_StylesheetRepository() + public void Can_Perform_Update() { // Arrange var provider = new FileUnitOfWorkProvider(); var unitOfWork = provider.GetUnitOfWork(); - var dbUnitOfWork = PetaPocoUnitOfWorkProvider.CreateUnitOfWork(); - var repository = new StylesheetRepository(unitOfWork, dbUnitOfWork, _fileSystem); + + var repository = new StylesheetRepository(unitOfWork, _fileSystem); // Act var stylesheet = new Stylesheet("test-update.css") { Content = "body { color:#000; } .bold {font-weight:bold;}" }; repository.AddOrUpdate(stylesheet); unitOfWork.Commit(); - dbUnitOfWork.Commit(); var stylesheetUpdate = repository.Get("test-update.css"); stylesheetUpdate.Content = "body { color:#000; }"; @@ -90,13 +89,43 @@ namespace Umbraco.Tests.Persistence.Repositories } [Test] - public void Can_Perform_Delete_On_StylesheetRepository() + public void Can_Perform_Update_With_Property() { // Arrange var provider = new FileUnitOfWorkProvider(); var unitOfWork = provider.GetUnitOfWork(); - var dbUnitOfWork = PetaPocoUnitOfWorkProvider.CreateUnitOfWork(); - var repository = new StylesheetRepository(unitOfWork, dbUnitOfWork, _fileSystem); + + var repository = new StylesheetRepository(unitOfWork, _fileSystem); + + // Act + var stylesheet = new Stylesheet("test-update.css") { Content = "body { color:#000; } .bold {font-weight:bold;}" }; + repository.AddOrUpdate(stylesheet); + unitOfWork.Commit(); + + stylesheet.AddProperty(new StylesheetProperty("Test", "p", "font-size:2em;")); + + repository.AddOrUpdate(stylesheet); + unitOfWork.Commit(); + + //re-get + stylesheet = repository.Get(stylesheet.Name); + + //Assert + Assert.That(stylesheet.Content, Is.EqualTo(@"body { color:#000; } .bold {font-weight:bold;} + +/**umb_name:Test*/ +p{font-size:2em;}")); + Assert.AreEqual(1, stylesheet.Properties.Count()); + } + + [Test] + public void Can_Perform_Delete() + { + // Arrange + var provider = new FileUnitOfWorkProvider(); + var unitOfWork = provider.GetUnitOfWork(); + + var repository = new StylesheetRepository(unitOfWork, _fileSystem); // Act var stylesheet = new Stylesheet("test-delete.css") { Content = "body { color:#000; } .bold {font-weight:bold;}" }; @@ -111,13 +140,13 @@ namespace Umbraco.Tests.Persistence.Repositories } [Test] - public void Can_Perform_Get_On_StylesheetRepository() + public void Can_Perform_Get() { // Arrange var provider = new FileUnitOfWorkProvider(); var unitOfWork = provider.GetUnitOfWork(); - var dbUnitOfWork = PetaPocoUnitOfWorkProvider.CreateUnitOfWork(); - var repository = new StylesheetRepository(unitOfWork, dbUnitOfWork, _fileSystem); + + var repository = new StylesheetRepository(unitOfWork, _fileSystem); // Act var stylesheet = repository.Get("styles.css"); @@ -126,22 +155,21 @@ namespace Umbraco.Tests.Persistence.Repositories Assert.That(stylesheet, Is.Not.Null); Assert.That(stylesheet.HasIdentity, Is.True); Assert.That(stylesheet.Content, Is.EqualTo("body {background:#EE7600; color:#FFF;}")); - Assert.That(stylesheet.IsFileValidCss(), Is.True); + Assert.That(repository.ValidateStylesheet(stylesheet), Is.True); } [Test] - public void Can_Perform_GetAll_On_StylesheetRepository() + public void Can_Perform_GetAll() { // Arrange var provider = new FileUnitOfWorkProvider(); var unitOfWork = provider.GetUnitOfWork(); - var dbUnitOfWork = PetaPocoUnitOfWorkProvider.CreateUnitOfWork(); - var repository = new StylesheetRepository(unitOfWork, dbUnitOfWork, _fileSystem); + + var repository = new StylesheetRepository(unitOfWork, _fileSystem); var stylesheet = new Stylesheet("styles-v2.css") { Content = "body { color:#000; } .bold {font-weight:bold;}" }; repository.AddOrUpdate(stylesheet); unitOfWork.Commit(); - dbUnitOfWork.Commit(); // Act var stylesheets = repository.GetAll(); @@ -154,18 +182,17 @@ namespace Umbraco.Tests.Persistence.Repositories } [Test] - public void Can_Perform_GetAll_With_Params_On_StylesheetRepository() + public void Can_Perform_GetAll_With_Params() { // Arrange var provider = new FileUnitOfWorkProvider(); var unitOfWork = provider.GetUnitOfWork(); - var dbUnitOfWork = PetaPocoUnitOfWorkProvider.CreateUnitOfWork(); - var repository = new StylesheetRepository(unitOfWork, dbUnitOfWork, _fileSystem); + + var repository = new StylesheetRepository(unitOfWork, _fileSystem); var stylesheet = new Stylesheet("styles-v2.css") { Content = "body { color:#000; } .bold {font-weight:bold;}" }; repository.AddOrUpdate(stylesheet); unitOfWork.Commit(); - dbUnitOfWork.Commit(); // Act var stylesheets = repository.GetAll("styles-v2.css", "styles.css"); @@ -178,13 +205,13 @@ namespace Umbraco.Tests.Persistence.Repositories } [Test] - public void Can_Perform_Exists_On_StylesheetRepository() + public void Can_Perform_Exists() { // Arrange var provider = new FileUnitOfWorkProvider(); var unitOfWork = provider.GetUnitOfWork(); - var dbUnitOfWork = PetaPocoUnitOfWorkProvider.CreateUnitOfWork(); - var repository = new StylesheetRepository(unitOfWork, dbUnitOfWork, _fileSystem); + + var repository = new StylesheetRepository(unitOfWork, _fileSystem); // Act var exists = repository.Exists("styles.css"); diff --git a/src/Umbraco.Tests/Persistence/Repositories/TagRepositoryTest.cs b/src/Umbraco.Tests/Persistence/Repositories/TagRepositoryTest.cs index c3524580dd..f6714728ce 100644 --- a/src/Umbraco.Tests/Persistence/Repositories/TagRepositoryTest.cs +++ b/src/Umbraco.Tests/Persistence/Repositories/TagRepositoryTest.cs @@ -1,11 +1,15 @@ using System; using System.Linq; +using Moq; using NUnit.Framework; using Umbraco.Core; +using Umbraco.Core.Configuration.UmbracoSettings; +using Umbraco.Core.IO; +using Umbraco.Core.Logging; using Umbraco.Core.Models; using Umbraco.Core.Models.Rdbms; using Umbraco.Core.Persistence; -using Umbraco.Core.Persistence.Caching; + using Umbraco.Core.Persistence.Repositories; using Umbraco.Core.Persistence.UnitOfWork; using Umbraco.Tests.TestHelpers; @@ -31,29 +35,15 @@ namespace Umbraco.Tests.Persistence.Repositories private TagRepository CreateRepository(IDatabaseUnitOfWork unitOfWork) { - var tagRepository = new TagRepository(unitOfWork, NullCacheProvider.Current); + var tagRepository = new TagRepository(unitOfWork, CacheHelper.CreateDisabledCacheHelper(), Mock.Of(), SqlSyntaxProvider); return tagRepository; } - [Test] - public void Can_Instantiate_Repository_From_Resolver() - { - // Arrange - var provider = new PetaPocoUnitOfWorkProvider(); - var unitOfWork = provider.GetUnitOfWork(); - - // Act - var repository = RepositoryResolver.Current.ResolveByType(unitOfWork); - - // Assert - Assert.That(repository, Is.Not.Null); - } - [Test] public void Can_Perform_Add_On_Repository() { // Arrange - var provider = new PetaPocoUnitOfWorkProvider(); + var provider = new PetaPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); using (var repository = CreateRepository(unitOfWork)) { @@ -76,7 +66,7 @@ namespace Umbraco.Tests.Persistence.Repositories public void Can_Perform_Multiple_Adds_On_Repository() { // Arrange - var provider = new PetaPocoUnitOfWorkProvider(); + var provider = new PetaPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); using (var repository = CreateRepository(unitOfWork)) { @@ -109,7 +99,7 @@ namespace Umbraco.Tests.Persistence.Repositories [Test] public void Can_Create_Tag_Relations() { - var provider = new PetaPocoUnitOfWorkProvider(); + var provider = new PetaPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); ContentTypeRepository contentTypeRepository; using (var contentRepository = CreateContentRepository(unitOfWork, out contentTypeRepository)) @@ -141,7 +131,7 @@ namespace Umbraco.Tests.Persistence.Repositories [Test] public void Can_Append_Tag_Relations() { - var provider = new PetaPocoUnitOfWorkProvider(); + var provider = new PetaPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); ContentTypeRepository contentTypeRepository; using (var contentRepository = CreateContentRepository(unitOfWork, out contentTypeRepository)) @@ -182,7 +172,7 @@ namespace Umbraco.Tests.Persistence.Repositories [Test] public void Can_Replace_Tag_Relations() { - var provider = new PetaPocoUnitOfWorkProvider(); + var provider = new PetaPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); ContentTypeRepository contentTypeRepository; using (var contentRepository = CreateContentRepository(unitOfWork, out contentTypeRepository)) @@ -226,7 +216,7 @@ namespace Umbraco.Tests.Persistence.Repositories [Test] public void Can_Merge_Tag_Relations() { - var provider = new PetaPocoUnitOfWorkProvider(); + var provider = new PetaPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); ContentTypeRepository contentTypeRepository; using (var contentRepository = CreateContentRepository(unitOfWork, out contentTypeRepository)) @@ -268,7 +258,7 @@ namespace Umbraco.Tests.Persistence.Repositories [Test] public void Can_Clear_Tag_Relations() { - var provider = new PetaPocoUnitOfWorkProvider(); + var provider = new PetaPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); ContentTypeRepository contentTypeRepository; using (var contentRepository = CreateContentRepository(unitOfWork, out contentTypeRepository)) @@ -306,7 +296,7 @@ namespace Umbraco.Tests.Persistence.Repositories [Test] public void Can_Remove_Specific_Tags_From_Property() { - var provider = new PetaPocoUnitOfWorkProvider(); + var provider = new PetaPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); ContentTypeRepository contentTypeRepository; using (var contentRepository = CreateContentRepository(unitOfWork, out contentTypeRepository)) @@ -352,7 +342,7 @@ namespace Umbraco.Tests.Persistence.Repositories [Test] public void Can_Get_Tags_For_Content() { - var provider = new PetaPocoUnitOfWorkProvider(); + var provider = new PetaPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); ContentTypeRepository contentTypeRepository; using (var contentRepository = CreateContentRepository(unitOfWork, out contentTypeRepository)) @@ -398,7 +388,7 @@ namespace Umbraco.Tests.Persistence.Repositories [Test] public void Can_Get_All() { - var provider = new PetaPocoUnitOfWorkProvider(); + var provider = new PetaPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); ContentTypeRepository contentTypeRepository; using (var contentRepository = CreateContentRepository(unitOfWork, out contentTypeRepository)) @@ -435,7 +425,7 @@ namespace Umbraco.Tests.Persistence.Repositories [Test] public void Can_Get_All_With_Ids() { - var provider = new PetaPocoUnitOfWorkProvider(); + var provider = new PetaPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); ContentTypeRepository contentTypeRepository; using (var contentRepository = CreateContentRepository(unitOfWork, out contentTypeRepository)) @@ -477,7 +467,7 @@ namespace Umbraco.Tests.Persistence.Repositories [Test] public void Can_Get_Tags_For_Content_For_Group() { - var provider = new PetaPocoUnitOfWorkProvider(); + var provider = new PetaPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); ContentTypeRepository contentTypeRepository; using (var contentRepository = CreateContentRepository(unitOfWork, out contentTypeRepository)) @@ -523,7 +513,7 @@ namespace Umbraco.Tests.Persistence.Repositories [Test] public void Can_Get_Tags_For_Property() { - var provider = new PetaPocoUnitOfWorkProvider(); + var provider = new PetaPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); ContentTypeRepository contentTypeRepository; using (var contentRepository = CreateContentRepository(unitOfWork, out contentTypeRepository)) @@ -570,7 +560,7 @@ namespace Umbraco.Tests.Persistence.Repositories [Test] public void Can_Get_Tags_For_Property_For_Group() { - var provider = new PetaPocoUnitOfWorkProvider(); + var provider = new PetaPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); ContentTypeRepository contentTypeRepository; using (var contentRepository = CreateContentRepository(unitOfWork, out contentTypeRepository)) @@ -619,7 +609,7 @@ namespace Umbraco.Tests.Persistence.Repositories [Test] public void Can_Get_Tags_For_Entity_Type() { - var provider = new PetaPocoUnitOfWorkProvider(); + var provider = new PetaPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); MediaTypeRepository mediaTypeRepository; ContentTypeRepository contentTypeRepository; @@ -681,7 +671,7 @@ namespace Umbraco.Tests.Persistence.Repositories [Test] public void Can_Get_Tags_For_Entity_Type_For_Group() { - var provider = new PetaPocoUnitOfWorkProvider(); + var provider = new PetaPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); MediaTypeRepository mediaTypeRepository; ContentTypeRepository contentTypeRepository; @@ -738,7 +728,7 @@ namespace Umbraco.Tests.Persistence.Repositories [Test] public void Cascade_Deletes_Tag_Relations() { - var provider = new PetaPocoUnitOfWorkProvider(); + var provider = new PetaPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); ContentTypeRepository contentTypeRepository; using (var contentRepository = CreateContentRepository(unitOfWork, out contentTypeRepository)) @@ -779,7 +769,7 @@ namespace Umbraco.Tests.Persistence.Repositories [Test] public void Can_Get_Tagged_Entities_For_Tag_Group() { - var provider = new PetaPocoUnitOfWorkProvider(); + var provider = new PetaPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); MediaTypeRepository mediaTypeRepository; ContentTypeRepository contentTypeRepository; @@ -866,7 +856,7 @@ namespace Umbraco.Tests.Persistence.Repositories [Test] public void Can_Get_Tagged_Entities_For_Tag() { - var provider = new PetaPocoUnitOfWorkProvider(); + var provider = new PetaPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); MediaTypeRepository mediaTypeRepository; ContentTypeRepository contentTypeRepository; @@ -949,18 +939,18 @@ namespace Umbraco.Tests.Persistence.Repositories private ContentRepository CreateContentRepository(IDatabaseUnitOfWork unitOfWork, out ContentTypeRepository contentTypeRepository) { - var templateRepository = new TemplateRepository(unitOfWork, NullCacheProvider.Current); - var tagRepository = new TagRepository(unitOfWork, NullCacheProvider.Current); - contentTypeRepository = new ContentTypeRepository(unitOfWork, NullCacheProvider.Current, templateRepository); - var repository = new ContentRepository(unitOfWork, NullCacheProvider.Current, contentTypeRepository, templateRepository, tagRepository, CacheHelper.CreateDisabledCacheHelper()); + var templateRepository = new TemplateRepository(unitOfWork, CacheHelper.CreateDisabledCacheHelper(), Mock.Of(), SqlSyntaxProvider, Mock.Of(), Mock.Of(), Mock.Of()); + var tagRepository = new TagRepository(unitOfWork, CacheHelper.CreateDisabledCacheHelper(), Mock.Of(), SqlSyntaxProvider); + contentTypeRepository = new ContentTypeRepository(unitOfWork, CacheHelper.CreateDisabledCacheHelper(), Mock.Of(), SqlSyntaxProvider, templateRepository); + var repository = new ContentRepository(unitOfWork, CacheHelper.CreateDisabledCacheHelper(), Mock.Of(), SqlSyntaxProvider, contentTypeRepository, templateRepository, tagRepository); return repository; } private MediaRepository CreateMediaRepository(IDatabaseUnitOfWork unitOfWork, out MediaTypeRepository mediaTypeRepository) { - var tagRepository = new TagRepository(unitOfWork, NullCacheProvider.Current); - mediaTypeRepository = new MediaTypeRepository(unitOfWork, NullCacheProvider.Current); - var repository = new MediaRepository(unitOfWork, NullCacheProvider.Current, mediaTypeRepository, tagRepository); + var tagRepository = new TagRepository(unitOfWork, CacheHelper.CreateDisabledCacheHelper(), Mock.Of(), SqlSyntaxProvider); + mediaTypeRepository = new MediaTypeRepository(unitOfWork, CacheHelper.CreateDisabledCacheHelper(), Mock.Of(), SqlSyntaxProvider); + var repository = new MediaRepository(unitOfWork, CacheHelper.CreateDisabledCacheHelper(), Mock.Of(), SqlSyntaxProvider, mediaTypeRepository, tagRepository); return repository; } } diff --git a/src/Umbraco.Tests/Persistence/Repositories/TemplateRepositoryTest.cs b/src/Umbraco.Tests/Persistence/Repositories/TemplateRepositoryTest.cs index a3955538cf..4987309e34 100644 --- a/src/Umbraco.Tests/Persistence/Repositories/TemplateRepositoryTest.cs +++ b/src/Umbraco.Tests/Persistence/Repositories/TemplateRepositoryTest.cs @@ -2,14 +2,18 @@ using System.IO; using System.Linq; using System.Text; +using Moq; using NUnit.Framework; using Umbraco.Core; +using Umbraco.Core.Configuration.UmbracoSettings; using Umbraco.Core.IO; +using Umbraco.Core.Logging; using Umbraco.Core.Models; using Umbraco.Core.Persistence; -using Umbraco.Core.Persistence.Caching; + using Umbraco.Core.Persistence.Repositories; using Umbraco.Core.Persistence.UnitOfWork; +using Umbraco.Core.Services; using Umbraco.Tests.TestHelpers; using Umbraco.Tests.TestHelpers.Entities; @@ -22,6 +26,12 @@ namespace Umbraco.Tests.Persistence.Repositories private IFileSystem _masterPageFileSystem; private IFileSystem _viewsFileSystem; + private ITemplateRepository CreateRepository(IDatabaseUnitOfWork unitOfWork, ITemplatesSection templatesSection = null) + { + return new TemplateRepository(unitOfWork, CacheHelper.CreateDisabledCacheHelper(), Mock.Of(), SqlSyntaxProvider, _masterPageFileSystem, _viewsFileSystem, + templatesSection ?? Mock.Of(t => t.DefaultRenderingEngine == RenderingEngine.Mvc)); + } + [SetUp] public override void Initialize() { @@ -31,70 +41,255 @@ namespace Umbraco.Tests.Persistence.Repositories _viewsFileSystem = new PhysicalFileSystem(SystemDirectories.MvcViews); } - [Test] - public void Can_Instantiate_Repository_From_Resolver() - { - // Arrange - var provider = new PetaPocoUnitOfWorkProvider(); - var unitOfWork = provider.GetUnitOfWork(); - - // Act - using (var repository = RepositoryResolver.Current.ResolveByType(unitOfWork)) - { - - // Assert - Assert.That(repository, Is.Not.Null); - } - - } - [Test] public void Can_Instantiate_Repository() { // Arrange - var provider = new PetaPocoUnitOfWorkProvider(); + var provider = new PetaPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); // Act - using (var repository = new TemplateRepository(unitOfWork, NullCacheProvider.Current, _masterPageFileSystem, _viewsFileSystem)) + using (var repository = CreateRepository(unitOfWork)) { // Assert - Assert.That(repository, Is.Not.Null); + Assert.That(repository, Is.Not.Null); } } [Test] - public void Can_Perform_Add_MasterPage() + public void Can_Perform_Add_MasterPage_Detect_Content() { // Arrange - var provider = new PetaPocoUnitOfWorkProvider(); + var provider = new PetaPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); - using (var repository = new TemplateRepository(unitOfWork, NullCacheProvider.Current, _masterPageFileSystem, _viewsFileSystem)) + using (var repository = CreateRepository(unitOfWork)) { // Act - var template = new Template("test-add-masterpage.master", "test", "test") { Content = @"<%@ Master Language=""C#"" %>" }; + var template = new Template("test", "test") + { + Content = @"<%@ Master Language=""C#"" %>" + }; repository.AddOrUpdate(template); unitOfWork.Commit(); //Assert Assert.That(repository.Get("test"), Is.Not.Null); - Assert.That(_masterPageFileSystem.FileExists("test.master"), Is.True); + Assert.That(_masterPageFileSystem.FileExists("test.master"), Is.True); } - + + } + + [Test] + public void Can_Perform_Add_MasterPage_With_Default_Content() + { + // Arrange + var provider = new PetaPocoUnitOfWorkProvider(Logger); + var unitOfWork = provider.GetUnitOfWork(); + using (var repository = CreateRepository(unitOfWork, Mock.Of(x => x.DefaultRenderingEngine == RenderingEngine.WebForms))) + { + // Act + var template = new Template("test", "test"); + repository.AddOrUpdate(template); + unitOfWork.Commit(); + + //Assert + Assert.That(repository.Get("test"), Is.Not.Null); + Assert.That(_masterPageFileSystem.FileExists("test.master"), Is.True); + Assert.AreEqual(@"<%@ Master Language=""C#"" MasterPageFile=""~/umbraco/masterpages/default.master"" AutoEventWireup=""true"" %> + + + + +", template.Content); + } + + } + + [Test] + public void Can_Perform_Add_MasterPage_With_Default_Content_With_Parent() + { + // Arrange + var provider = new PetaPocoUnitOfWorkProvider(Logger); + var unitOfWork = provider.GetUnitOfWork(); + using (var repository = CreateRepository(unitOfWork, Mock.Of(x => x.DefaultRenderingEngine == RenderingEngine.WebForms))) + { + //NOTE: This has to be persisted first + var template = new Template("test", "test"); + repository.AddOrUpdate(template); + unitOfWork.Commit(); + + // Act + var template2 = new Template("test2", "test2"); + template2.SetMasterTemplate(template); + repository.AddOrUpdate(template2); + unitOfWork.Commit(); + + //Assert + Assert.That(repository.Get("test2"), Is.Not.Null); + Assert.That(_masterPageFileSystem.FileExists("test2.master"), Is.True); + Assert.AreEqual(@"<%@ Master Language=""C#"" MasterPageFile=""~/masterpages/test.master"" AutoEventWireup=""true"" %> + +", template2.Content); + } + + } + + [Test] + public void Can_Perform_Add_View() + { + // Arrange + var provider = new PetaPocoUnitOfWorkProvider(Logger); + var unitOfWork = provider.GetUnitOfWork(); + using (var repository = CreateRepository(unitOfWork)) + { + // Act + var template = new Template("test", "test"); + repository.AddOrUpdate(template); + unitOfWork.Commit(); + + //Assert + Assert.That(repository.Get("test"), Is.Not.Null); + Assert.That(_viewsFileSystem.FileExists("test.cshtml"), Is.True); + } + + } + + [Test] + public void Can_Perform_Add_View_With_Default_Content() + { + // Arrange + var provider = new PetaPocoUnitOfWorkProvider(Logger); + var unitOfWork = provider.GetUnitOfWork(); + using (var repository = CreateRepository(unitOfWork)) + { + // Act + var template = new Template("test", "test") + { + Content = ViewHelper.GetDefaultFileContent() + }; + repository.AddOrUpdate(template); + unitOfWork.Commit(); + + //Assert + Assert.That(repository.Get("test"), Is.Not.Null); + Assert.That(_viewsFileSystem.FileExists("test.cshtml"), Is.True); + Assert.AreEqual(@"@inherits Umbraco.Web.Mvc.UmbracoTemplatePage +@{ + Layout = null; +}", template.Content); + } + + } + + [Test] + public void Can_Perform_Add_View_With_Default_Content_With_Parent() + { + // Arrange + var provider = new PetaPocoUnitOfWorkProvider(Logger); + var unitOfWork = provider.GetUnitOfWork(); + using (var repository = CreateRepository(unitOfWork)) + { + //NOTE: This has to be persisted first + var template = new Template("test", "test"); + repository.AddOrUpdate(template); + unitOfWork.Commit(); + + // Act + var template2 = new Template("test2", "test2"); + template2.SetMasterTemplate(template); + repository.AddOrUpdate(template2); + unitOfWork.Commit(); + + //Assert + Assert.That(repository.Get("test2"), Is.Not.Null); + Assert.That(_viewsFileSystem.FileExists("test2.cshtml"), Is.True); + Assert.AreEqual(@"@inherits Umbraco.Web.Mvc.UmbracoTemplatePage +@{ + Layout = ""test.cshtml""; +}", template2.Content); + } + + } + + [Test] + public void Can_Perform_Add_Unique_Alias() + { + // Arrange + var provider = new PetaPocoUnitOfWorkProvider(Logger); + var unitOfWork = provider.GetUnitOfWork(); + using (var repository = CreateRepository(unitOfWork)) + { + // Act + var template = new Template("test", "test") + { + Content = ViewHelper.GetDefaultFileContent() + }; + repository.AddOrUpdate(template); + unitOfWork.Commit(); + + var template2 = new Template("test", "test") + { + Content = ViewHelper.GetDefaultFileContent() + }; + repository.AddOrUpdate(template2); + unitOfWork.Commit(); + + //Assert + Assert.AreEqual("test1", template2.Alias); + } + + } + + [Test] + public void Can_Perform_Update_Unique_Alias() + { + // Arrange + var provider = new PetaPocoUnitOfWorkProvider(Logger); + var unitOfWork = provider.GetUnitOfWork(); + using (var repository = CreateRepository(unitOfWork)) + { + // Act + var template = new Template("test", "test") + { + Content = ViewHelper.GetDefaultFileContent() + }; + repository.AddOrUpdate(template); + unitOfWork.Commit(); + + var template2 = new Template("test1", "test1") + { + Content = ViewHelper.GetDefaultFileContent() + }; + repository.AddOrUpdate(template2); + unitOfWork.Commit(); + + template.Alias = "test1"; + repository.AddOrUpdate(template); + unitOfWork.Commit(); + + //Assert + Assert.AreEqual("test11", template.Alias); + Assert.That(_viewsFileSystem.FileExists("test11.cshtml"), Is.True); + Assert.That(_viewsFileSystem.FileExists("test.cshtml"), Is.False); + } + } [Test] public void Can_Perform_Update_MasterPage() { // Arrange - var provider = new PetaPocoUnitOfWorkProvider(); + var provider = new PetaPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); - using (var repository = new TemplateRepository(unitOfWork, NullCacheProvider.Current, _masterPageFileSystem, _viewsFileSystem)) + using (var repository = CreateRepository(unitOfWork)) { // Act - var template = new Template("test-updated-masterpage.master", "test", "test") { Content = @"<%@ Master Language=""C#"" %>" }; + var template = new Template("test", "test") + { + Content = @"<%@ Master Language=""C#"" %>" + }; repository.AddOrUpdate(template); unitOfWork.Commit(); @@ -106,60 +301,127 @@ namespace Umbraco.Tests.Persistence.Repositories // Assert Assert.That(_masterPageFileSystem.FileExists("test.master"), Is.True); - Assert.That(updated.Content, Is.EqualTo(@"<%@ Master Language=""VB"" %>")); + Assert.That(updated.Content, Is.EqualTo(@"<%@ Master Language=""VB"" %>")); } - + } [Test] - public void Can_Perform_Delete() + public void Can_Perform_Update_View() { // Arrange - var provider = new PetaPocoUnitOfWorkProvider(); + var provider = new PetaPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); - using (var repository = new TemplateRepository(unitOfWork, NullCacheProvider.Current, _masterPageFileSystem, _viewsFileSystem)) + using (var repository = CreateRepository(unitOfWork)) { - var template = new Template("test-add-masterpage.master", "test", "test") { Content = @"<%@ Master Language=""C#"" %>" }; + // Act + var template = new Template("test", "test") + { + Content = ViewHelper.GetDefaultFileContent() + }; + repository.AddOrUpdate(template); + unitOfWork.Commit(); + + template.Content += ""; + repository.AddOrUpdate(template); + unitOfWork.Commit(); + + var updated = repository.Get("test"); + + // Assert + Assert.That(_viewsFileSystem.FileExists("test.cshtml"), Is.True); + Assert.That(updated.Content, Is.EqualTo(ViewHelper.GetDefaultFileContent() + "")); + } + + + } + + [Test] + public void Can_Perform_Delete_MasterPage() + { + // Arrange + var provider = new PetaPocoUnitOfWorkProvider(Logger); + var unitOfWork = provider.GetUnitOfWork(); + using (var repository = CreateRepository(unitOfWork)) + { + var template = new Template("test", "test") + { + Content = @"<%@ Master Language=""C#"" %>" + }; repository.AddOrUpdate(template); unitOfWork.Commit(); // Act var templates = repository.Get("test"); + Assert.That(_masterPageFileSystem.FileExists("test.master"), Is.True); repository.Delete(templates); unitOfWork.Commit(); // Assert Assert.IsNull(repository.Get("test")); + Assert.That(_masterPageFileSystem.FileExists("test.master"), Is.False); } - + + } + + [Test] + public void Can_Perform_Delete_View() + { + // Arrange + var provider = new PetaPocoUnitOfWorkProvider(Logger); + var unitOfWork = provider.GetUnitOfWork(); + using (var repository = CreateRepository(unitOfWork)) + { + var template = new Template("test", "test") + { + Content = ViewHelper.GetDefaultFileContent() + }; + repository.AddOrUpdate(template); + unitOfWork.Commit(); + + // Act + var templates = repository.Get("test"); + Assert.That(_viewsFileSystem.FileExists("test.cshtml"), Is.True); + repository.Delete(templates); + unitOfWork.Commit(); + + // Assert + Assert.IsNull(repository.Get("test")); + Assert.That(_viewsFileSystem.FileExists("test.cshtml"), Is.False); + } + + } [Test] public void Can_Perform_Delete_When_Assigned_To_Doc() { // Arrange - var provider = new PetaPocoUnitOfWorkProvider(); + var provider = new PetaPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); - var templateRepository = new TemplateRepository(unitOfWork, NullCacheProvider.Current); - var tagRepository = new TagRepository(unitOfWork, NullCacheProvider.Current); - var contentTypeRepository = new ContentTypeRepository(unitOfWork, NullCacheProvider.Current, templateRepository); - var contentRepo = new ContentRepository(unitOfWork, NullCacheProvider.Current, contentTypeRepository, templateRepository, tagRepository, CacheHelper.CreateDisabledCacheHelper()); - - using (contentRepo) + using (var templateRepository = CreateRepository(unitOfWork)) { - var contentType = MockedContentTypes.CreateSimpleContentType("umbTextpage2", "Textpage"); - var textpage = MockedContent.CreateSimpleContent(contentType); - contentTypeRepository.AddOrUpdate(contentType); - contentRepo.AddOrUpdate(textpage); - unitOfWork.Commit(); + var tagRepository = new TagRepository(unitOfWork, CacheHelper.CreateDisabledCacheHelper(), Mock.Of(), SqlSyntaxProvider); + var contentTypeRepository = new ContentTypeRepository(unitOfWork, CacheHelper.CreateDisabledCacheHelper(), Mock.Of(), SqlSyntaxProvider, templateRepository); + var contentRepo = new ContentRepository(unitOfWork, CacheHelper.CreateDisabledCacheHelper(), Mock.Of(), SqlSyntaxProvider, contentTypeRepository, templateRepository, tagRepository); - using (var repository = new TemplateRepository(unitOfWork, NullCacheProvider.Current, _masterPageFileSystem, _viewsFileSystem)) + using (contentRepo) { - var template = new Template("test-add-masterpage.master", "test", "test") { Content = @"<%@ Master Language=""C#"" %>" }; - repository.AddOrUpdate(template); + var contentType = MockedContentTypes.CreateSimpleContentType("umbTextpage2", "Textpage"); + var textpage = MockedContent.CreateSimpleContent(contentType); + contentTypeRepository.AddOrUpdate(contentType); + contentRepo.AddOrUpdate(textpage); + unitOfWork.Commit(); + + + var template = new Template("test", "test") + { + Content = @"<%@ Master Language=""C#"" %>" + }; + templateRepository.AddOrUpdate(template); unitOfWork.Commit(); textpage.Template = template; @@ -167,28 +429,37 @@ namespace Umbraco.Tests.Persistence.Repositories unitOfWork.Commit(); // Act - var templates = repository.Get("test"); - repository.Delete(templates); + var templates = templateRepository.Get("test"); + templateRepository.Delete(templates); unitOfWork.Commit(); // Assert - Assert.IsNull(repository.Get("test")); + Assert.IsNull(templateRepository.Get("test")); } } - + } [Test] public void Can_Perform_Delete_On_Nested_Templates() { // Arrange - var provider = new PetaPocoUnitOfWorkProvider(); + var provider = new PetaPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); - using (var repository = new TemplateRepository(unitOfWork, NullCacheProvider.Current, _masterPageFileSystem, _viewsFileSystem)) + using (var repository = CreateRepository(unitOfWork)) { - var parent = new Template("test-parent-masterpage.master", "parent", "parent") { Content = @"<%@ Master Language=""C#"" %>" }; - var child = new Template("test-child-masterpage.master", "child", "child") { Content = @"<%@ Master Language=""C#"" %>" }; - var baby = new Template("test-baby-masterpage.master", "baby", "baby") { Content = @"<%@ Master Language=""C#"" %>" }; + var parent = new Template("parent", "parent") + { + Content = @"<%@ Master Language=""C#"" %>" + }; + var child = new Template("child", "child") + { + Content = @"<%@ Master Language=""C#"" %>" + }; + var baby = new Template("baby", "baby") + { + Content = @"<%@ Master Language=""C#"" %>" + }; child.MasterTemplateAlias = parent.Alias; child.MasterTemplateId = new Lazy(() => parent.Id); baby.MasterTemplateAlias = child.Alias; @@ -207,28 +478,55 @@ namespace Umbraco.Tests.Persistence.Repositories Assert.IsNull(repository.Get("test")); } - + } [Test] public void Can_Get_Template_Tree() { // Arrange - var provider = new PetaPocoUnitOfWorkProvider(); + var provider = new PetaPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); - using (var repository = new TemplateRepository(unitOfWork, NullCacheProvider.Current, _masterPageFileSystem, _viewsFileSystem)) + using (var repository = CreateRepository(unitOfWork)) { - var parent = new Template("test-parent-masterpage.master", "parent", "parent") { Content = @"<%@ Master Language=""C#"" %>" }; + var parent = new Template("parent", "parent") + { + Content = @"<%@ Master Language=""C#"" %>" + }; - var child1 = new Template("test-child1-masterpage.master", "child1", "child1") { Content = @"<%@ Master Language=""C#"" %>" }; - var toddler1 = new Template("test-toddler1-masterpage.master", "toddler1", "toddler1") { Content = @"<%@ Master Language=""C#"" %>" }; - var toddler2 = new Template("test-toddler2-masterpage.master", "toddler2", "toddler2") { Content = @"<%@ Master Language=""C#"" %>" }; - var baby1 = new Template("test-baby1-masterpage.master", "baby1", "baby1") { Content = @"<%@ Master Language=""C#"" %>" }; + var child1 = new Template("child1", "child1") + { + Content = @"<%@ Master Language=""C#"" %>" + }; + var toddler1 = new Template("toddler1", "toddler1") + { + Content = @"<%@ Master Language=""C#"" %>" + }; + var toddler2 = new Template("toddler2", "toddler2") + { + Content = @"<%@ Master Language=""C#"" %>" + }; + var baby1 = new Template("baby1", "baby1") + { + Content = @"<%@ Master Language=""C#"" %>" + }; - var child2 = new Template("test-child2-masterpage.master", "child2", "child2") { Content = @"<%@ Master Language=""C#"" %>" }; - var toddler3 = new Template("test-toddler3-masterpage.master", "toddler3", "toddler3") { Content = @"<%@ Master Language=""C#"" %>" }; - var toddler4 = new Template("test-toddler4-masterpage.master", "toddler4", "toddler4") { Content = @"<%@ Master Language=""C#"" %>" }; - var baby2 = new Template("test-baby2-masterpage.master", "baby2", "baby2") { Content = @"<%@ Master Language=""C#"" %>" }; + var child2 = new Template("child2", "child2") + { + Content = @"<%@ Master Language=""C#"" %>" + }; + var toddler3 = new Template("toddler3", "toddler3") + { + Content = @"<%@ Master Language=""C#"" %>" + }; + var toddler4 = new Template("toddler4", "toddler4") + { + Content = @"<%@ Master Language=""C#"" %>" + }; + var baby2 = new Template("baby2", "baby2") + { + Content = @"<%@ Master Language=""C#"" %>" + }; child1.MasterTemplateAlias = parent.Alias; @@ -278,92 +576,114 @@ namespace Umbraco.Tests.Persistence.Repositories Assert.IsNotNull(repository.FindTemplateInTree(rootNode, "baby2")); } - + } - //[Test] - //public void Can_Perform_Get_On_ScriptRepository() - //{ - // // Arrange - // var provider = new FileUnitOfWorkProvider(); - // var unitOfWork = provider.GetUnitOfWork(); - // var repository = new ScriptRepository(unitOfWork, _masterPageFileSystem); + [Test] + public void Path_Is_Set_Correctly_On_Creation() + { + // Arrange + var provider = new PetaPocoUnitOfWorkProvider(Logger); + var unitOfWork = provider.GetUnitOfWork(); + using (var repository = CreateRepository(unitOfWork)) + { + var parent = new Template("parent", "parent"); + var child1 = new Template("child1", "child1"); + var toddler1 = new Template("toddler1", "toddler1"); + var toddler2 = new Template("toddler2", "toddler2"); + var baby1 = new Template("baby1", "baby1"); + var child2 = new Template("child2", "child2"); + var toddler3 = new Template("toddler3", "toddler3"); + var toddler4 = new Template("toddler4", "toddler4"); + var baby2 = new Template("baby2", "baby2"); - // // Act - // var exists = repository.Get("test-script.js"); + child1.MasterTemplateAlias = parent.Alias; + child1.MasterTemplateId = new Lazy(() => parent.Id); + child2.MasterTemplateAlias = parent.Alias; + child2.MasterTemplateId = new Lazy(() => parent.Id); + toddler1.MasterTemplateAlias = child1.Alias; + toddler1.MasterTemplateId = new Lazy(() => child1.Id); + toddler2.MasterTemplateAlias = child1.Alias; + toddler2.MasterTemplateId = new Lazy(() => child1.Id); + toddler3.MasterTemplateAlias = child2.Alias; + toddler3.MasterTemplateId = new Lazy(() => child2.Id); + toddler4.MasterTemplateAlias = child2.Alias; + toddler4.MasterTemplateId = new Lazy(() => child2.Id); + baby1.MasterTemplateAlias = toddler2.Alias; + baby1.MasterTemplateId = new Lazy(() => toddler2.Id); + baby2.MasterTemplateAlias = toddler4.Alias; + baby2.MasterTemplateId = new Lazy(() => toddler4.Id); - // // Assert - // Assert.That(exists, Is.Not.Null); - // Assert.That(exists.Alias, Is.EqualTo("test-script")); - // Assert.That(exists.Name, Is.EqualTo("test-script.js")); - //} - //[Test] - //public void Can_Perform_GetAll_On_ScriptRepository() - //{ - // // Arrange - // var provider = new FileUnitOfWorkProvider(); - // var unitOfWork = provider.GetUnitOfWork(); - // var repository = new ScriptRepository(unitOfWork, _masterPageFileSystem); + // Act + repository.AddOrUpdate(parent); + repository.AddOrUpdate(child1); + repository.AddOrUpdate(child2); + repository.AddOrUpdate(toddler1); + repository.AddOrUpdate(toddler2); + repository.AddOrUpdate(toddler3); + repository.AddOrUpdate(toddler4); + repository.AddOrUpdate(baby1); + repository.AddOrUpdate(baby2); + unitOfWork.Commit(); - // var script = new Script("test-script1.js") { Content = "/// " }; - // repository.AddOrUpdate(script); - // var script2 = new Script("test-script2.js") { Content = "/// " }; - // repository.AddOrUpdate(script2); - // var script3 = new Script("test-script3.js") { Content = "/// " }; - // repository.AddOrUpdate(script3); - // unitOfWork.Commit(); + // Assert + Assert.AreEqual(string.Format("-1,{0}", parent.Id), parent.Path); + Assert.AreEqual(string.Format("-1,{0},{1}", parent.Id, child1.Id), child1.Path); + Assert.AreEqual(string.Format("-1,{0},{1}", parent.Id, child2.Id), child2.Path); + Assert.AreEqual(string.Format("-1,{0},{1}", parent.Id, child2.Id), child2.Path); + Assert.AreEqual(string.Format("-1,{0},{1},{2}", parent.Id, child1.Id, toddler1.Id), toddler1.Path); + Assert.AreEqual(string.Format("-1,{0},{1},{2}", parent.Id, child1.Id, toddler2.Id), toddler2.Path); + Assert.AreEqual(string.Format("-1,{0},{1},{2}", parent.Id, child2.Id, toddler3.Id), toddler3.Path); + Assert.AreEqual(string.Format("-1,{0},{1},{2}", parent.Id, child2.Id, toddler4.Id), toddler4.Path); + Assert.AreEqual(string.Format("-1,{0},{1},{2},{3}", parent.Id, child1.Id, toddler2.Id, baby1.Id), baby1.Path); + Assert.AreEqual(string.Format("-1,{0},{1},{2},{3}", parent.Id, child2.Id, toddler4.Id, baby2.Id), baby2.Path); + } - // // Act - // var scripts = repository.GetAll(); - // // Assert - // Assert.That(scripts, Is.Not.Null); - // Assert.That(scripts.Any(), Is.True); - // Assert.That(scripts.Any(x => x == null), Is.False); - // Assert.That(scripts.Count(), Is.EqualTo(4)); - //} + } - //[Test] - //public void Can_Perform_GetAll_With_Params_On_ScriptRepository() - //{ - // // Arrange - // var provider = new FileUnitOfWorkProvider(); - // var unitOfWork = provider.GetUnitOfWork(); - // var repository = new ScriptRepository(unitOfWork, _masterPageFileSystem); + [Test] + public void Path_Is_Set_Correctly_On_Update() + { + // Arrange + var provider = new PetaPocoUnitOfWorkProvider(Logger); + var unitOfWork = provider.GetUnitOfWork(); + using (var repository = CreateRepository(unitOfWork)) + { + var parent = new Template("parent", "parent"); + var child1 = new Template("child1", "child1"); + var child2 = new Template("child2", "child2"); + var toddler1 = new Template("toddler1", "toddler1"); + var toddler2 = new Template("toddler2", "toddler2"); - // var script = new Script("test-script1.js") { Content = "/// " }; - // repository.AddOrUpdate(script); - // var script2 = new Script("test-script2.js") { Content = "/// " }; - // repository.AddOrUpdate(script2); - // var script3 = new Script("test-script3.js") { Content = "/// " }; - // repository.AddOrUpdate(script3); - // unitOfWork.Commit(); + child1.MasterTemplateAlias = parent.Alias; + child1.MasterTemplateId = new Lazy(() => parent.Id); + child2.MasterTemplateAlias = parent.Alias; + child2.MasterTemplateId = new Lazy(() => parent.Id); + toddler1.MasterTemplateAlias = child1.Alias; + toddler1.MasterTemplateId = new Lazy(() => child1.Id); + toddler2.MasterTemplateAlias = child1.Alias; + toddler2.MasterTemplateId = new Lazy(() => child1.Id); - // // Act - // var scripts = repository.GetAll("test-script1.js", "test-script2.js"); + repository.AddOrUpdate(parent); + repository.AddOrUpdate(child1); + repository.AddOrUpdate(child2); + repository.AddOrUpdate(toddler1); + repository.AddOrUpdate(toddler2); + unitOfWork.Commit(); - // // Assert - // Assert.That(scripts, Is.Not.Null); - // Assert.That(scripts.Any(), Is.True); - // Assert.That(scripts.Any(x => x == null), Is.False); - // Assert.That(scripts.Count(), Is.EqualTo(2)); - //} + //Act + toddler2.SetMasterTemplate(child2); + repository.AddOrUpdate(toddler2); + unitOfWork.Commit(); - //[Test] - //public void Can_Perform_Exists_On_ScriptRepository() - //{ - // // Arrange - // var provider = new FileUnitOfWorkProvider(); - // var unitOfWork = provider.GetUnitOfWork(); - // var repository = new ScriptRepository(unitOfWork, _masterPageFileSystem); + //Assert + Assert.AreEqual(string.Format("-1,{0},{1},{2}", parent.Id, child2.Id, toddler2.Id), toddler2.Path); - // // Act - // var exists = repository.Exists("test-script.js"); + } + } - // // Assert - // Assert.That(exists, Is.True); - //} [TearDown] public override void TearDown() diff --git a/src/Umbraco.Tests/Persistence/Repositories/UserRepositoryTest.cs b/src/Umbraco.Tests/Persistence/Repositories/UserRepositoryTest.cs index 8d1e7dac1e..7f6051a62e 100644 --- a/src/Umbraco.Tests/Persistence/Repositories/UserRepositoryTest.cs +++ b/src/Umbraco.Tests/Persistence/Repositories/UserRepositoryTest.cs @@ -1,11 +1,13 @@ using System; using System.Collections.Generic; using System.Linq; +using Moq; using NUnit.Framework; using Umbraco.Core; +using Umbraco.Core.Logging; using Umbraco.Core.Models.Membership; using Umbraco.Core.Persistence; -using Umbraco.Core.Persistence.Caching; + using Umbraco.Core.Persistence.Querying; using Umbraco.Core.Persistence.Repositories; using Umbraco.Core.Persistence.UnitOfWork; @@ -32,30 +34,17 @@ namespace Umbraco.Tests.Persistence.Repositories private UserRepository CreateRepository(IDatabaseUnitOfWork unitOfWork, out UserTypeRepository userTypeRepository) { - userTypeRepository = new UserTypeRepository(unitOfWork, NullCacheProvider.Current); - var repository = new UserRepository(unitOfWork, NullCacheProvider.Current, userTypeRepository, CacheHelper.CreateDisabledCacheHelper()); + userTypeRepository = new UserTypeRepository(unitOfWork, CacheHelper.CreateDisabledCacheHelper(), Mock.Of(), SqlSyntaxProvider); + var repository = new UserRepository(unitOfWork, CacheHelper.CreateDisabledCacheHelper(), Mock.Of(), SqlSyntaxProvider, userTypeRepository); return repository; } - [Test] - public void Can_Instantiate_Repository_From_Resolver() - { - // Arrange - var provider = new PetaPocoUnitOfWorkProvider(); - var unitOfWork = provider.GetUnitOfWork(); - - // Act - var repository = RepositoryResolver.Current.ResolveByType(unitOfWork); - - // Assert - Assert.That(repository, Is.Not.Null); - } [Test] public void Can_Perform_Add_On_UserRepository() { // Arrange - var provider = new PetaPocoUnitOfWorkProvider(); + var provider = new PetaPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); UserTypeRepository userTypeRepository; using (var repository = CreateRepository(unitOfWork, out userTypeRepository)) @@ -76,7 +65,7 @@ namespace Umbraco.Tests.Persistence.Repositories public void Can_Perform_Multiple_Adds_On_UserRepository() { // Arrange - var provider = new PetaPocoUnitOfWorkProvider(); + var provider = new PetaPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); UserTypeRepository userTypeRepository; using (var repository = CreateRepository(unitOfWork, out userTypeRepository)) @@ -101,7 +90,7 @@ namespace Umbraco.Tests.Persistence.Repositories public void Can_Verify_Fresh_Entity_Is_Not_Dirty() { // Arrange - var provider = new PetaPocoUnitOfWorkProvider(); + var provider = new PetaPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); UserTypeRepository userTypeRepository; using (var repository = CreateRepository(unitOfWork, out userTypeRepository)) @@ -123,7 +112,7 @@ namespace Umbraco.Tests.Persistence.Repositories public void Can_Perform_Update_On_UserRepository() { // Arrange - var provider = new PetaPocoUnitOfWorkProvider(); + var provider = new PetaPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); UserTypeRepository userTypeRepository; using (var repository = CreateRepository(unitOfWork, out userTypeRepository)) @@ -173,7 +162,7 @@ namespace Umbraco.Tests.Persistence.Repositories public void Can_Perform_Delete_On_UserRepository() { // Arrange - var provider = new PetaPocoUnitOfWorkProvider(); + var provider = new PetaPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); UserTypeRepository userTypeRepository; using (var repository = CreateRepository(unitOfWork, out userTypeRepository)) @@ -186,14 +175,17 @@ namespace Umbraco.Tests.Persistence.Repositories unitOfWork.Commit(); var id = user.Id; - var repository2 = RepositoryResolver.Current.ResolveByType(unitOfWork); - repository2.Delete(user); - unitOfWork.Commit(); + using (var utRepo = new UserTypeRepository(unitOfWork, CacheHelper.CreateDisabledCacheHelper(), Logger, SqlSyntaxProvider)) + using (var repository2 = new UserRepository(unitOfWork, CacheHelper.CreateDisabledCacheHelper(), Logger, SqlSyntaxProvider, utRepo)) + { + repository2.Delete(user); + unitOfWork.Commit(); - var resolved = repository2.Get((int)id); + var resolved = repository2.Get((int) id); - // Assert - Assert.That(resolved, Is.Null); + // Assert + Assert.That(resolved, Is.Null); + } } } @@ -201,7 +193,7 @@ namespace Umbraco.Tests.Persistence.Repositories //public void Can_Perform_Delete_On_UserRepository_With_Permissions_Assigned() //{ // // Arrange - // var provider = new PetaPocoUnitOfWorkProvider(); + // var provider = new PetaPocoUnitOfWorkProvider(Logger); // var unitOfWork = provider.GetUnitOfWork(); // UserTypeRepository userTypeRepository; //using (var repository = CreateRepository(unitOfWork, out userTypeRepository)) @@ -231,7 +223,7 @@ namespace Umbraco.Tests.Persistence.Repositories public void Can_Perform_Get_On_UserRepository() { // Arrange - var provider = new PetaPocoUnitOfWorkProvider(); + var provider = new PetaPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); UserTypeRepository userTypeRepository; using (var repository = CreateRepository(unitOfWork, out userTypeRepository)) @@ -252,7 +244,7 @@ namespace Umbraco.Tests.Persistence.Repositories public void Can_Perform_GetByQuery_On_UserRepository() { // Arrange - var provider = new PetaPocoUnitOfWorkProvider(); + var provider = new PetaPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); UserTypeRepository userTypeRepository; using (var repository = CreateRepository(unitOfWork, out userTypeRepository)) @@ -272,7 +264,7 @@ namespace Umbraco.Tests.Persistence.Repositories public void Can_Perform_GetAll_By_Param_Ids_On_UserRepository() { // Arrange - var provider = new PetaPocoUnitOfWorkProvider(); + var provider = new PetaPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); UserTypeRepository userTypeRepository; using (var repository = CreateRepository(unitOfWork, out userTypeRepository)) @@ -293,7 +285,7 @@ namespace Umbraco.Tests.Persistence.Repositories public void Can_Perform_GetAll_On_UserRepository() { // Arrange - var provider = new PetaPocoUnitOfWorkProvider(); + var provider = new PetaPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); UserTypeRepository userTypeRepository; using (var repository = CreateRepository(unitOfWork, out userTypeRepository)) @@ -314,7 +306,7 @@ namespace Umbraco.Tests.Persistence.Repositories public void Can_Perform_Exists_On_UserRepository() { // Arrange - var provider = new PetaPocoUnitOfWorkProvider(); + var provider = new PetaPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); UserTypeRepository userTypeRepository; using (var repository = CreateRepository(unitOfWork, out userTypeRepository)) @@ -333,7 +325,7 @@ namespace Umbraco.Tests.Persistence.Repositories public void Can_Perform_Count_On_UserRepository() { // Arrange - var provider = new PetaPocoUnitOfWorkProvider(); + var provider = new PetaPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); UserTypeRepository userTypeRepository; using (var repository = CreateRepository(unitOfWork, out userTypeRepository)) @@ -353,7 +345,7 @@ namespace Umbraco.Tests.Persistence.Repositories public void Can_Remove_Section_For_User() { // Arrange - var provider = new PetaPocoUnitOfWorkProvider(); + var provider = new PetaPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); UserTypeRepository userTypeRepository; using (var repository = CreateRepository(unitOfWork, out userTypeRepository)) @@ -388,7 +380,7 @@ namespace Umbraco.Tests.Persistence.Repositories public void Can_Add_Section_For_User() { // Arrange - var provider = new PetaPocoUnitOfWorkProvider(); + var provider = new PetaPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); UserTypeRepository userTypeRepository; using (var repository = CreateRepository(unitOfWork, out userTypeRepository)) @@ -432,7 +424,7 @@ namespace Umbraco.Tests.Persistence.Repositories public void Can_Update_Section_For_User() { // Arrange - var provider = new PetaPocoUnitOfWorkProvider(); + var provider = new PetaPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); UserTypeRepository userTypeRepository; using (var repository = CreateRepository(unitOfWork, out userTypeRepository)) @@ -460,7 +452,7 @@ namespace Umbraco.Tests.Persistence.Repositories public void Get_Users_Assigned_To_Section() { // Arrange - var provider = new PetaPocoUnitOfWorkProvider(); + var provider = new PetaPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); UserTypeRepository userTypeRepository; using (var repository = CreateRepository(unitOfWork, out userTypeRepository)) @@ -489,22 +481,23 @@ namespace Umbraco.Tests.Persistence.Repositories public void Default_User_Permissions_Based_On_User_Type() { // Arrange - var provider = new PetaPocoUnitOfWorkProvider(); + var provider = new PetaPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); - var repository = RepositoryResolver.Current.ResolveByType(unitOfWork); - + using (var utRepo = new UserTypeRepository(unitOfWork, CacheHelper.CreateDisabledCacheHelper(), Logger, SqlSyntaxProvider)) + using (var repository = new UserRepository(unitOfWork, CacheHelper.CreateDisabledCacheHelper(), Logger, SqlSyntaxProvider, utRepo)) + { - // Act - var user1 = MockedUser.CreateUser(CreateAndCommitUserType(), "1", "test", "media"); - repository.AddOrUpdate(user1); - unitOfWork.Commit(); - - // Assert - Assert.AreEqual(3, user1.DefaultPermissions.Count()); - Assert.AreEqual("A", user1.DefaultPermissions.ElementAt(0)); - Assert.AreEqual("B", user1.DefaultPermissions.ElementAt(1)); - Assert.AreEqual("C", user1.DefaultPermissions.ElementAt(2)); + // Act + var user1 = MockedUser.CreateUser(CreateAndCommitUserType(), "1", "test", "media"); + repository.AddOrUpdate(user1); + unitOfWork.Commit(); + // Assert + Assert.AreEqual(3, user1.DefaultPermissions.Count()); + Assert.AreEqual("A", user1.DefaultPermissions.ElementAt(0)); + Assert.AreEqual("B", user1.DefaultPermissions.ElementAt(1)); + Assert.AreEqual("C", user1.DefaultPermissions.ElementAt(2)); + } } private void AssertPropertyValues(IUser updatedItem, IUser originalUser) @@ -539,13 +532,15 @@ namespace Umbraco.Tests.Persistence.Repositories private IUserType CreateAndCommitUserType() { - var provider = new PetaPocoUnitOfWorkProvider(); + var provider = new PetaPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); - var repository = RepositoryResolver.Current.ResolveByType(unitOfWork); - var userType = MockedUserType.CreateUserType(); - repository.AddOrUpdate(userType); - unitOfWork.Commit(); - return userType; + using (var repository = new UserTypeRepository(unitOfWork, CacheHelper.CreateDisabledCacheHelper(), Logger, SqlSyntaxProvider)) + { + var userType = MockedUserType.CreateUserType(); + repository.AddOrUpdate(userType); + unitOfWork.Commit(); + return userType; + } } } } \ No newline at end of file diff --git a/src/Umbraco.Tests/Persistence/Repositories/UserTypeRepositoryTest.cs b/src/Umbraco.Tests/Persistence/Repositories/UserTypeRepositoryTest.cs index 07212c0896..c84397049d 100644 --- a/src/Umbraco.Tests/Persistence/Repositories/UserTypeRepositoryTest.cs +++ b/src/Umbraco.Tests/Persistence/Repositories/UserTypeRepositoryTest.cs @@ -1,8 +1,11 @@ using System.Linq; +using Moq; using NUnit.Framework; +using Umbraco.Core; +using Umbraco.Core.Logging; using Umbraco.Core.Models.Membership; using Umbraco.Core.Persistence; -using Umbraco.Core.Persistence.Caching; + using Umbraco.Core.Persistence.Querying; using Umbraco.Core.Persistence.Repositories; using Umbraco.Core.Persistence.UnitOfWork; @@ -29,28 +32,14 @@ namespace Umbraco.Tests.Persistence.Repositories private UserTypeRepository CreateRepository(IDatabaseUnitOfWork unitOfWork) { - return new UserTypeRepository(unitOfWork, NullCacheProvider.Current); - } - - [Test] - public void Can_Instantiate_Repository_From_Resolver() - { - // Arrange - var provider = new PetaPocoUnitOfWorkProvider(); - var unitOfWork = provider.GetUnitOfWork(); - - // Act - var repository = RepositoryResolver.Current.ResolveByType(unitOfWork); - - // Assert - Assert.That(repository, Is.Not.Null); + return new UserTypeRepository(unitOfWork, CacheHelper.CreateDisabledCacheHelper(), Mock.Of(), SqlSyntaxProvider); } [Test] public void Can_Perform_Add_On_UserTypeRepository() { // Arrange - var provider = new PetaPocoUnitOfWorkProvider(); + var provider = new PetaPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); using (var repository = CreateRepository(unitOfWork)) { @@ -70,7 +59,7 @@ namespace Umbraco.Tests.Persistence.Repositories public void Can_Perform_Multiple_Adds_On_UserTypeRepository() { // Arrange - var provider = new PetaPocoUnitOfWorkProvider(); + var provider = new PetaPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); using (var repository = CreateRepository(unitOfWork)) { @@ -94,7 +83,7 @@ namespace Umbraco.Tests.Persistence.Repositories public void Can_Verify_Fresh_Entity_Is_Not_Dirty() { // Arrange - var provider = new PetaPocoUnitOfWorkProvider(); + var provider = new PetaPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); using (var repository = CreateRepository(unitOfWork)) { @@ -115,7 +104,7 @@ namespace Umbraco.Tests.Persistence.Repositories public void Can_Perform_Update_On_UserTypeRepository() { // Arrange - var provider = new PetaPocoUnitOfWorkProvider(); + var provider = new PetaPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); using (var repository = CreateRepository(unitOfWork)) { @@ -142,7 +131,7 @@ namespace Umbraco.Tests.Persistence.Repositories public void Can_Perform_Delete_On_UserTypeRepository() { // Arrange - var provider = new PetaPocoUnitOfWorkProvider(); + var provider = new PetaPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); using (var repository = CreateRepository(unitOfWork)) { @@ -154,14 +143,17 @@ namespace Umbraco.Tests.Persistence.Repositories unitOfWork.Commit(); var id = userType.Id; - var repository2 = RepositoryResolver.Current.ResolveByType(unitOfWork); - repository2.Delete(userType); - unitOfWork.Commit(); + using (var repository2 = new UserTypeRepository(unitOfWork, CacheHelper.CreateDisabledCacheHelper(), Logger, SqlSyntaxProvider)) + { + repository2.Delete(userType); + unitOfWork.Commit(); - var resolved = repository2.Get(id); + var resolved = repository2.Get(id); - // Assert - Assert.That(resolved, Is.Null); + // Assert + Assert.That(resolved, Is.Null); + } + } } @@ -169,7 +161,7 @@ namespace Umbraco.Tests.Persistence.Repositories public void Can_Perform_Get_On_UserTypeRepository() { // Arrange - var provider = new PetaPocoUnitOfWorkProvider(); + var provider = new PetaPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); using (var repository = CreateRepository(unitOfWork)) { @@ -194,7 +186,7 @@ namespace Umbraco.Tests.Persistence.Repositories public void Can_Perform_GetByQuery_On_UserTypeRepository() { // Arrange - var provider = new PetaPocoUnitOfWorkProvider(); + var provider = new PetaPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); using (var repository = CreateRepository(unitOfWork)) { @@ -213,7 +205,7 @@ namespace Umbraco.Tests.Persistence.Repositories public void Can_Perform_GetAll_By_Param_Ids_On_UserTypeRepository() { // Arrange - var provider = new PetaPocoUnitOfWorkProvider(); + var provider = new PetaPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); using (var repository = CreateRepository(unitOfWork)) { @@ -233,7 +225,7 @@ namespace Umbraco.Tests.Persistence.Repositories public void Can_Perform_GetAll_On_UserTypeRepository() { // Arrange - var provider = new PetaPocoUnitOfWorkProvider(); + var provider = new PetaPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); using (var repository = CreateRepository(unitOfWork)) { @@ -253,7 +245,7 @@ namespace Umbraco.Tests.Persistence.Repositories public void Can_Perform_Exists_On_UserTypeRepository() { // Arrange - var provider = new PetaPocoUnitOfWorkProvider(); + var provider = new PetaPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); using (var repository = CreateRepository(unitOfWork)) { @@ -271,7 +263,7 @@ namespace Umbraco.Tests.Persistence.Repositories public void Can_Perform_Count_On_UserTypeRepository() { // Arrange - var provider = new PetaPocoUnitOfWorkProvider(); + var provider = new PetaPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); using (var repository = CreateRepository(unitOfWork)) { diff --git a/src/Umbraco.Tests/Persistence/RepositoryResolverTests.cs b/src/Umbraco.Tests/Persistence/RepositoryResolverTests.cs deleted file mode 100644 index bd4d366c4e..0000000000 --- a/src/Umbraco.Tests/Persistence/RepositoryResolverTests.cs +++ /dev/null @@ -1,94 +0,0 @@ -using System; -using System.Reflection; -using NUnit.Framework; -using Umbraco.Core; -using Umbraco.Core.Models; -using Umbraco.Core.Models.Membership; -using Umbraco.Core.ObjectResolution; -using Umbraco.Core.Persistence; -using Umbraco.Core.Persistence.Repositories; -using Umbraco.Core.Persistence.UnitOfWork; - -namespace Umbraco.Tests.Persistence -{ - [TestFixture] - public class RepositoryResolverTests - { - - [SetUp] - public void Setup() - { - RepositoryResolver.Current = new RepositoryResolver( - new RepositoryFactory(true)); //disable all repo caches for tests! - - Resolution.Freeze(); - } - - [TearDown] - public void Teardown() - { - RepositoryResolver.Reset(); - } - - //[TestCase(typeof(IUserTypeRepository))] - //[TestCase(typeof(IUserRepository))] - //[TestCase(typeof(IMacroRepository))] - [TestCase(typeof(IContentRepository))] - [TestCase(typeof(IMediaRepository))] - [TestCase(typeof(IMediaTypeRepository))] - [TestCase(typeof(IContentTypeRepository))] - [TestCase(typeof(IDataTypeDefinitionRepository))] - [TestCase(typeof(IDictionaryRepository))] - [TestCase(typeof(ILanguageRepository))] - [TestCase(typeof(IRelationRepository))] - [TestCase(typeof(IRelationTypeRepository))] - [TestCase(typeof(IScriptRepository))] - //[TestCase(typeof(IStylesheetRepository))] - [TestCase(typeof(ITemplateRepository))] - public void ResolveRepository(Type repoType) - { - var method = typeof(RepositoryResolver).GetMethod("ResolveByType", BindingFlags.NonPublic | BindingFlags.Instance); - var gMethod = method.MakeGenericMethod(repoType); - var repo = gMethod.Invoke(RepositoryResolver.Current, new object[] { PetaPocoUnitOfWorkProvider.CreateUnitOfWork() }); - Assert.IsNotNull(repo); - Assert.IsTrue(TypeHelper.IsTypeAssignableFrom(repoType, repo.GetType())); - repo.DisposeIfDisposable(); - } - - [Test] - public void Can_Verify_UOW_In_Repository() - { - // Arrange - var uow = PetaPocoUnitOfWorkProvider.CreateUnitOfWork(); - - // Act - var repository = RepositoryResolver.Current.ResolveByType(uow); - - // Assert - Assert.That(repository, Is.Not.Null); - Assert.That(uow.Key, Is.EqualTo(((RepositoryBase)repository).UnitKey)); - - repository.Dispose(); - } - - [Test] - public void Type_Checking() - { - var repositoryType = typeof (IContentRepository); - bool isSubclassOf = repositoryType.IsSubclassOf(typeof(IRepository)); - bool isAssignableFrom = typeof(IRepository).IsAssignableFrom(repositoryType); - - Assert.That(isSubclassOf, Is.False); - Assert.That(isAssignableFrom, Is.True); - - var uow = PetaPocoUnitOfWorkProvider.CreateUnitOfWork(); - var repository = RepositoryResolver.Current.ResolveByType(uow); - bool subclassOf = repository.GetType().IsSubclassOf(typeof (IRepository)); - - Assert.That(subclassOf, Is.False); - Assert.That((typeof(IRepository).IsInstanceOfType(repository)), Is.True); - - repository.Dispose(); - } - } -} \ No newline at end of file diff --git a/src/Umbraco.Tests/Persistence/SchemaValidationTest.cs b/src/Umbraco.Tests/Persistence/SchemaValidationTest.cs index 14581378f9..26b5b49efb 100644 --- a/src/Umbraco.Tests/Persistence/SchemaValidationTest.cs +++ b/src/Umbraco.Tests/Persistence/SchemaValidationTest.cs @@ -1,6 +1,9 @@ -using NUnit.Framework; +using Moq; +using NUnit.Framework; using Umbraco.Core.Configuration; +using Umbraco.Core.Logging; using Umbraco.Core.Persistence.Migrations.Initial; +using Umbraco.Core.Persistence.SqlSyntax; using Umbraco.Tests.TestHelpers; namespace Umbraco.Tests.Persistence @@ -26,7 +29,7 @@ namespace Umbraco.Tests.Persistence { // Arrange var db = DatabaseContext.Database; - var schema = new DatabaseSchemaCreation(db); + var schema = new DatabaseSchemaCreation(db, Logger, new SqlCeSyntaxProvider()); // Act var result = schema.ValidateSchema(); diff --git a/src/Umbraco.Tests/Persistence/SqlCeTableByTableTest.cs b/src/Umbraco.Tests/Persistence/SqlCeTableByTableTest.cs index 54b427e2eb..d7115461db 100644 --- a/src/Umbraco.Tests/Persistence/SqlCeTableByTableTest.cs +++ b/src/Umbraco.Tests/Persistence/SqlCeTableByTableTest.cs @@ -21,6 +21,11 @@ namespace Umbraco.Tests.Persistence #region Overrides of BaseTableByTableTest + protected override ISqlSyntaxProvider SqlSyntaxProvider + { + get { return new SqlCeSyntaxProvider(); } + } + [SetUp] public override void Initialize() { @@ -38,8 +43,6 @@ namespace Umbraco.Tests.Persistence var engine = new SqlCeEngine("Datasource=|DataDirectory|test.sdf;Flush Interval=1;"); engine.CreateDatabase(); - SqlSyntaxContext.SqlSyntaxProvider = SqlCeSyntax.Provider; - _database = new Database("Datasource=|DataDirectory|test.sdf;Flush Interval=1;", "System.Data.SqlServerCe.4.0"); } diff --git a/src/Umbraco.Tests/Persistence/SqlTableByTableTest.cs b/src/Umbraco.Tests/Persistence/SqlTableByTableTest.cs index bdc9c45b00..f781d38447 100644 --- a/src/Umbraco.Tests/Persistence/SqlTableByTableTest.cs +++ b/src/Umbraco.Tests/Persistence/SqlTableByTableTest.cs @@ -19,13 +19,16 @@ namespace Umbraco.Tests.Persistence #region Overrides of BaseTableByTableTest + protected override ISqlSyntaxProvider SqlSyntaxProvider + { + get { return new SqlServerSyntaxProvider(); } + } + [SetUp] public override void Initialize() { base.Initialize(); - SqlSyntaxContext.SqlSyntaxProvider = SqlServerSyntax.Provider; - _database = new Database(@"server=.\SQLEXPRESS;database=EmptyForTest;user id=umbraco;password=umbraco", "System.Data.SqlClient"); } diff --git a/src/Umbraco.Tests/Persistence/SyntaxProvider/MySqlSyntaxProviderTests.cs b/src/Umbraco.Tests/Persistence/SyntaxProvider/MySqlSyntaxProviderTests.cs index 00319c2ccc..7b16e77171 100644 --- a/src/Umbraco.Tests/Persistence/SyntaxProvider/MySqlSyntaxProviderTests.cs +++ b/src/Umbraco.Tests/Persistence/SyntaxProvider/MySqlSyntaxProviderTests.cs @@ -1,5 +1,8 @@ using System; + +using Moq; using NUnit.Framework; +using Umbraco.Core.Logging; using Umbraco.Core.Models.Rdbms; using Umbraco.Core.Persistence.DatabaseModelDefinitions; using Umbraco.Core.Persistence.SqlSyntax; @@ -13,7 +16,7 @@ namespace Umbraco.Tests.Persistence.SyntaxProvider [SetUp] public void SetUp() { - SqlSyntaxContext.SqlSyntaxProvider = MySqlSyntax.Provider; + SqlSyntaxContext.SqlSyntaxProvider = new MySqlSyntaxProvider(Mock.Of()); } [Test] diff --git a/src/Umbraco.Tests/Persistence/SyntaxProvider/SqlCeSyntaxProviderTests.cs b/src/Umbraco.Tests/Persistence/SyntaxProvider/SqlCeSyntaxProviderTests.cs index 1c6eaca2bb..b574cb81bd 100644 --- a/src/Umbraco.Tests/Persistence/SyntaxProvider/SqlCeSyntaxProviderTests.cs +++ b/src/Umbraco.Tests/Persistence/SyntaxProvider/SqlCeSyntaxProviderTests.cs @@ -18,7 +18,7 @@ namespace Umbraco.Tests.Persistence.SyntaxProvider [SetUp] public void SetUp() { - SqlSyntaxContext.SqlSyntaxProvider = SqlCeSyntax.Provider; + SqlSyntaxContext.SqlSyntaxProvider = new SqlCeSyntaxProvider(); } [Test] @@ -73,7 +73,7 @@ WHERE ([umbracoNode].[nodeObjectType] = @0)) x)".Replace(Environment.NewLine, " [Test] public void Format_SqlServer_NonClusteredIndexDefinition_AddsNonClusteredDirective() { - SqlSyntaxContext.SqlSyntaxProvider = SqlServerSyntax.Provider; + SqlSyntaxContext.SqlSyntaxProvider = new SqlServerSyntaxProvider(); var indexDefinition = CreateIndexDefinition(); indexDefinition.IndexType = IndexTypes.NonClustered; @@ -85,7 +85,7 @@ WHERE ([umbracoNode].[nodeObjectType] = @0)) x)".Replace(Environment.NewLine, " [Test] public void Format_SqlServer_NonClusteredIndexDefinition_UsingIsClusteredFalse_AddsClusteredDirective() { - SqlSyntaxContext.SqlSyntaxProvider = SqlServerSyntax.Provider; + SqlSyntaxContext.SqlSyntaxProvider = new SqlServerSyntaxProvider(); var indexDefinition = CreateIndexDefinition(); indexDefinition.IsClustered = false; @@ -97,7 +97,7 @@ WHERE ([umbracoNode].[nodeObjectType] = @0)) x)".Replace(Environment.NewLine, " [Test] public void CreateIndexBuilder_SqlServer_NonClustered_CreatesNonClusteredIndex() { - SqlSyntaxContext.SqlSyntaxProvider = SqlServerSyntax.Provider; + SqlSyntaxContext.SqlSyntaxProvider = new SqlServerSyntaxProvider(); var createExpression = new CreateIndexExpression { Index = { Name = "IX_A" } }; var builder = new CreateIndexBuilder(createExpression); builder.OnTable("TheTable").OnColumn("A").Ascending().WithOptions().NonClustered(); @@ -107,7 +107,7 @@ WHERE ([umbracoNode].[nodeObjectType] = @0)) x)".Replace(Environment.NewLine, " [Test] public void CreateIndexBuilder_SqlServer_Unique_CreatesUniqueNonClusteredIndex() { - SqlSyntaxContext.SqlSyntaxProvider = SqlServerSyntax.Provider; + SqlSyntaxContext.SqlSyntaxProvider = new SqlServerSyntaxProvider(); var createExpression = new CreateIndexExpression { Index = { Name = "IX_A" } }; var builder = new CreateIndexBuilder(createExpression); builder.OnTable("TheTable").OnColumn("A").Ascending().WithOptions().Unique(); @@ -117,7 +117,7 @@ WHERE ([umbracoNode].[nodeObjectType] = @0)) x)".Replace(Environment.NewLine, " [Test] public void CreateIndexBuilder_SqlServer_Clustered_CreatesClusteredIndex() { - SqlSyntaxContext.SqlSyntaxProvider = SqlServerSyntax.Provider; + SqlSyntaxContext.SqlSyntaxProvider = new SqlServerSyntaxProvider(); var createExpression = new CreateIndexExpression { Index = { Name = "IX_A" } }; var builder = new CreateIndexBuilder(createExpression); builder.OnTable("TheTable").OnColumn("A").Ascending().WithOptions().Clustered(); diff --git a/src/Umbraco.Tests/Plugins/PluginManagerTests.cs b/src/Umbraco.Tests/Plugins/PluginManagerTests.cs index a8fae01850..e83a8eecaa 100644 --- a/src/Umbraco.Tests/Plugins/PluginManagerTests.cs +++ b/src/Umbraco.Tests/Plugins/PluginManagerTests.cs @@ -4,16 +4,19 @@ using System.Globalization; using System.IO; using System.Linq; using System.Reflection; +using Moq; using NUnit.Framework; using SqlCE4Umbraco; using umbraco; using umbraco.businesslogic; using umbraco.cms.businesslogic; using Umbraco.Core; +using Umbraco.Core.Cache; using Umbraco.Core.IO; +using Umbraco.Core.Logging; +using Umbraco.Core.Profiling; using Umbraco.Core.PropertyEditors; using umbraco.DataLayer; -using Umbraco.Tests.TestHelpers; using umbraco.uicontrols; using Umbraco.Web; using Umbraco.Web.PropertyEditors; @@ -24,18 +27,17 @@ namespace Umbraco.Tests.Plugins [TestFixture] public class PluginManagerTests { - + private PluginManager _manager; [SetUp] public void Initialize() { - TestHelper.SetupLog4NetForTests(); - //this ensures its reset - PluginManager.Current = new PluginManager(false); + _manager = new PluginManager(new ActivatorServiceProvider(), new NullCacheProvider(), + new ProfilingLogger(Mock.Of(), Mock.Of())); //for testing, we'll specify which assemblies are scanned for the PluginTypeResolver //TODO: Should probably update this so it only searches this assembly and add custom types to be found - PluginManager.Current.AssembliesToScan = new[] + _manager.AssembliesToScan = new[] { this.GetType().Assembly, typeof(ApplicationStartupHandler).Assembly, @@ -58,7 +60,7 @@ namespace Umbraco.Tests.Plugins [TearDown] public void TearDown() { - PluginManager.Current = null; + _manager = null; } private DirectoryInfo PrepareFolder() @@ -154,7 +156,7 @@ namespace Umbraco.Tests.Plugins public void Detect_Legacy_Plugin_File_List() { var tempFolder = IOHelper.MapPath("~/App_Data/TEMP/PluginCache"); - var manager = new PluginManager(false); + var filePath= Path.Combine(tempFolder, string.Format("umbraco-plugins.{0}.list", NetworkHelper.FileSafeMachineName)); File.WriteAllText(filePath, @" @@ -164,7 +166,7 @@ namespace Umbraco.Tests.Plugins "); - Assert.IsTrue(manager.DetectLegacyPluginListFile()); + Assert.IsTrue(_manager.DetectLegacyPluginListFile()); File.Delete(filePath); @@ -176,7 +178,7 @@ namespace Umbraco.Tests.Plugins "); - Assert.IsFalse(manager.DetectLegacyPluginListFile()); + Assert.IsFalse(_manager.DetectLegacyPluginListFile()); } [Test] @@ -184,12 +186,11 @@ namespace Umbraco.Tests.Plugins { var types = new[] { typeof(PluginManager), typeof(PluginManagerTests), typeof(UmbracoContext) }; - var manager = new PluginManager(false); //yes this is silly, none of these types inherit from string, but this is just to test the xml file format - manager.UpdateCachedPluginsFile(types, PluginManager.TypeResolutionKind.FindAllTypes); + _manager.UpdateCachedPluginsFile(types, PluginManager.TypeResolutionKind.FindAllTypes); - var plugins = manager.TryGetCachedPluginsFromFile(PluginManager.TypeResolutionKind.FindAllTypes); - var diffType = manager.TryGetCachedPluginsFromFile(PluginManager.TypeResolutionKind.FindAttributedTypes); + var plugins = _manager.TryGetCachedPluginsFromFile(PluginManager.TypeResolutionKind.FindAllTypes); + var diffType = _manager.TryGetCachedPluginsFromFile(PluginManager.TypeResolutionKind.FindAttributedTypes); Assert.IsTrue(plugins.Success); //this will be false since there is no cache of that type resolution kind @@ -235,69 +236,69 @@ namespace Umbraco.Tests.Plugins var list1 = new[] { f1, f2, f3, f4, f5, f6 }; var list2 = new[] { f1, f3, f5 }; var list3 = new[] { f1, f3, f5, f7 }; - + //Act - var hash1 = PluginManager.GetFileHash(list1); - var hash2 = PluginManager.GetFileHash(list2); - var hash3 = PluginManager.GetFileHash(list3); + var hash1 = PluginManager.GetFileHash(list1, new ProfilingLogger(Mock.Of(), Mock.Of())); + var hash2 = PluginManager.GetFileHash(list2, new ProfilingLogger(Mock.Of(), Mock.Of())); + var hash3 = PluginManager.GetFileHash(list3, new ProfilingLogger(Mock.Of(), Mock.Of())); //Assert Assert.AreNotEqual(hash1, hash2); Assert.AreNotEqual(hash1, hash3); Assert.AreNotEqual(hash2, hash3); - Assert.AreEqual(hash1, PluginManager.GetFileHash(list1)); + Assert.AreEqual(hash1, PluginManager.GetFileHash(list1, new ProfilingLogger(Mock.Of(), Mock.Of()))); } [Test] public void Ensure_Only_One_Type_List_Created() { - var foundTypes1 = PluginManager.Current.ResolveFindMeTypes(); - var foundTypes2 = PluginManager.Current.ResolveFindMeTypes(); + var foundTypes1 = _manager.ResolveFindMeTypes(); + var foundTypes2 = _manager.ResolveFindMeTypes(); Assert.AreEqual(1, - PluginManager.Current.GetTypeLists() + _manager.GetTypeLists() .Count(x => x.IsTypeList(PluginManager.TypeResolutionKind.FindAllTypes))); } [Test] public void Resolves_Assigned_Mappers() { - var foundTypes1 = PluginManager.Current.ResolveAssignedMapperTypes(); + var foundTypes1 = _manager.ResolveAssignedMapperTypes(); Assert.AreEqual(23, foundTypes1.Count()); } [Test] public void Resolves_Types() { - var foundTypes1 = PluginManager.Current.ResolveFindMeTypes(); + var foundTypes1 = _manager.ResolveFindMeTypes(); Assert.AreEqual(2, foundTypes1.Count()); } [Test] public void Resolves_Attributed_Trees() { - var trees = PluginManager.Current.ResolveAttributedTrees(); + var trees = _manager.ResolveAttributedTrees(); Assert.AreEqual(19, trees.Count()); } [Test] public void Resolves_Actions() { - var actions = PluginManager.Current.ResolveActions(); + var actions = _manager.ResolveActions(); Assert.AreEqual(36, actions.Count()); } [Test] public void Resolves_Trees() { - var trees = PluginManager.Current.ResolveTrees(); + var trees = _manager.ResolveTrees(); Assert.AreEqual(39, trees.Count()); } [Test] public void Resolves_Applications() { - var apps = PluginManager.Current.ResolveApplications(); + var apps = _manager.ResolveApplications(); Assert.AreEqual(7, apps.Count()); } @@ -305,7 +306,7 @@ namespace Umbraco.Tests.Plugins [Test] public void Resolves_XsltExtensions() { - var types = PluginManager.Current.ResolveXsltExtensions(); + var types = _manager.ResolveXsltExtensions(); Assert.AreEqual(3, types.Count()); } diff --git a/src/Umbraco.Tests/Plugins/TypeFinderTests.cs b/src/Umbraco.Tests/Plugins/TypeFinderTests.cs index 0616e7ef94..9b01a8c814 100644 --- a/src/Umbraco.Tests/Plugins/TypeFinderTests.cs +++ b/src/Umbraco.Tests/Plugins/TypeFinderTests.cs @@ -19,7 +19,6 @@ using Umbraco.Core; using Umbraco.Core.IO; using umbraco.DataLayer; using umbraco.interfaces; -using Umbraco.Tests.TestHelpers; using umbraco.uicontrols; namespace Umbraco.Tests.Plugins @@ -39,9 +38,7 @@ namespace Umbraco.Tests.Plugins [SetUp] public void Initialize() { - TestHelper.SetupLog4NetForTests(); - - _assemblies = new[] + _assemblies = new[] { this.GetType().Assembly, typeof(ApplicationStartupHandler).Assembly, diff --git a/src/Umbraco.Tests/PublishedContent/PublishedContentMoreTests.cs b/src/Umbraco.Tests/PublishedContent/PublishedContentMoreTests.cs index d320c5f844..7c74d093ba 100644 --- a/src/Umbraco.Tests/PublishedContent/PublishedContentMoreTests.cs +++ b/src/Umbraco.Tests/PublishedContent/PublishedContentMoreTests.cs @@ -3,6 +3,7 @@ using System.Collections.ObjectModel; using System.Web.Routing; using NUnit.Framework; using Umbraco.Core; +using Umbraco.Core.Cache; using Umbraco.Core.Models; using Umbraco.Core.Models.PublishedContent; using Umbraco.Core.ObjectResolution; @@ -31,7 +32,7 @@ namespace Umbraco.Tests.PublishedContent // this is so the model factory looks into the test assembly _pluginManager = PluginManager.Current; - PluginManager.Current = new PluginManager(false) + PluginManager.Current = new PluginManager(new ActivatorServiceProvider(), new NullCacheProvider(), ProfilingLogger, false) { AssembliesToScan = _pluginManager.AssembliesToScan .Union(new[] { typeof (PublishedContentMoreTests).Assembly}) @@ -43,7 +44,7 @@ namespace Umbraco.Tests.PublishedContent protected override void FreezeResolution() { PropertyValueConvertersResolver.Current = - new PropertyValueConvertersResolver(); + new PropertyValueConvertersResolver(new ActivatorServiceProvider(), Logger); var types = PluginManager.Current.ResolveTypes(); PublishedContentModelFactoryResolver.Current = new PublishedContentModelFactoryResolver(new PublishedContentModelFactory(types)); diff --git a/src/Umbraco.Tests/PublishedContent/PublishedContentTestBase.cs b/src/Umbraco.Tests/PublishedContent/PublishedContentTestBase.cs index 478335af15..789d9f7218 100644 --- a/src/Umbraco.Tests/PublishedContent/PublishedContentTestBase.cs +++ b/src/Umbraco.Tests/PublishedContent/PublishedContentTestBase.cs @@ -41,6 +41,7 @@ namespace Umbraco.Tests.PublishedContent { if (PropertyValueConvertersResolver.HasCurrent == false) PropertyValueConvertersResolver.Current = new PropertyValueConvertersResolver( + new ActivatorServiceProvider(), Logger, new[] { typeof(DatePickerValueConverter), diff --git a/src/Umbraco.Tests/PublishedContent/PublishedContentTests.cs b/src/Umbraco.Tests/PublishedContent/PublishedContentTests.cs index 343d9359e8..a61dd793b2 100644 --- a/src/Umbraco.Tests/PublishedContent/PublishedContentTests.cs +++ b/src/Umbraco.Tests/PublishedContent/PublishedContentTests.cs @@ -30,7 +30,7 @@ namespace Umbraco.Tests.PublishedContent // this is so the model factory looks into the test assembly _pluginManager = PluginManager.Current; - PluginManager.Current = new PluginManager(false) + PluginManager.Current = new PluginManager(new ActivatorServiceProvider(), CacheHelper.RuntimeCache, ProfilingLogger, false) { AssembliesToScan = _pluginManager.AssembliesToScan .Union(new[] { typeof(PublishedContentTests).Assembly }) diff --git a/src/Umbraco.Tests/Resolvers/ActionsResolverTests.cs b/src/Umbraco.Tests/Resolvers/ActionsResolverTests.cs index 47ba900ae6..08049c5480 100644 --- a/src/Umbraco.Tests/Resolvers/ActionsResolverTests.cs +++ b/src/Umbraco.Tests/Resolvers/ActionsResolverTests.cs @@ -1,7 +1,11 @@ using System.Linq; +using Moq; using NUnit.Framework; using Umbraco.Core; +using Umbraco.Core.Cache; +using Umbraco.Core.Logging; using Umbraco.Core.ObjectResolution; +using Umbraco.Core.Profiling; using Umbraco.Tests.TestHelpers; using umbraco.BasePages; using umbraco.interfaces; @@ -9,30 +13,13 @@ using umbraco.interfaces; namespace Umbraco.Tests.Resolvers { [TestFixture] - public class ActionsResolverTests - { - [SetUp] - public void Initialize() - { - TestHelper.SetupLog4NetForTests(); - - ActionsResolver.Reset(); - - // this ensures it's reset - PluginManager.Current = new PluginManager(false); - - // for testing, we'll specify which assemblies are scanned for the PluginTypeResolver - PluginManager.Current.AssembliesToScan = new[] - { - this.GetType().Assembly // this assembly only - }; - } - + public class ActionsResolverTests : ResolverBaseTest + { + [TearDown] public void TearDown() { ActionsResolver.Reset(); - PluginManager.Current = null; } // NOTE @@ -44,7 +31,8 @@ namespace Umbraco.Tests.Resolvers public void FindAllActions() { ActionsResolver.Current = new ActionsResolver( - () => PluginManager.Current.ResolveActions()); + new ActivatorServiceProvider(), ProfilingLogger.Logger, + () => PluginManager.ResolveActions()); Resolution.Freeze(); diff --git a/src/Umbraco.Tests/Resolvers/LazyManyObjectResolverTests.cs b/src/Umbraco.Tests/Resolvers/LazyManyObjectResolverTests.cs index 66549d82dd..1f85aa2a47 100644 --- a/src/Umbraco.Tests/Resolvers/LazyManyObjectResolverTests.cs +++ b/src/Umbraco.Tests/Resolvers/LazyManyObjectResolverTests.cs @@ -5,7 +5,6 @@ using System.Linq; using NUnit.Framework; using Umbraco.Core; using Umbraco.Core.ObjectResolution; -using Umbraco.Tests.TestHelpers; namespace Umbraco.Tests.Resolvers { @@ -16,9 +15,7 @@ namespace Umbraco.Tests.Resolvers [SetUp] public void Initialize() { - TestHelper.SetupLog4NetForTests(); - - LazyResolver.Reset(); + LazyResolver.Reset(); } [TearDown] diff --git a/src/Umbraco.Tests/Resolvers/MacroFieldEditorsResolverTests.cs b/src/Umbraco.Tests/Resolvers/MacroFieldEditorsResolverTests.cs index 1e6759c45a..b1dfc4c58e 100644 --- a/src/Umbraco.Tests/Resolvers/MacroFieldEditorsResolverTests.cs +++ b/src/Umbraco.Tests/Resolvers/MacroFieldEditorsResolverTests.cs @@ -5,37 +5,18 @@ using NUnit.Framework; using Umbraco.Core; using Umbraco.Core.Macros; using Umbraco.Core.ObjectResolution; -using Umbraco.Tests.TestHelpers; using umbraco.interfaces; namespace Umbraco.Tests.Resolvers { [TestFixture] - public class MacroFieldEditorsResolverTests + public class MacroFieldEditorsResolverTests : ResolverBaseTest { - [SetUp] - public void Initialize() - { - TestHelper.SetupLog4NetForTests(); - - MacroFieldEditorsResolver.Reset(); - - - // this ensures it's reset - PluginManager.Current = new PluginManager(false); - - // for testing, we'll specify which assemblies are scanned for the PluginTypeResolver - PluginManager.Current.AssembliesToScan = new[] - { - this.GetType().Assembly - }; - } - + [TearDown] public void TearDown() { MacroFieldEditorsResolver.Reset(); - PluginManager.Current = null; } // NOTE @@ -46,7 +27,8 @@ namespace Umbraco.Tests.Resolvers public void FindAllTypes() { MacroFieldEditorsResolver.Current = new MacroFieldEditorsResolver( - () => PluginManager.Current.ResolveMacroRenderings()); + new ActivatorServiceProvider(), ProfilingLogger.Logger, + () => PluginManager.ResolveMacroRenderings()); Resolution.Freeze(); diff --git a/src/Umbraco.Tests/Resolvers/ManyResolverTests.cs b/src/Umbraco.Tests/Resolvers/ManyResolverTests.cs index 06b0daca63..dbeb790102 100644 --- a/src/Umbraco.Tests/Resolvers/ManyResolverTests.cs +++ b/src/Umbraco.Tests/Resolvers/ManyResolverTests.cs @@ -18,8 +18,6 @@ namespace Umbraco.Tests.Resolvers [SetUp] public void Setup() { - TestHelper.SetupLog4NetForTests(); - ManyResolver.Reset(); } diff --git a/src/Umbraco.Tests/Resolvers/PackageActionsResolverTests.cs b/src/Umbraco.Tests/Resolvers/PackageActionsResolverTests.cs index baee392bf4..8026f0bd99 100644 --- a/src/Umbraco.Tests/Resolvers/PackageActionsResolverTests.cs +++ b/src/Umbraco.Tests/Resolvers/PackageActionsResolverTests.cs @@ -9,31 +9,14 @@ using umbraco.interfaces; namespace Umbraco.Tests.Resolvers { - [TestFixture] - public class PackageActionsResolverTests - { - [SetUp] - public void Initialize() - { - TestHelper.SetupLog4NetForTests(); - - PackageActionsResolver.Reset(); - - // ensures it's reset - PluginManager.Current = new PluginManager(false); - - // for testing, we'll specify which assemblies are scanned for the PluginTypeResolver - PluginManager.Current.AssembliesToScan = new[] - { - this.GetType().Assembly // this assembly only - }; - } + [TestFixture] + public class PackageActionsResolverTests : ResolverBaseTest + { [TearDown] public void TearDown() { PackageActionsResolver.Reset(); - PluginManager.Current = null; } // NOTE @@ -44,7 +27,8 @@ namespace Umbraco.Tests.Resolvers public void FindAllPackageActions() { PackageActionsResolver.Current = new PackageActionsResolver( - () => PluginManager.Current.ResolvePackageActions()); + new ActivatorServiceProvider(), ProfilingLogger.Logger, + () => PluginManager.ResolvePackageActions()); Resolution.Freeze(); diff --git a/src/Umbraco.Tests/Resolvers/ResolutionTests.cs b/src/Umbraco.Tests/Resolvers/ResolutionTests.cs index 37cf8bcb04..9dc3166616 100644 --- a/src/Umbraco.Tests/Resolvers/ResolutionTests.cs +++ b/src/Umbraco.Tests/Resolvers/ResolutionTests.cs @@ -5,8 +5,6 @@ using System.Text; using Umbraco.Core; using Umbraco.Core.ObjectResolution; -using Umbraco.Tests.TestHelpers; - using NUnit.Framework; namespace Umbraco.Tests.Resolvers @@ -17,7 +15,6 @@ namespace Umbraco.Tests.Resolvers [SetUp] public void Setup() { - TestHelper.SetupLog4NetForTests(); } [TearDown] diff --git a/src/Umbraco.Tests/Resolvers/ResolverBaseTest.cs b/src/Umbraco.Tests/Resolvers/ResolverBaseTest.cs new file mode 100644 index 0000000000..b5fa17f235 --- /dev/null +++ b/src/Umbraco.Tests/Resolvers/ResolverBaseTest.cs @@ -0,0 +1,44 @@ +using System.Collections.Generic; +using System.Reflection; +using Moq; +using NUnit.Framework; +using Umbraco.Core; +using Umbraco.Core.Cache; +using Umbraco.Core.Logging; +using Umbraco.Core.Profiling; + +namespace Umbraco.Tests.Resolvers +{ + public abstract class ResolverBaseTest + { + protected PluginManager PluginManager { get; private set; } + protected ProfilingLogger ProfilingLogger { get; private set; } + + [SetUp] + public void Initialize() + { + + PackageActionsResolver.Reset(); + + ProfilingLogger = new ProfilingLogger(Mock.Of(), Mock.Of()); + + PluginManager = new PluginManager(new ActivatorServiceProvider(), new NullCacheProvider(), + ProfilingLogger, + false) + { + AssembliesToScan = AssembliesToScan + }; + } + + protected virtual IEnumerable AssembliesToScan + { + get + { + return new[] + { + this.GetType().Assembly // this assembly only + }; + } + } + } +} \ No newline at end of file diff --git a/src/Umbraco.Tests/Resolvers/SingleResolverTests.cs b/src/Umbraco.Tests/Resolvers/SingleResolverTests.cs index 581fa98f1c..c97360307c 100644 --- a/src/Umbraco.Tests/Resolvers/SingleResolverTests.cs +++ b/src/Umbraco.Tests/Resolvers/SingleResolverTests.cs @@ -5,8 +5,6 @@ using System.Text; using Umbraco.Core; using Umbraco.Core.ObjectResolution; -using Umbraco.Tests.TestHelpers; - using NUnit.Framework; namespace Umbraco.Tests.Resolvers @@ -17,8 +15,6 @@ namespace Umbraco.Tests.Resolvers [SetUp] public void Setup() { - TestHelper.SetupLog4NetForTests(); - SingleResolver.Reset(); } diff --git a/src/Umbraco.Tests/Resolvers/XsltExtensionsResolverTests.cs b/src/Umbraco.Tests/Resolvers/XsltExtensionsResolverTests.cs index 8b06c99f60..84bb735578 100644 --- a/src/Umbraco.Tests/Resolvers/XsltExtensionsResolverTests.cs +++ b/src/Umbraco.Tests/Resolvers/XsltExtensionsResolverTests.cs @@ -1,9 +1,12 @@ using System.Linq; +using Moq; using NUnit.Framework; using Umbraco.Core; +using Umbraco.Core.Cache; +using Umbraco.Core.Logging; using Umbraco.Core.Macros; using Umbraco.Core.ObjectResolution; -using Umbraco.Tests.TestHelpers; +using Umbraco.Core.Profiling; using Umbraco.Web; using Umbraco.Web.Macros; using umbraco; @@ -11,30 +14,12 @@ using umbraco; namespace Umbraco.Tests.Resolvers { [TestFixture] - public class XsltExtensionsResolverTests + public class XsltExtensionsResolverTests : ResolverBaseTest { - [SetUp] - public void Initialize() - { - TestHelper.SetupLog4NetForTests(); - - ActionsResolver.Reset(); - - // this ensures it's reset - PluginManager.Current = new PluginManager(false); - - // for testing, we'll specify which assemblies are scanned for the PluginTypeResolver - PluginManager.Current.AssembliesToScan = new[] - { - this.GetType().Assembly // this assembly only - }; - } - [TearDown] public void TearDown() { ActionsResolver.Reset(); - PluginManager.Current = null; } // NOTE @@ -46,7 +31,8 @@ namespace Umbraco.Tests.Resolvers public void Find_All_Extensions() { XsltExtensionsResolver.Current = new XsltExtensionsResolver( - () => PluginManager.Current.ResolveXsltExtensions()); + new ActivatorServiceProvider(),ProfilingLogger.Logger, + () => PluginManager.ResolveXsltExtensions()); Resolution.Freeze(); diff --git a/src/Umbraco.Tests/Routing/RenderRouteHandlerTests.cs b/src/Umbraco.Tests/Routing/RenderRouteHandlerTests.cs index 47ff544fed..9744f189aa 100644 --- a/src/Umbraco.Tests/Routing/RenderRouteHandlerTests.cs +++ b/src/Umbraco.Tests/Routing/RenderRouteHandlerTests.cs @@ -1,7 +1,9 @@ using System.Web.Mvc; using System.Web.Routing; +using Moq; using NUnit.Framework; using Umbraco.Core; +using Umbraco.Core.Logging; using Umbraco.Core.Models; using Umbraco.Tests.TestHelpers; using Umbraco.Tests.TestHelpers.Stubs; @@ -38,8 +40,10 @@ namespace Umbraco.Tests.Routing DefaultRenderMvcControllerResolver.Current = new DefaultRenderMvcControllerResolver(typeof(RenderMvcController)); SurfaceControllerResolver.Current = new SurfaceControllerResolver( + new ActivatorServiceProvider(), Logger, PluginManager.Current.ResolveSurfaceControllers()); UmbracoApiControllerResolver.Current = new UmbracoApiControllerResolver( + new ActivatorServiceProvider(), Logger, PluginManager.Current.ResolveUmbracoApiControllers()); ShortStringHelperResolver.Current = new ShortStringHelperResolver(new LegacyShortStringHelper()); @@ -80,7 +84,9 @@ namespace Umbraco.Tests.Routing RenderingEngine = RenderingEngine.Mvc }; - var handler = new RenderRouteHandler(new TestControllerFactory(), routingContext.UmbracoContext); + var handler = new RenderRouteHandler( + new TestControllerFactory(routingContext.UmbracoContext, Mock.Of()), + routingContext.UmbracoContext); handler.GetHandlerForRoute(routingContext.UmbracoContext.HttpContext.Request.RequestContext, docRequest); Assert.AreEqual("RenderMvc", routeData.Values["controller"].ToString()); @@ -116,7 +122,9 @@ namespace Umbraco.Tests.Routing TemplateModel = template }; - var handler = new RenderRouteHandler(new TestControllerFactory(), routingContext.UmbracoContext); + var handler = new RenderRouteHandler( + new TestControllerFactory(routingContext.UmbracoContext, Mock.Of()), + routingContext.UmbracoContext); handler.GetHandlerForRoute(routingContext.UmbracoContext.HttpContext.Request.RequestContext, docRequest); Assert.AreEqual("CustomDocument", routeData.Values["controller"].ToString()); @@ -152,8 +160,11 @@ namespace Umbraco.Tests.Routing /// public class CustomDocumentController : RenderMvcController { + public CustomDocumentController(UmbracoContext umbracoContext) : base(umbracoContext) + { + } - public ActionResult HomePage(RenderModel model) + public ActionResult HomePage(RenderModel model) { return View(); } diff --git a/src/Umbraco.Tests/Services/ContentServicePerformanceTest.cs b/src/Umbraco.Tests/Services/ContentServicePerformanceTest.cs index 3f2e22bf66..d7509cf68e 100644 --- a/src/Umbraco.Tests/Services/ContentServicePerformanceTest.cs +++ b/src/Umbraco.Tests/Services/ContentServicePerformanceTest.cs @@ -2,8 +2,11 @@ using System.Collections.Generic; using System.Diagnostics; using System.Linq; +using Moq; using NUnit.Framework; using Umbraco.Core; +using Umbraco.Core.Configuration.UmbracoSettings; +using Umbraco.Core.IO; using Umbraco.Core.Logging; using Umbraco.Core.Models; using Umbraco.Core.Models.Rdbms; @@ -49,10 +52,10 @@ namespace Umbraco.Tests.Services // ... NOPE, made even more nice changes, it is now... // 4452ms !!!!!!! - var contentType1 = MockedContentTypes.CreateTextpageContentType("test1", "test1"); + var contentType1 = MockedContentTypes.CreateTextpageContentType("test1", "test1"); var contentType2 = MockedContentTypes.CreateTextpageContentType("test2", "test2"); - var contentType3 = MockedContentTypes.CreateTextpageContentType("test3", "test3"); - ServiceContext.ContentTypeService.Save(new[] {contentType1, contentType2, contentType3}); + var contentType3 = MockedContentTypes.CreateTextpageContentType("test3", "test3"); + ServiceContext.ContentTypeService.Save(new[] { contentType1, contentType2, contentType3 }); contentType1.AllowedContentTypes = new[] { new ContentTypeSort(new Lazy(() => contentType2.Id), 0, contentType2.Alias), @@ -69,7 +72,7 @@ namespace Umbraco.Tests.Services new ContentTypeSort(new Lazy(() => contentType2.Id), 1, contentType2.Alias) }; ServiceContext.ContentTypeService.Save(new[] { contentType1, contentType2, contentType3 }); - + var roots = MockedContent.CreateTextpageContent(contentType1, -1, 10); ServiceContext.ContentService.Save(roots); foreach (var root in roots) @@ -142,21 +145,28 @@ namespace Umbraco.Tests.Services var pages = MockedContent.CreateTextpageContent(contentType, -1, 100); ServiceContext.ContentService.Save(pages, 0); - var provider = new PetaPocoUnitOfWorkProvider(); + var provider = new PetaPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); - var repository = RepositoryResolver.Current.ResolveByType(unitOfWork); - // Act - Stopwatch watch = Stopwatch.StartNew(); - var contents = repository.GetAll(); - watch.Stop(); - var elapsed = watch.ElapsedMilliseconds; + using (var tRepository = new TemplateRepository(unitOfWork, CacheHelper.CreateDisabledCacheHelper(), Logger, SqlSyntaxProvider, Mock.Of(), Mock.Of(), Mock.Of())) + using (var tagRepo = new TagRepository(unitOfWork, CacheHelper.CreateDisabledCacheHelper(), Logger, SqlSyntaxProvider)) + using (var ctRepository = new ContentTypeRepository(unitOfWork, CacheHelper.CreateDisabledCacheHelper(), Logger, SqlSyntaxProvider, tRepository)) + using (var repository = new ContentRepository(unitOfWork, CacheHelper.CreateDisabledCacheHelper(), Logger, SqlSyntaxProvider, ctRepository, tRepository, tagRepo)) + { + // Act + Stopwatch watch = Stopwatch.StartNew(); + var contents = repository.GetAll(); + watch.Stop(); + var elapsed = watch.ElapsedMilliseconds; + + Console.WriteLine("100 content items retrieved in {0} ms without caching", elapsed); + + // Assert + Assert.That(contents.Any(x => x.HasIdentity == false), Is.False); + Assert.That(contents.Any(x => x == null), Is.False); + } - Console.WriteLine("100 content items retrieved in {0} ms without caching", elapsed); - // Assert - Assert.That(contents.Any(x => x.HasIdentity == false), Is.False); - Assert.That(contents.Any(x => x == null), Is.False); } [Test, NUnit.Framework.Ignore] @@ -167,21 +177,25 @@ namespace Umbraco.Tests.Services var pages = MockedContent.CreateTextpageContent(contentType, -1, 1000); ServiceContext.ContentService.Save(pages, 0); - var provider = new PetaPocoUnitOfWorkProvider(); + var provider = new PetaPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); - var repository = RepositoryResolver.Current.ResolveByType(unitOfWork); + using (var tRepository = new TemplateRepository(unitOfWork, CacheHelper.CreateDisabledCacheHelper(), Logger, SqlSyntaxProvider, Mock.Of(), Mock.Of(), Mock.Of())) + using (var tagRepo = new TagRepository(unitOfWork, CacheHelper.CreateDisabledCacheHelper(), Logger, SqlSyntaxProvider)) + using (var ctRepository = new ContentTypeRepository(unitOfWork, CacheHelper.CreateDisabledCacheHelper(), Logger, SqlSyntaxProvider, tRepository)) + using (var repository = new ContentRepository(unitOfWork, CacheHelper.CreateDisabledCacheHelper(), Logger, SqlSyntaxProvider, ctRepository, tRepository, tagRepo)) + { + // Act + Stopwatch watch = Stopwatch.StartNew(); + var contents = repository.GetAll(); + watch.Stop(); + var elapsed = watch.ElapsedMilliseconds; - // Act - Stopwatch watch = Stopwatch.StartNew(); - var contents = repository.GetAll(); - watch.Stop(); - var elapsed = watch.ElapsedMilliseconds; + Console.WriteLine("1000 content items retrieved in {0} ms without caching", elapsed); - Console.WriteLine("1000 content items retrieved in {0} ms without caching", elapsed); - - // Assert - //Assert.That(contents.Any(x => x.HasIdentity == false), Is.False); - //Assert.That(contents.Any(x => x == null), Is.False); + // Assert + //Assert.That(contents.Any(x => x.HasIdentity == false), Is.False); + //Assert.That(contents.Any(x => x == null), Is.False); + } } [Test] @@ -192,24 +206,30 @@ namespace Umbraco.Tests.Services var pages = MockedContent.CreateTextpageContent(contentType, -1, 100); ServiceContext.ContentService.Save(pages, 0); - var provider = new PetaPocoUnitOfWorkProvider(); + var provider = new PetaPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); - var repository = RepositoryResolver.Current.ResolveByType(unitOfWork); - // Act - var contents = repository.GetAll(); + using (var tRepository = new TemplateRepository(unitOfWork, CacheHelper.CreateDisabledCacheHelper(), Logger, SqlSyntaxProvider, Mock.Of(), Mock.Of(), Mock.Of())) + using (var tagRepo = new TagRepository(unitOfWork, CacheHelper.CreateDisabledCacheHelper(), Logger, SqlSyntaxProvider)) + using (var ctRepository = new ContentTypeRepository(unitOfWork, CacheHelper.CreateDisabledCacheHelper(), Logger, SqlSyntaxProvider, tRepository)) + using (var repository = new ContentRepository(unitOfWork, CacheHelper.CreateDisabledCacheHelper(), Logger, SqlSyntaxProvider, ctRepository, tRepository, tagRepo)) + { - Stopwatch watch = Stopwatch.StartNew(); - var contentsCached = repository.GetAll(); - watch.Stop(); - var elapsed = watch.ElapsedMilliseconds; + // Act + var contents = repository.GetAll(); - Console.WriteLine("100 content items retrieved in {0} ms with caching", elapsed); + Stopwatch watch = Stopwatch.StartNew(); + var contentsCached = repository.GetAll(); + watch.Stop(); + var elapsed = watch.ElapsedMilliseconds; - // Assert - Assert.That(contentsCached.Any(x => x.HasIdentity == false), Is.False); - Assert.That(contentsCached.Any(x => x == null), Is.False); - Assert.That(contentsCached.Count(), Is.EqualTo(contents.Count())); + Console.WriteLine("100 content items retrieved in {0} ms with caching", elapsed); + + // Assert + Assert.That(contentsCached.Any(x => x.HasIdentity == false), Is.False); + Assert.That(contentsCached.Any(x => x == null), Is.False); + Assert.That(contentsCached.Count(), Is.EqualTo(contents.Count())); + } } [Test, NUnit.Framework.Ignore] @@ -220,24 +240,29 @@ namespace Umbraco.Tests.Services var pages = MockedContent.CreateTextpageContent(contentType, -1, 1000); ServiceContext.ContentService.Save(pages, 0); - var provider = new PetaPocoUnitOfWorkProvider(); + var provider = new PetaPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); - var repository = RepositoryResolver.Current.ResolveByType(unitOfWork); + using (var tRepository = new TemplateRepository(unitOfWork, CacheHelper.CreateDisabledCacheHelper(), Logger, SqlSyntaxProvider, Mock.Of(), Mock.Of(), Mock.Of())) + using (var tagRepo = new TagRepository(unitOfWork, CacheHelper.CreateDisabledCacheHelper(), Logger, SqlSyntaxProvider)) + using (var ctRepository = new ContentTypeRepository(unitOfWork, CacheHelper.CreateDisabledCacheHelper(), Logger, SqlSyntaxProvider, tRepository)) + using (var repository = new ContentRepository(unitOfWork, CacheHelper.CreateDisabledCacheHelper(), Logger, SqlSyntaxProvider, ctRepository, tRepository, tagRepo)) + { - // Act - var contents = repository.GetAll(); + // Act + var contents = repository.GetAll(); - Stopwatch watch = Stopwatch.StartNew(); - var contentsCached = repository.GetAll(); - watch.Stop(); - var elapsed = watch.ElapsedMilliseconds; + Stopwatch watch = Stopwatch.StartNew(); + var contentsCached = repository.GetAll(); + watch.Stop(); + var elapsed = watch.ElapsedMilliseconds; - Console.WriteLine("1000 content items retrieved in {0} ms with caching", elapsed); + Console.WriteLine("1000 content items retrieved in {0} ms with caching", elapsed); - // Assert - //Assert.That(contentsCached.Any(x => x.HasIdentity == false), Is.False); - //Assert.That(contentsCached.Any(x => x == null), Is.False); - //Assert.That(contentsCached.Count(), Is.EqualTo(contents.Count())); + // Assert + //Assert.That(contentsCached.Any(x => x.HasIdentity == false), Is.False); + //Assert.That(contentsCached.Any(x => x == null), Is.False); + //Assert.That(contentsCached.Count(), Is.EqualTo(contents.Count())); + } } [TearDown] diff --git a/src/Umbraco.Tests/Services/ContentServiceTests.cs b/src/Umbraco.Tests/Services/ContentServiceTests.cs index 5714ec2c9f..5c469cdcd8 100644 --- a/src/Umbraco.Tests/Services/ContentServiceTests.cs +++ b/src/Umbraco.Tests/Services/ContentServiceTests.cs @@ -2,7 +2,12 @@ using System.Collections.Generic; using System.Linq; using System.Threading; +using Moq; using NUnit.Framework; +using Umbraco.Core; +using Umbraco.Core.Configuration.UmbracoSettings; +using Umbraco.Core.IO; +using Umbraco.Core.Logging; using Umbraco.Core.Models; using Umbraco.Core.Models.Membership; using Umbraco.Core.Models.Rdbms; @@ -715,12 +720,9 @@ namespace Umbraco.Tests.Services var content = contentService.GetById(NodeDto.NodeIdSeed + 1); bool published = contentService.Publish(content, 0); - var provider = new PetaPocoUnitOfWorkProvider(); + var provider = new PetaPocoUnitOfWorkProvider(Logger); var uow = provider.GetUnitOfWork(); - using (RepositoryResolver.Current.ResolveByType(uow)) - { - Assert.IsTrue(uow.Database.Exists(content.Id)); - } + Assert.IsTrue(uow.Database.Exists(content.Id)); // Act bool unpublished = contentService.UnPublish(content, 0); @@ -731,10 +733,7 @@ namespace Umbraco.Tests.Services Assert.That(content.Published, Is.False); uow = provider.GetUnitOfWork(); - using (RepositoryResolver.Current.ResolveByType(uow)) - { - Assert.IsFalse(uow.Database.Exists(content.Id)); - } + Assert.IsFalse(uow.Database.Exists(content.Id)); } /// @@ -783,12 +782,13 @@ 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(); - var uow = provider.GetUnitOfWork(); - using (RepositoryResolver.Current.ResolveByType(uow)) + var provider = new PetaPocoUnitOfWorkProvider(Logger); + using (var uow = provider.GetUnitOfWork()) { - uow.Database.TruncateTable("cmsContentXml"); + uow.Database.TruncateTable("cmsContentXml"); } + + //for this test we are also going to save a revision for a content item that is not published, this is to ensure //that it's published version still makes it into the cmsContentXml table! contentService.Save(allContent.Last()); @@ -798,10 +798,9 @@ namespace Umbraco.Tests.Services // Assert Assert.IsTrue(published); - uow = provider.GetUnitOfWork(); - using (var repo = RepositoryResolver.Current.ResolveByType(uow)) + using (var uow = provider.GetUnitOfWork()) { - Assert.AreEqual(allContent.Count(), uow.Database.ExecuteScalar("select count(*) from cmsContentXml")); + Assert.AreEqual(allContent.Count(), uow.Database.ExecuteScalar("select count(*) from cmsContentXml")); } } @@ -817,9 +816,9 @@ 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(); - var uow = provider.GetUnitOfWork(); - using (RepositoryResolver.Current.ResolveByType(uow)) + var provider = new PetaPocoUnitOfWorkProvider(Logger); + + using (var uow = provider.GetUnitOfWork()) { uow.Database.TruncateTable("cmsContentXml"); } @@ -831,8 +830,7 @@ namespace Umbraco.Tests.Services contentService.RePublishAll(new int[]{allContent.Last().ContentTypeId}); // Assert - uow = provider.GetUnitOfWork(); - using (var repo = RepositoryResolver.Current.ResolveByType(uow)) + using (var uow = provider.GetUnitOfWork()) { Assert.AreEqual(allContent.Count(), uow.Database.ExecuteScalar("select count(*) from cmsContentXml")); } @@ -1263,7 +1261,7 @@ namespace Umbraco.Tests.Services [Test] public void Can_Save_Lazy_Content() { - var unitOfWork = PetaPocoUnitOfWorkProvider.CreateUnitOfWork(); + var unitOfWork = PetaPocoUnitOfWorkProvider.CreateUnitOfWork(Mock.Of()); var contentType = ServiceContext.ContentTypeService.GetContentType("umbTextpage"); var root = ServiceContext.ContentService.GetById(NodeDto.NodeIdSeed + 1); @@ -1271,21 +1269,25 @@ namespace Umbraco.Tests.Services var c2 = new Lazy(() => MockedContent.CreateSimpleContent(contentType, "Hierarchy Simple Text Subpage", c.Value.Id)); var list = new List> {c, c2}; - var repository = RepositoryResolver.Current.ResolveByType(unitOfWork); - foreach (var content in list) + ContentTypeRepository contentTypeRepository; + using (var repository = CreateRepository(unitOfWork, out contentTypeRepository)) { - repository.AddOrUpdate(content.Value); - unitOfWork.Commit(); + foreach (var content in list) + { + repository.AddOrUpdate(content.Value); + unitOfWork.Commit(); + } + + Assert.That(c.Value.HasIdentity, Is.True); + Assert.That(c2.Value.HasIdentity, Is.True); + + Assert.That(c.Value.Id > 0, Is.True); + Assert.That(c2.Value.Id > 0, Is.True); + + Assert.That(c.Value.ParentId > 0, Is.True); + Assert.That(c2.Value.ParentId > 0, Is.True); } - - Assert.That(c.Value.HasIdentity, Is.True); - Assert.That(c2.Value.HasIdentity, Is.True); - - Assert.That(c.Value.Id > 0, Is.True); - Assert.That(c2.Value.Id > 0, Is.True); - - Assert.That(c.Value.ParentId > 0, Is.True); - Assert.That(c2.Value.ParentId > 0, Is.True); + } [Test] @@ -1373,17 +1375,16 @@ namespace Umbraco.Tests.Services contentService.Save(content); - var provider = new PetaPocoUnitOfWorkProvider(); - var uow = provider.GetUnitOfWork(); - using (RepositoryResolver.Current.ResolveByType(uow)) + var provider = new PetaPocoUnitOfWorkProvider(Logger); + + using (var uow = provider.GetUnitOfWork()) { Assert.IsFalse(uow.Database.Exists(content.Id)); } contentService.Publish(content); - uow = provider.GetUnitOfWork(); - using (RepositoryResolver.Current.ResolveByType(uow)) + using (var uow = provider.GetUnitOfWork()) { Assert.IsTrue(uow.Database.Exists(content.Id)); } @@ -1398,9 +1399,9 @@ namespace Umbraco.Tests.Services contentService.Save(content); - var provider = new PetaPocoUnitOfWorkProvider(); - var uow = provider.GetUnitOfWork(); - using (RepositoryResolver.Current.ResolveByType(uow)) + var provider = new PetaPocoUnitOfWorkProvider(Logger); + + using (var uow = provider.GetUnitOfWork()) { Assert.IsTrue(uow.Database.SingleOrDefault("WHERE nodeId=@nodeId AND versionId = @versionId", new{nodeId = content.Id, versionId = content.Version}) != null); } @@ -1438,5 +1439,14 @@ namespace Umbraco.Tests.Services } return list; } + + private ContentRepository CreateRepository(IDatabaseUnitOfWork unitOfWork, out ContentTypeRepository contentTypeRepository) + { + var templateRepository = new TemplateRepository(unitOfWork, CacheHelper.CreateDisabledCacheHelper(), Mock.Of(), SqlSyntaxProvider, Mock.Of(), Mock.Of(), Mock.Of()); + var tagRepository = new TagRepository(unitOfWork, CacheHelper.CreateDisabledCacheHelper(), Mock.Of(), SqlSyntaxProvider); + contentTypeRepository = new ContentTypeRepository(unitOfWork, CacheHelper.CreateDisabledCacheHelper(), Mock.Of(), SqlSyntaxProvider, templateRepository); + var repository = new ContentRepository(unitOfWork, CacheHelper.CreateDisabledCacheHelper(), Mock.Of(), SqlSyntaxProvider, contentTypeRepository, templateRepository, tagRepository); + return repository; + } } } \ No newline at end of file diff --git a/src/Umbraco.Tests/Services/ContentTypeServiceTests.cs b/src/Umbraco.Tests/Services/ContentTypeServiceTests.cs index f430a93e23..1bb3abde7c 100644 --- a/src/Umbraco.Tests/Services/ContentTypeServiceTests.cs +++ b/src/Umbraco.Tests/Services/ContentTypeServiceTests.cs @@ -6,7 +6,7 @@ using System.Linq; using Umbraco.Core; using Umbraco.Core.Models; using Umbraco.Core.Models.Rdbms; -using Umbraco.Core.Persistence.Caching; + using Umbraco.Tests.CodeFirst.TestModels.Composition; using Umbraco.Tests.TestHelpers; using Umbraco.Tests.TestHelpers.Entities; diff --git a/src/Umbraco.Tests/Services/FileServiceTests.cs b/src/Umbraco.Tests/Services/FileServiceTests.cs new file mode 100644 index 0000000000..38f93c9195 --- /dev/null +++ b/src/Umbraco.Tests/Services/FileServiceTests.cs @@ -0,0 +1,72 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Runtime.InteropServices; +using System.Text; +using System.Threading.Tasks; +using NUnit.Framework; +using Umbraco.Tests.TestHelpers; + +namespace Umbraco.Tests.Services +{ + [DatabaseTestBehavior(DatabaseBehavior.NewDbFileAndSchemaPerTest)] + [TestFixture, RequiresSTA] + public class FileServiceTests : BaseServiceTest + { + + [SetUp] + public override void Initialize() + { + base.Initialize(); + } + + [TearDown] + public override void TearDown() + { + base.TearDown(); + } + + [Test] + public void Create_Template_Then_Assign_Child() + { + var child = ServiceContext.FileService.CreateTemplateWithIdentity("child", "test"); + var parent = ServiceContext.FileService.CreateTemplateWithIdentity("parent", "test"); + + child.SetMasterTemplate(parent); + ServiceContext.FileService.SaveTemplate(child); + + child = ServiceContext.FileService.GetTemplate(child.Id); + + Assert.AreEqual(parent.Alias, child.MasterTemplateAlias); + + } + + [Test] + public void Create_Template_With_Child_Then_Unassign() + { + var parent = ServiceContext.FileService.CreateTemplateWithIdentity("parent", "test"); + var child = ServiceContext.FileService.CreateTemplateWithIdentity("child", "test", parent); + + child.SetMasterTemplate(null); + ServiceContext.FileService.SaveTemplate(child); + + child = ServiceContext.FileService.GetTemplate(child.Id); + + Assert.AreEqual(null, child.MasterTemplateAlias); + } + + [Test] + public void Can_Query_Template_Children() + { + var parent = ServiceContext.FileService.CreateTemplateWithIdentity("parent", "test"); + var child1 = ServiceContext.FileService.CreateTemplateWithIdentity("child1", "test", parent); + var child2 = ServiceContext.FileService.CreateTemplateWithIdentity("child2", "test", parent); + + var children = ServiceContext.FileService.GetTemplates(parent.Id).Select(x => x.Id).ToArray(); + + Assert.IsTrue(children.Contains(child1.Id)); + Assert.IsTrue(children.Contains(child2.Id)); + } + + } +} diff --git a/src/Umbraco.Tests/Services/LocalizationServiceTests.cs b/src/Umbraco.Tests/Services/LocalizationServiceTests.cs index 0d78f56939..a4dcaff25b 100644 --- a/src/Umbraco.Tests/Services/LocalizationServiceTests.cs +++ b/src/Umbraco.Tests/Services/LocalizationServiceTests.cs @@ -2,6 +2,7 @@ using System.Collections.Generic; using System.Linq; using NUnit.Framework; +using Umbraco.Core; using Umbraco.Core.Models; using Umbraco.Tests.TestHelpers; @@ -36,7 +37,7 @@ namespace Umbraco.Tests.Services } [Test] - public void LocalizationService_Can_Get_Root_Dictionary_Items() + public void Can_Get_Root_Dictionary_Items() { var rootItems = ServiceContext.LocalizationService.GetRootDictionaryItems(); @@ -45,14 +46,14 @@ namespace Umbraco.Tests.Services } [Test] - public void LocalizationService_Can_Determint_If_DictionaryItem_Exists() + public void Can_Determint_If_DictionaryItem_Exists() { var exists = ServiceContext.LocalizationService.DictionaryItemExists("Parent"); Assert.IsTrue(exists); } [Test] - public void LocalizationService_Can_Get_All_Languages() + public void Can_Get_All_Languages() { var languages = ServiceContext.LocalizationService.GetAllLanguages(); Assert.NotNull(languages); @@ -61,7 +62,7 @@ namespace Umbraco.Tests.Services } [Test] - public void LocalizationService_Can_Get_Dictionary_Item_By_Int_Id() + public void Can_Get_Dictionary_Item_By_Int_Id() { var parentItem = ServiceContext.LocalizationService.GetDictionaryItemById(_parentItemIntId); Assert.NotNull(parentItem); @@ -71,7 +72,7 @@ namespace Umbraco.Tests.Services } [Test] - public void LocalizationService_Can_Get_Dictionary_Item_By_Guid_Id() + public void Can_Get_Dictionary_Item_By_Guid_Id() { var parentItem = ServiceContext.LocalizationService.GetDictionaryItemById(_parentItemGuidId); Assert.NotNull(parentItem); @@ -81,7 +82,7 @@ namespace Umbraco.Tests.Services } [Test] - public void LocalizationService_Can_Get_Dictionary_Item_By_Key() + public void Can_Get_Dictionary_Item_By_Key() { var parentItem = ServiceContext.LocalizationService.GetDictionaryItemByKey("Parent"); Assert.NotNull(parentItem); @@ -91,7 +92,7 @@ namespace Umbraco.Tests.Services } [Test] - public void LocalizationService_Can_Get_Dictionary_Item_Children() + public void Can_Get_Dictionary_Item_Children() { var item = ServiceContext.LocalizationService.GetDictionaryItemChildren(_parentItemGuidId); Assert.NotNull(item); @@ -104,7 +105,7 @@ namespace Umbraco.Tests.Services } [Test] - public void LocalizationService_Can_Get_Language_By_Culture_Code() + public void Can_Get_Language_By_Culture_Code() { var danish = ServiceContext.LocalizationService.GetLanguageByCultureCode("Danish"); var english = ServiceContext.LocalizationService.GetLanguageByCultureCode("English"); @@ -113,7 +114,7 @@ namespace Umbraco.Tests.Services } [Test] - public void LocalizationService_Can_GetLanguageById() + public void Can_GetLanguageById() { var danish = ServiceContext.LocalizationService.GetLanguageById(_danishLangId); var english = ServiceContext.LocalizationService.GetLanguageById(_englishLangId); @@ -122,7 +123,7 @@ namespace Umbraco.Tests.Services } [Test] - public void LocalizationService_Can_GetLanguageByIsoCode() + public void Can_GetLanguageByIsoCode() { var danish = ServiceContext.LocalizationService.GetLanguageByIsoCode("da-DK"); var english = ServiceContext.LocalizationService.GetLanguageByIsoCode("en-GB"); @@ -131,21 +132,21 @@ namespace Umbraco.Tests.Services } [Test] - public void LocalizationService_Does_Not_Fail_When_Language_Doesnt_Exist() + public void Does_Not_Fail_When_Language_Doesnt_Exist() { var language = ServiceContext.LocalizationService.GetLanguageByIsoCode("sv-SE"); Assert.Null(language); } [Test] - public void LocalizationService_Does_Not_Fail_When_DictionaryItem_Doesnt_Exist() + public void Does_Not_Fail_When_DictionaryItem_Doesnt_Exist() { var item = ServiceContext.LocalizationService.GetDictionaryItemByKey("RandomKey"); Assert.Null(item); } [Test] - public void LocalizationService_Can_Delete_Language() + public void Can_Delete_Language() { var norwegian = new Language("nb-NO") { CultureName = "Norwegian" }; ServiceContext.LocalizationService.Save(norwegian, 0); @@ -159,7 +160,96 @@ namespace Umbraco.Tests.Services } [Test] - public void LocalizationService_Can_Delete_DictionaryItem() + public void Can_Create_DictionaryItem_At_Root() + { + var english = ServiceContext.LocalizationService.GetLanguageByIsoCode("en-US"); + + var item = (IDictionaryItem)new DictionaryItem("Testing123") + { + Translations = new List + { + new DictionaryTranslation(english, "Hello world") + } + }; + ServiceContext.LocalizationService.Save(item); + + //re-get + item = ServiceContext.LocalizationService.GetDictionaryItemById(item.Id); + + Assert.Greater(item.Id, 0); + Assert.IsTrue(item.HasIdentity); + Assert.AreEqual(new Guid(Constants.Conventions.Localization.DictionaryItemRootId), item.ParentId); + Assert.AreEqual("Testing123", item.ItemKey); + Assert.AreEqual(1, item.Translations.Count()); + } + + [Test] + public void Can_Create_DictionaryItem_At_Root_With_Identity() + { + + var item = ServiceContext.LocalizationService.CreateDictionaryItemWithIdentity( + "Testing12345", null, "Hellooooo"); + + //re-get + item = ServiceContext.LocalizationService.GetDictionaryItemById(item.Id); + + Assert.IsNotNull(item); + Assert.Greater(item.Id, 0); + Assert.IsTrue(item.HasIdentity); + Assert.AreEqual(new Guid(Constants.Conventions.Localization.DictionaryItemRootId), item.ParentId); + Assert.AreEqual("Testing12345", item.ItemKey); + var allLangs = ServiceContext.LocalizationService.GetAllLanguages(); + Assert.Greater(allLangs.Count(), 0); + foreach (var language in allLangs) + { + Assert.AreEqual("Hellooooo", item.Translations.Single(x => x.Language.CultureName == language.CultureName).Value); + } + + } + + [Test] + public void Can_Add_Translation_To_Existing_Dictionary_Item() + { + var english = ServiceContext.LocalizationService.GetLanguageByIsoCode("en-US"); + + var item = (IDictionaryItem) new DictionaryItem("Testing123"); + ServiceContext.LocalizationService.Save(item); + + //re-get + item = ServiceContext.LocalizationService.GetDictionaryItemById(item.Id); + + item.Translations = new List + { + new DictionaryTranslation(english, "Hello world") + }; + + ServiceContext.LocalizationService.Save(item); + + Assert.AreEqual(1, item.Translations.Count()); + foreach (var translation in item.Translations) + { + Assert.AreEqual("Hello world", translation.Value); + } + + item.Translations = new List(item.Translations) + { + new DictionaryTranslation( + ServiceContext.LocalizationService.GetLanguageByIsoCode("en-GB"), + "My new value") + }; + + ServiceContext.LocalizationService.Save(item); + + //re-get + item = ServiceContext.LocalizationService.GetDictionaryItemById(item.Id); + + Assert.AreEqual(2, item.Translations.Count()); + Assert.AreEqual("Hello world", item.Translations.First().Value); + Assert.AreEqual("My new value", item.Translations.Last().Value); + } + + [Test] + public void Can_Delete_DictionaryItem() { var item = ServiceContext.LocalizationService.GetDictionaryItemByKey("Child"); Assert.NotNull(item); @@ -171,7 +261,7 @@ namespace Umbraco.Tests.Services } [Test] - public void LocalizationService_Can_Update_Existing_DictionaryItem() + public void Can_Update_Existing_DictionaryItem() { var item = ServiceContext.LocalizationService.GetDictionaryItemByKey("Child"); foreach (var translation in item.Translations) @@ -190,40 +280,6 @@ namespace Umbraco.Tests.Services } } - public override void CreateTestData() - { - var danish = new Language("da-DK") { CultureName = "Danish" }; - var english = new Language("en-GB") { CultureName = "English"}; - ServiceContext.LocalizationService.Save(danish, 0); - ServiceContext.LocalizationService.Save(english, 0); - _danishLangId = danish.Id; - _englishLangId = english.Id; - - var parentItem = new DictionaryItem("Parent") - { - Translations = new List - { - new DictionaryTranslation(english, "ParentValue"), - new DictionaryTranslation(danish, "ForældreVærdi") - } - }; - ServiceContext.LocalizationService.Save(parentItem); - _parentItemGuidId = parentItem.Key; - _parentItemIntId = parentItem.Id; - - var childItem = new DictionaryItem(parentItem.Key, "Child") - { - Translations = new List - { - new DictionaryTranslation(english, "ChildValue"), - new DictionaryTranslation(danish, "BørnVærdi") - } - }; - ServiceContext.LocalizationService.Save(childItem); - _childItemGuidId = childItem.Key; - _childItemIntId = childItem.Id; - } - [Test] public void Find_BaseData_Language() { @@ -284,5 +340,39 @@ namespace Umbraco.Tests.Services Assert.Null(result); } + public override void CreateTestData() + { + var danish = new Language("da-DK") { CultureName = "Danish" }; + var english = new Language("en-GB") { CultureName = "English" }; + ServiceContext.LocalizationService.Save(danish, 0); + ServiceContext.LocalizationService.Save(english, 0); + _danishLangId = danish.Id; + _englishLangId = english.Id; + + var parentItem = new DictionaryItem("Parent") + { + Translations = new List + { + new DictionaryTranslation(english, "ParentValue"), + new DictionaryTranslation(danish, "ForældreVærdi") + } + }; + ServiceContext.LocalizationService.Save(parentItem); + _parentItemGuidId = parentItem.Key; + _parentItemIntId = parentItem.Id; + + var childItem = new DictionaryItem(parentItem.Key, "Child") + { + Translations = new List + { + new DictionaryTranslation(english, "ChildValue"), + new DictionaryTranslation(danish, "BørnVærdi") + } + }; + ServiceContext.LocalizationService.Save(childItem); + _childItemGuidId = childItem.Key; + _childItemIntId = childItem.Id; + } + } } \ No newline at end of file diff --git a/src/Umbraco.Tests/Services/LocalizedTextServiceTests.cs b/src/Umbraco.Tests/Services/LocalizedTextServiceTests.cs index 97ed516846..3a492c84c7 100644 --- a/src/Umbraco.Tests/Services/LocalizedTextServiceTests.cs +++ b/src/Umbraco.Tests/Services/LocalizedTextServiceTests.cs @@ -5,7 +5,9 @@ using System.Linq; using System.Text; using System.Threading.Tasks; using System.Xml.Linq; +using Moq; using NUnit.Framework; +using Umbraco.Core.Logging; using Umbraco.Core.Services; namespace Umbraco.Tests.Services @@ -59,8 +61,7 @@ namespace Umbraco.Tests.Services public void Using_XDocument_Gets_All_Stored_Values() { var culture = CultureInfo.GetCultureInfo("en-US"); - var txtService = new LocalizedTextService( - new Dictionary> + var txtService = new LocalizedTextService(new Dictionary> { { culture, new Lazy(() => new XDocument( @@ -72,7 +73,7 @@ namespace Umbraco.Tests.Services new XElement("key", new XAttribute("alias", "blah1"), "blahValue1"), new XElement("key", new XAttribute("alias", "blah2"), "blahValue2"))))) } - }); + }, Mock.Of()); var result = txtService.GetAllStoredValues(culture); @@ -103,7 +104,7 @@ namespace Umbraco.Tests.Services new XElement("key", new XAttribute("alias", "testKey1"), "testValue1"), new XElement("key", new XAttribute("alias", "testKey1"), "testValue1"))))) } - }); + }, Mock.Of()); var result = txtService.GetAllStoredValues(culture); @@ -251,7 +252,7 @@ namespace Umbraco.Tests.Services new XElement("key", new XAttribute("alias", "testKey"), "testValue")))) } - }); + }, Mock.Of()); var result = txtService.Localize("testArea/testKey", culture); @@ -271,7 +272,7 @@ namespace Umbraco.Tests.Services new XElement("key", new XAttribute("alias", "testKey"), "testValue")))) } - }); + }, Mock.Of()); var result = txtService.Localize("testKey", culture); @@ -291,7 +292,7 @@ namespace Umbraco.Tests.Services new XElement("key", new XAttribute("alias", "testKey"), "testValue")))) } - }); + }, Mock.Of()); var result = txtService.Localize("testArea/doNotFind", culture); @@ -312,7 +313,7 @@ namespace Umbraco.Tests.Services new XElement("key", new XAttribute("alias", "testKey"), "testValue")))) } - }); + }, Mock.Of()); var result = txtService.Localize("doNotFind", culture); @@ -332,7 +333,7 @@ namespace Umbraco.Tests.Services new XElement("key", new XAttribute("alias", "testKey"), "Hello %0%, you are such a %1% %2%")))) } - }); + }, Mock.Of()); var result = txtService.Localize("testKey", culture, new Dictionary { { "0", "world" }, { "1", "great" }, { "2", "planet" } }); @@ -364,7 +365,7 @@ namespace Umbraco.Tests.Services } [Test] - public void Using_XDocument_Throws_When_No_Culture_Found() + public void Using_XDocument_Returns_Default_Text_When_No_Culture_Found() { var culture = CultureInfo.GetCultureInfo("en-US"); var txtService = new LocalizedTextService( @@ -376,9 +377,9 @@ namespace Umbraco.Tests.Services new XElement("key", new XAttribute("alias", "testKey"), "testValue")))) } - }); + }, Mock.Of()); - Assert.Throws(() => txtService.Localize("testArea/testKey", CultureInfo.GetCultureInfo("en-AU"))); + Assert.AreEqual("[testKey]", txtService.Localize("testArea/testKey", CultureInfo.GetCultureInfo("en-AU"))); } } } diff --git a/src/Umbraco.Tests/Services/MacroServiceTests.cs b/src/Umbraco.Tests/Services/MacroServiceTests.cs index 9f81ffab9a..4d4a0ee4f0 100644 --- a/src/Umbraco.Tests/Services/MacroServiceTests.cs +++ b/src/Umbraco.Tests/Services/MacroServiceTests.cs @@ -1,6 +1,10 @@ using System.Linq; +using Moq; using NUnit.Framework; +using Umbraco.Core; +using Umbraco.Core.Logging; using Umbraco.Core.Models; + using Umbraco.Core.Persistence.Repositories; using Umbraco.Core.Persistence.UnitOfWork; using Umbraco.Tests.TestHelpers; @@ -21,9 +25,9 @@ namespace Umbraco.Tests.Services { base.CreateTestData(); - var provider = new PetaPocoUnitOfWorkProvider(); + var provider = new PetaPocoUnitOfWorkProvider(Logger); using (var unitOfWork = provider.GetUnitOfWork()) - using (var repository = new MacroRepository(unitOfWork)) + using (var repository = new MacroRepository(unitOfWork, CacheHelper.CreateDisabledCacheHelper(), Mock.Of(), SqlSyntaxProvider)) { repository.AddOrUpdate(new Macro("test1", "Test1", "~/usercontrol/test1.ascx", "MyAssembly1", "test1.xslt", "~/views/macropartials/test1.cshtml")); repository.AddOrUpdate(new Macro("test2", "Test2", "~/usercontrol/test2.ascx", "MyAssembly2", "test2.xslt", "~/views/macropartials/test2.cshtml")); diff --git a/src/Umbraco.Tests/Services/MediaServiceTests.cs b/src/Umbraco.Tests/Services/MediaServiceTests.cs index 4f76f4f7f8..12d4b4b0aa 100644 --- a/src/Umbraco.Tests/Services/MediaServiceTests.cs +++ b/src/Umbraco.Tests/Services/MediaServiceTests.cs @@ -90,12 +90,10 @@ namespace Umbraco.Tests.Services mediaService.Save(media); - var provider = new PetaPocoUnitOfWorkProvider(); + var provider = new PetaPocoUnitOfWorkProvider(Logger); var uow = provider.GetUnitOfWork(); - using (RepositoryResolver.Current.ResolveByType(uow)) - { - Assert.IsTrue(uow.Database.Exists(media.Id)); - } + + Assert.IsTrue(uow.Database.Exists(media.Id)); } diff --git a/src/Umbraco.Tests/Services/MemberServiceTests.cs b/src/Umbraco.Tests/Services/MemberServiceTests.cs index 5a52bca4f9..d9cb75e587 100644 --- a/src/Umbraco.Tests/Services/MemberServiceTests.cs +++ b/src/Umbraco.Tests/Services/MemberServiceTests.cs @@ -1066,9 +1066,9 @@ namespace Umbraco.Tests.Services var customMember = MockedMember.CreateSimpleMember(memberType, "hello", "hello@test.com", "hello", "hello"); ServiceContext.MemberService.Save(customMember); - var provider = new PetaPocoUnitOfWorkProvider(); - var uow = provider.GetUnitOfWork(); - using (RepositoryResolver.Current.ResolveByType(uow)) + var provider = new PetaPocoUnitOfWorkProvider(Logger); + + using (var uow = provider.GetUnitOfWork()) { Assert.IsTrue(uow.Database.Exists(customMember.Id)); } diff --git a/src/Umbraco.Tests/Services/PerformanceTests.cs b/src/Umbraco.Tests/Services/PerformanceTests.cs index 7e754b6635..438705eec8 100644 --- a/src/Umbraco.Tests/Services/PerformanceTests.cs +++ b/src/Umbraco.Tests/Services/PerformanceTests.cs @@ -11,7 +11,7 @@ using Umbraco.Core; using Umbraco.Core.Models; using Umbraco.Core.Models.Rdbms; using Umbraco.Core.Persistence; -using Umbraco.Core.Persistence.Caching; + using Umbraco.Core.Persistence.Repositories; using Umbraco.Core.Persistence.SqlSyntax; using Umbraco.Core.Persistence.UnitOfWork; @@ -75,8 +75,6 @@ namespace Umbraco.Tests.Services //do this 10x! for (var i = 0; i < 10; i++) { - //clear the cache to make this test valid - RuntimeCacheProvider.Current.Clear(); var published = new List(); //get all content items that are published @@ -97,8 +95,6 @@ namespace Umbraco.Tests.Services //do this 10x! for (var i = 0; i < 10; i++) { - //clear the cache to make this test valid - RuntimeCacheProvider.Current.Clear(); //get all content items that are published var published = contentSvc.GetAllPublished(); @@ -122,8 +118,7 @@ namespace Umbraco.Tests.Services //do this 10x! for (var i = 0; i < 10; i++) { - //clear the cache to make this test valid - RuntimeCacheProvider.Current.Clear(); + //get all content items that are published of this type var published = contentSvc.GetContentOfContentType(contentTypeId).Where(content => content.Published); Assert.AreEqual(countOfPublished, published.Count(x => x.ContentTypeId == contentTypeId)); @@ -136,8 +131,6 @@ namespace Umbraco.Tests.Services //do this 10x! for (var i = 0; i < 10; i++) { - //clear the cache to make this test valid - RuntimeCacheProvider.Current.Clear(); //get all content items that are published of this type var published = contentSvc.GetPublishedContentOfContentType(contentTypeId); Assert.AreEqual(countOfPublished, published.Count(x => x.ContentTypeId == contentTypeId)); diff --git a/src/Umbraco.Tests/Services/ThreadSafetyServiceTest.cs b/src/Umbraco.Tests/Services/ThreadSafetyServiceTest.cs index 793a03e1df..5c3babb011 100644 --- a/src/Umbraco.Tests/Services/ThreadSafetyServiceTest.cs +++ b/src/Umbraco.Tests/Services/ThreadSafetyServiceTest.cs @@ -6,8 +6,10 @@ using System.Linq; using System.Threading; 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.Publishing; using Umbraco.Core.Services; @@ -32,9 +34,9 @@ namespace Umbraco.Tests.Services //a Database instance is created per thread, whereas the default implementation which will work in an HttpContext //threading environment, or a single apartment threading environment will not work for this test because //it is multi-threaded. - _dbFactory = new PerThreadDatabaseFactory(); + _dbFactory = new PerThreadDatabaseFactory(Logger); //overwrite the local object - ApplicationContext.DatabaseContext = new DatabaseContext(_dbFactory); + ApplicationContext.DatabaseContext = new DatabaseContext(_dbFactory, Logger, new SqlCeSyntaxProvider(), "System.Data.SqlServerCe.4.0"); //disable cache var cacheHelper = CacheHelper.CreateDisabledCacheHelper(); @@ -42,8 +44,15 @@ namespace Umbraco.Tests.Services //here we are going to override the ServiceContext because normally with our test cases we use a //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(cacheHelper, Logger, SqlSyntaxProvider, SettingsForTests.GenerateMockSettings()); _uowProvider = new PerThreadPetaPocoUnitOfWorkProvider(_dbFactory); - ApplicationContext.Services = new ServiceContext(_uowProvider, new FileUnitOfWorkProvider(), new PublishingStrategy(), cacheHelper); + ApplicationContext.Services = new ServiceContext( + repositoryFactory, + _uowProvider, + new FileUnitOfWorkProvider(), + new PublishingStrategy(), + cacheHelper, + Logger); CreateTestData(); } @@ -205,11 +214,20 @@ namespace Umbraco.Tests.Services /// internal class PerThreadDatabaseFactory : DisposableObject, IDatabaseFactory { - private readonly ConcurrentDictionary _databases = new ConcurrentDictionary(); + private readonly ILogger _logger; + + public PerThreadDatabaseFactory(ILogger logger) + { + _logger = logger; + } + + private readonly ConcurrentDictionary _databases = new ConcurrentDictionary(); public UmbracoDatabase CreateDatabase() { - var db = _databases.GetOrAdd(Thread.CurrentThread.ManagedThreadId, i => new UmbracoDatabase(Umbraco.Core.Configuration.GlobalSettings.UmbracoConnectionName)); + var db = _databases.GetOrAdd( + Thread.CurrentThread.ManagedThreadId, + i => new UmbracoDatabase(Umbraco.Core.Configuration.GlobalSettings.UmbracoConnectionName, _logger)); return db; } diff --git a/src/Umbraco.Tests/CoreStrings/CmsHelperCasingTests.cs b/src/Umbraco.Tests/Strings/CmsHelperCasingTests.cs similarity index 96% rename from src/Umbraco.Tests/CoreStrings/CmsHelperCasingTests.cs rename to src/Umbraco.Tests/Strings/CmsHelperCasingTests.cs index 5d369ab11d..798cc57526 100644 --- a/src/Umbraco.Tests/CoreStrings/CmsHelperCasingTests.cs +++ b/src/Umbraco.Tests/Strings/CmsHelperCasingTests.cs @@ -1,59 +1,59 @@ -using NUnit.Framework; -using Umbraco.Core; -using Umbraco.Core.Strings; -using Umbraco.Tests.TestHelpers; - -namespace Umbraco.Tests.CoreStrings -{ - [TestFixture] - public class CmsHelperCasingTests - { - [SetUp] - public void Setup() - { - //set default config - var config = SettingsForTests.GetDefault(); - SettingsForTests.ConfigureSettings(config); - - } - - [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")] // note the issue with Number6In - [TestCase("WhoIsNumber6InTheVillage", "Who Is Number6 In The Village")] // now fixed since DefaultShortStringHelper is the default - public void SpaceCamelCasing(string input, string expected) - { - var output = umbraco.cms.helpers.Casing.SpaceCamelCasing(input); - 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")] - [TestCase("thisis", "Thisis")] - [TestCase("ThisIsTheEnd", "This Is The End")] - [TestCase("WhoIsNumber6InTheVillage", "Who Is Number6 In The Village")] // issue is fixed - public void CompatibleDefaultReplacement(string input, string expected) - { - var helper = new DefaultShortStringHelper(); - var output = input.Length < 2 ? input : helper.SplitPascalCasing(input, ' ').ToFirstUpperInvariant(); - Assert.AreEqual(expected, output); - } - } -} +using NUnit.Framework; +using Umbraco.Core; +using Umbraco.Core.Strings; +using Umbraco.Tests.TestHelpers; + +namespace Umbraco.Tests.Strings +{ + [TestFixture] + public class CmsHelperCasingTests + { + [SetUp] + public void Setup() + { + //set default config + var config = SettingsForTests.GetDefault(); + SettingsForTests.ConfigureSettings(config); + + } + + [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")] // note the issue with Number6In + [TestCase("WhoIsNumber6InTheVillage", "Who Is Number6 In The Village")] // now fixed since DefaultShortStringHelper is the default + public void SpaceCamelCasing(string input, string expected) + { + var output = umbraco.cms.helpers.Casing.SpaceCamelCasing(input); + 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")] + [TestCase("thisis", "Thisis")] + [TestCase("ThisIsTheEnd", "This Is The End")] + [TestCase("WhoIsNumber6InTheVillage", "Who Is Number6 In The Village")] // issue is fixed + public void CompatibleDefaultReplacement(string input, string expected) + { + var helper = new DefaultShortStringHelper(); + var output = input.Length < 2 ? input : helper.SplitPascalCasing(input, ' ').ToFirstUpperInvariant(); + Assert.AreEqual(expected, output); + } + } +} diff --git a/src/Umbraco.Tests/CoreStrings/DefaultShortStringHelperTests.cs b/src/Umbraco.Tests/Strings/DefaultShortStringHelperTests.cs similarity index 97% rename from src/Umbraco.Tests/CoreStrings/DefaultShortStringHelperTests.cs rename to src/Umbraco.Tests/Strings/DefaultShortStringHelperTests.cs index 64a432e815..04b632ffeb 100644 --- a/src/Umbraco.Tests/CoreStrings/DefaultShortStringHelperTests.cs +++ b/src/Umbraco.Tests/Strings/DefaultShortStringHelperTests.cs @@ -1,652 +1,648 @@ -using System; -using System.Collections.Generic; -using System.Diagnostics; -using System.Globalization; -using System.IO; -using System.Linq; -using System.Text; -using System.Text.RegularExpressions; -using Moq; -using NUnit.Framework; -using umbraco; -using Umbraco.Core; -using Umbraco.Core.Configuration; -using Umbraco.Core.Configuration.UmbracoSettings; -using Umbraco.Core.Strings; -using Umbraco.Core.ObjectResolution; -using Umbraco.Tests.TestHelpers; - -namespace Umbraco.Tests.CoreStrings -{ - [TestFixture] - public class DefaultShortStringHelperTests : BaseUmbracoConfigurationTest - { - private DefaultShortStringHelper _helper; - - [SetUp] - public override void Initialize() - { - base.Initialize(); - - // NOTE: it is not possible to configure the helper once it has been assigned - // to the resolver and resolution has frozen. but, obviously, it is possible - // to configure filters and then to alter these filters after resolution has - // frozen. beware, nothing is thread-safe in-there! - - // NOTE pre-filters runs _before_ Recode takes place - // so there still may be utf8 chars even though you want ascii - - _helper = new DefaultShortStringHelper() - .WithConfig(CleanStringType.FileName, new DefaultShortStringHelper.Config - { - //PreFilter = ClearFileChars, // done in IsTerm - IsTerm = (c, leading) => (char.IsLetterOrDigit(c) || c == '_') && DefaultShortStringHelper.IsValidFileNameChar(c), - StringType = CleanStringType.LowerCase | CleanStringType.Ascii, - Separator = '-' - }) - .WithConfig(CleanStringType.UrlSegment, new DefaultShortStringHelper.Config - { - PreFilter = StripQuotes, - IsTerm = (c, leading) => char.IsLetterOrDigit(c) || c == '_', - StringType = CleanStringType.LowerCase | CleanStringType.Ascii, - Separator = '-' - }) - .WithConfig(new CultureInfo("fr-FR"), CleanStringType.UrlSegment, new DefaultShortStringHelper.Config - { - PreFilter = FilterFrenchElisions, - IsTerm = (c, leading) => leading ? char.IsLetter(c) : (char.IsLetterOrDigit(c) || c == '_'), - StringType = CleanStringType.LowerCase | CleanStringType.Ascii, - Separator = '-' - }) - .WithConfig(CleanStringType.Alias, new DefaultShortStringHelper.Config - { - PreFilter = StripQuotes, - IsTerm = (c, leading) => leading ? char.IsLetter(c) : char.IsLetterOrDigit(c), - StringType = CleanStringType.UmbracoCase | CleanStringType.Ascii - }) - .WithConfig(new CultureInfo("fr-FR"), CleanStringType.Alias, new DefaultShortStringHelper.Config - { - PreFilter = WhiteQuotes, - IsTerm = (c, leading) => leading ? char.IsLetter(c) : char.IsLetterOrDigit(c), - StringType = CleanStringType.UmbracoCase | CleanStringType.Ascii - }) - .WithConfig(CleanStringType.ConvertCase, new DefaultShortStringHelper.Config - { - PreFilter = null, - IsTerm = (c, leading) => char.IsLetterOrDigit(c) || c == '_', // letter, digit or underscore - StringType = CleanStringType.Ascii, - BreakTermsOnUpper = true - }); - - ShortStringHelperResolver.Reset(); - ShortStringHelperResolver.Current = new ShortStringHelperResolver(_helper); - Resolution.Freeze(); - } - - [TearDown] - public override void TearDown() - { - base.TearDown(); - ShortStringHelperResolver.Reset(); - } - - static readonly Regex FrenchElisionsRegex = new Regex("\\b(c|d|j|l|m|n|qu|s|t)('|\u8217)", RegexOptions.Compiled | RegexOptions.IgnoreCase); - - private static string FilterFrenchElisions(string s) - { - return FrenchElisionsRegex.Replace(s, ""); - } - - private static string StripQuotes(string s) - { - s = s.ReplaceMany(new Dictionary {{"'", ""}, {"\u8217", ""}}); - return s; - } - - private static string WhiteQuotes(string s) - { - s = s.ReplaceMany(new Dictionary { { "'", " " }, { "\u8217", " " } }); - return s; - } - - [Test] - public void U4_4055_4056() - { - var settings = SettingsForTests.GenerateMockSettings(); - var contentMock = Mock.Get(settings.RequestHandler); - contentMock.Setup(x => x.CharCollection).Returns(Enumerable.Empty()); - contentMock.Setup(x => x.ConvertUrlsToAscii).Returns(false); - SettingsForTests.ConfigureSettings(settings); - - const string input = "publishedVersion"; - - Assert.AreEqual("PublishedVersion", input.ConvertCase(StringAliasCaseType.PascalCase)); // obsolete, use the one below - Assert.AreEqual("PublishedVersion", input.ToCleanString(CleanStringType.ConvertCase | CleanStringType.PascalCase | CleanStringType.Ascii)); // role, case and code - } - - [Test] - public void U4_4056() - { - var settings = SettingsForTests.GenerateMockSettings(); - var contentMock = Mock.Get(settings.RequestHandler); - contentMock.Setup(x => x.CharCollection).Returns(Enumerable.Empty()); - contentMock.Setup(x => x.ConvertUrlsToAscii).Returns(false); - SettingsForTests.ConfigureSettings(settings); - - const string input = "ÆØÅ and æøå and 中文测试 and אודות האתר and größer БбДдЖж page"; - - var helper = new DefaultShortStringHelper().WithDefaultConfig(); // unicode - var output = helper.CleanStringForUrlSegment(input); - Assert.AreEqual("æøå-and-æøå-and-中文测试-and-אודות-האתר-and-größer-ббдджж-page", output); - - helper = new DefaultShortStringHelper() - .WithConfig(CleanStringType.UrlSegment, new DefaultShortStringHelper.Config - { - IsTerm = (c, leading) => char.IsLetterOrDigit(c) || c == '_', - StringType = CleanStringType.LowerCase | CleanStringType.Ascii, // ascii - Separator = '-' - }); - output = helper.CleanStringForUrlSegment(input); - Assert.AreEqual("aeoa-and-aeoa-and-and-and-grosser-bbddzhzh-page", output); - } - - [Test] - public void CleanStringUnderscoreInTerm() - { - var helper = new DefaultShortStringHelper() - .WithConfig(CleanStringType.Alias, new DefaultShortStringHelper.Config - { - // underscore is accepted within terms - IsTerm = (c, leading) => char.IsLetterOrDigit(c) || c == '_', - StringType = CleanStringType.Utf8 | CleanStringType.Unchanged, - Separator = '*' - }); - Assert.AreEqual("foo_bar*nil", helper.CleanString("foo_bar nil", CleanStringType.Alias)); - - helper = new DefaultShortStringHelper() - .WithConfig(CleanStringType.Alias, new DefaultShortStringHelper.Config - { - // underscore is not accepted within terms - IsTerm = (c, leading) => char.IsLetterOrDigit(c), - StringType = CleanStringType.Utf8 | CleanStringType.Unchanged, - Separator = '*' - }); - Assert.AreEqual("foo*bar*nil", helper.CleanString("foo_bar nil", CleanStringType.Alias)); - } - - [Test] - public void CleanStringLeadingChars() - { - var helper = new DefaultShortStringHelper() - .WithConfig(CleanStringType.Alias, new DefaultShortStringHelper.Config - { - // letters and digits are valid leading chars - IsTerm = (c, leading) => char.IsLetterOrDigit(c), - StringType = CleanStringType.Utf8 | CleanStringType.Unchanged, - Separator = '*' - }); - Assert.AreEqual("0123foo*bar*543*nil*321", helper.CleanString("0123foo_bar 543 nil 321", CleanStringType.Alias)); - - helper = new DefaultShortStringHelper() - .WithConfig(CleanStringType.Alias, new DefaultShortStringHelper.Config - { - // only letters are valid leading chars - IsTerm = (c, leading) => leading ? char.IsLetter(c) : char.IsLetterOrDigit(c), - StringType = CleanStringType.Utf8 | CleanStringType.Unchanged, - Separator = '*' - }); - Assert.AreEqual("foo*bar*543*nil*321", helper.CleanString("0123foo_bar 543 nil 321", CleanStringType.Alias)); - Assert.AreEqual("foo*bar*543*nil*321", helper.CleanString("0123 foo_bar 543 nil 321", CleanStringType.Alias)); - - helper = new DefaultShortStringHelper().WithDefaultConfig(); - Assert.AreEqual("child2", helper.CleanStringForSafeAlias("1child2")); - } - - [Test] - public void CleanStringTermOnUpper() - { - var helper = new DefaultShortStringHelper() - .WithConfig(CleanStringType.Alias, new DefaultShortStringHelper.Config - { - StringType = CleanStringType.Utf8 | CleanStringType.Unchanged, - // uppercase letter means new term - BreakTermsOnUpper = true, - Separator = '*' - }); - Assert.AreEqual("foo*Bar", helper.CleanString("fooBar", CleanStringType.Alias)); - - helper = new DefaultShortStringHelper() - .WithConfig(CleanStringType.Alias, new DefaultShortStringHelper.Config - { - StringType = CleanStringType.Utf8 | CleanStringType.Unchanged, - // uppercase letter is part of term - BreakTermsOnUpper = false, - Separator = '*' - }); - Assert.AreEqual("fooBar", helper.CleanString("fooBar", CleanStringType.Alias)); - } - - [Test] - public void CleanStringAcronymOnNonUpper() - { - var helper = new DefaultShortStringHelper() - .WithConfig(CleanStringType.Alias, new DefaultShortStringHelper.Config - { - StringType = CleanStringType.Utf8 | CleanStringType.Unchanged, - // non-uppercase letter means cut acronym - CutAcronymOnNonUpper = true, - Separator = '*' - }); - Assert.AreEqual("foo*BAR*Rnil", helper.CleanString("foo BARRnil", CleanStringType.Alias)); - Assert.AreEqual("foo*BA*Rnil", helper.CleanString("foo BARnil", CleanStringType.Alias)); - Assert.AreEqual("foo*BAnil", helper.CleanString("foo BAnil", CleanStringType.Alias)); - Assert.AreEqual("foo*Bnil", helper.CleanString("foo Bnil", CleanStringType.Alias)); - - helper = new DefaultShortStringHelper() - .WithConfig(CleanStringType.Alias, new DefaultShortStringHelper.Config - { - StringType = CleanStringType.Utf8 | CleanStringType.Unchanged, - // non-uppercase letter means word - CutAcronymOnNonUpper = false, - Separator = '*' - }); - Assert.AreEqual("foo*BARRnil", helper.CleanString("foo BARRnil", CleanStringType.Alias)); - Assert.AreEqual("foo*BARnil", helper.CleanString("foo BARnil", CleanStringType.Alias)); - Assert.AreEqual("foo*BAnil", helper.CleanString("foo BAnil", CleanStringType.Alias)); - Assert.AreEqual("foo*Bnil", helper.CleanString("foo Bnil", CleanStringType.Alias)); - } - - [Test] - public void CleanStringGreedyAcronyms() - { - var helper = new DefaultShortStringHelper() - .WithConfig(CleanStringType.Alias, new DefaultShortStringHelper.Config - { - StringType = CleanStringType.Utf8 | CleanStringType.Unchanged, - CutAcronymOnNonUpper = true, - GreedyAcronyms = true, - Separator = '*' - }); - Assert.AreEqual("foo*BARR*nil", helper.CleanString("foo BARRnil", CleanStringType.Alias)); - Assert.AreEqual("foo*BAR*nil", helper.CleanString("foo BARnil", CleanStringType.Alias)); - Assert.AreEqual("foo*BA*nil", helper.CleanString("foo BAnil", CleanStringType.Alias)); - Assert.AreEqual("foo*Bnil", helper.CleanString("foo Bnil", CleanStringType.Alias)); - - helper = new DefaultShortStringHelper() - .WithConfig(CleanStringType.Alias, new DefaultShortStringHelper.Config - { - StringType = CleanStringType.Utf8 | CleanStringType.Unchanged, - CutAcronymOnNonUpper = true, - GreedyAcronyms = false, - Separator = '*' - }); - Assert.AreEqual("foo*BAR*Rnil", helper.CleanString("foo BARRnil", CleanStringType.Alias)); - Assert.AreEqual("foo*BA*Rnil", helper.CleanString("foo BARnil", CleanStringType.Alias)); - Assert.AreEqual("foo*BAnil", helper.CleanString("foo BAnil", CleanStringType.Alias)); - Assert.AreEqual("foo*Bnil", helper.CleanString("foo Bnil", CleanStringType.Alias)); - } - - [Test] - public void CleanStringWhiteSpace() - { - var helper = new DefaultShortStringHelper() - .WithConfig(CleanStringType.Alias, new DefaultShortStringHelper.Config - { - StringType = CleanStringType.Utf8 | CleanStringType.Unchanged, - Separator = '*' - }); - Assert.AreEqual("foo", helper.CleanString(" foo ", CleanStringType.Alias)); - Assert.AreEqual("foo*bar", helper.CleanString(" foo bar ", CleanStringType.Alias)); - } - - [Test] - public void CleanStringSeparator() - { - var helper = new DefaultShortStringHelper() - .WithConfig(CleanStringType.Alias, new DefaultShortStringHelper.Config - { - StringType = CleanStringType.Utf8 | CleanStringType.Unchanged, - Separator = '*' - }); - Assert.AreEqual("foo*bar", helper.CleanString("foo bar", CleanStringType.Alias)); - - helper = new DefaultShortStringHelper() - .WithConfig(CleanStringType.Alias, new DefaultShortStringHelper.Config - { - StringType = CleanStringType.Utf8 | CleanStringType.Unchanged, - Separator = ' ' - }); - Assert.AreEqual("foo bar", helper.CleanString("foo bar", CleanStringType.Alias)); - - helper = new DefaultShortStringHelper() - .WithConfig(CleanStringType.Alias, new DefaultShortStringHelper.Config - { - StringType = CleanStringType.Utf8 | CleanStringType.Unchanged - }); - Assert.AreEqual("foobar", helper.CleanString("foo bar", CleanStringType.Alias)); - - helper = new DefaultShortStringHelper() - .WithConfig(CleanStringType.Alias, new DefaultShortStringHelper.Config - { - StringType = CleanStringType.Utf8 | CleanStringType.Unchanged, - Separator = '文' - }); - Assert.AreEqual("foo文bar", helper.CleanString("foo bar", CleanStringType.Alias)); - } - - [Test] - public void CleanStringSymbols() - { - var helper = new DefaultShortStringHelper() - .WithConfig(CleanStringType.Alias, new DefaultShortStringHelper.Config - { - StringType = CleanStringType.Utf8 | CleanStringType.Unchanged, - Separator = '*' - }); - Assert.AreEqual("house*2", helper.CleanString("house (2)", CleanStringType.Alias)); - - // FIXME but for a filename we want to keep them! - // FIXME and what about a url? - } - - [Test] - public void Utf8Surrogates() - { - // Unicode values between 0x10000 and 0x10FFF are represented by two 16-bit "surrogate" characters - const string str = "a\U00010F00z\uA74Ft"; - Assert.AreEqual(6, str.Length); - Assert.IsTrue(char.IsSurrogate(str[1])); - Assert.IsTrue(char.IsHighSurrogate(str[1])); - Assert.IsTrue(char.IsSurrogate(str[2])); - Assert.IsTrue(char.IsLowSurrogate(str[2])); - Assert.AreEqual('z', str[3]); - Assert.IsFalse(char.IsSurrogate(str[4])); - Assert.AreEqual('\uA74F', str[4]); - Assert.AreEqual('t', str[5]); - - Assert.AreEqual("z", str.Substring(3, 1)); - Assert.AreEqual("\U00010F00", str.Substring(1, 2)); - - var bytes = Encoding.UTF8.GetBytes(str); - Assert.AreEqual(10, bytes.Length); - Assert.AreEqual('a', bytes[0]); - // then next string element is two chars (surrogate pair) or 4 bytes, 21 bits of code point - Assert.AreEqual('z', bytes[5]); - // then next string element is one char and 3 bytes, 16 bits of code point - Assert.AreEqual('t', bytes[9]); - //foreach (var b in bytes) - // Console.WriteLine("{0:X}", b); - - Console.WriteLine("\U00010B70"); - } - - [Test] - public void Utf8ToAsciiConverter() - { - const string str = "a\U00010F00z\uA74Ftéô"; - var output = Core.Strings.Utf8ToAsciiConverter.ToAsciiString(str); - Assert.AreEqual("a?zooteo", output); - } - - [Test] - public void CleanStringEncoding() - { - var helper = new DefaultShortStringHelper() - .WithConfig(CleanStringType.Alias, new DefaultShortStringHelper.Config - { - StringType = CleanStringType.Utf8 | CleanStringType.Unchanged, - Separator = '*' - }); - Assert.AreEqual("中文测试", helper.CleanString("中文测试", CleanStringType.Alias)); - Assert.AreEqual("léger*中文测试*ZÔRG", helper.CleanString("léger 中文测试 ZÔRG", CleanStringType.Alias)); - - helper = new DefaultShortStringHelper() - .WithConfig(CleanStringType.Alias, new DefaultShortStringHelper.Config - { - StringType = CleanStringType.Ascii | CleanStringType.Unchanged, - Separator = '*' - }); - Assert.AreEqual("", helper.CleanString("中文测试", CleanStringType.Alias)); - Assert.AreEqual("leger*ZORG", helper.CleanString("léger 中文测试 ZÔRG", CleanStringType.Alias)); - } - - [Test] - public void CleanStringDefaultConfig() - { - var settings = SettingsForTests.GenerateMockSettings(); - var contentMock = Mock.Get(settings.RequestHandler); - contentMock.Setup(x => x.CharCollection).Returns(Enumerable.Empty()); - contentMock.Setup(x => x.ConvertUrlsToAscii).Returns(false); - SettingsForTests.ConfigureSettings(settings); - - var helper = new DefaultShortStringHelper().WithDefaultConfig(); - - const string input = "0123 中文测试 中文测试 léger ZÔRG (2) a?? *x"; - - var alias = helper.CleanStringForSafeAlias(input); - var filename = helper.CleanStringForSafeFileName(input); - var segment = helper.CleanStringForUrlSegment(input); - - // umbraco-cased ascii alias, must begin with a proper letter - Assert.AreEqual("legerZORG2AX", alias, "alias"); - - // lower-cased, utf8 filename, removing illegal filename chars, using dash-separator - Assert.AreEqual("0123-中文测试-中文测试-léger-zôrg-2-a-x", filename, "filename"); - - // lower-cased, utf8 url segment, only letters and digits, using dash-separator - Assert.AreEqual("0123-中文测试-中文测试-léger-zôrg-2-a-x", segment, "segment"); - } - - [Test] - public void CleanStringCasing() - { - var helper = new DefaultShortStringHelper() - .WithConfig(CleanStringType.Alias, new DefaultShortStringHelper.Config - { - StringType = CleanStringType.Utf8 | CleanStringType.Unchanged, - Separator = ' ' - }); - - // BBB is an acronym - // E is a word (too short to be an acronym) - // FF is an acronym - - // FIXME "C" can't be an acronym - // FIXME "DBXreview" = acronym?! - - Assert.AreEqual("aaa BBB CCc Ddd E FF", helper.CleanString("aaa BBB CCc Ddd E FF", CleanStringType.Alias)); // unchanged - Assert.AreEqual("aaa Bbb Ccc Ddd E FF", helper.CleanString("aaa BBB CCc Ddd E FF", CleanStringType.Alias | CleanStringType.CamelCase)); - Assert.AreEqual("Aaa Bbb Ccc Ddd E FF", helper.CleanString("aaa BBB CCc Ddd E FF", CleanStringType.Alias | CleanStringType.PascalCase)); - Assert.AreEqual("aaa bbb ccc ddd e ff", helper.CleanString("aaa BBB CCc Ddd E FF", CleanStringType.Alias | CleanStringType.LowerCase)); - Assert.AreEqual("AAA BBB CCC DDD E FF", helper.CleanString("aaa BBB CCc Ddd E FF", CleanStringType.Alias | CleanStringType.UpperCase)); - Assert.AreEqual("aaa BBB CCc Ddd E FF", helper.CleanString("aaa BBB CCc Ddd E FF", CleanStringType.Alias | CleanStringType.UmbracoCase)); - - // MS rules & guidelines: - // - Do capitalize both characters of two-character acronyms, except the first word of a camel-cased identifier. - // eg "DBRate" (pascal) or "ioHelper" (camel) - "SpecialDBRate" (pascal) or "specialIOHelper" (camel) - // - Do capitalize only the first character of acronyms with three or more characters, except the first word of a camel-cased identifier. - // eg "XmlWriter (pascal) or "htmlReader" (camel) - "SpecialXmlWriter" (pascal) or "specialHtmlReader" (camel) - // - Do not capitalize any of the characters of any acronyms, whatever their length, at the beginning of a camel-cased identifier. - // eg "xmlWriter" or "dbWriter" (camel) - - Assert.AreEqual("aaa BB Ccc", helper.CleanString("aaa BB ccc", CleanStringType.Alias | CleanStringType.CamelCase)); - Assert.AreEqual("aa Bb Ccc", helper.CleanString("AA bb ccc", CleanStringType.Alias | CleanStringType.CamelCase)); - Assert.AreEqual("aaa Bb Ccc", helper.CleanString("AAA bb ccc", CleanStringType.Alias | CleanStringType.CamelCase)); - Assert.AreEqual("db Rate", helper.CleanString("DB rate", CleanStringType.Alias | CleanStringType.CamelCase)); - Assert.AreEqual("special DB Rate", helper.CleanString("special DB rate", CleanStringType.Alias | CleanStringType.CamelCase)); - Assert.AreEqual("xml Writer", helper.CleanString("XML writer", CleanStringType.Alias | CleanStringType.CamelCase)); - Assert.AreEqual("special Xml Writer", helper.CleanString("special XML writer", CleanStringType.Alias | CleanStringType.CamelCase)); - - Assert.AreEqual("Aaa BB Ccc", helper.CleanString("aaa BB ccc", CleanStringType.Alias | CleanStringType.PascalCase)); - Assert.AreEqual("AA Bb Ccc", helper.CleanString("AA bb ccc", CleanStringType.Alias | CleanStringType.PascalCase)); - Assert.AreEqual("Aaa Bb Ccc", helper.CleanString("AAA bb ccc", CleanStringType.Alias | CleanStringType.PascalCase)); - Assert.AreEqual("DB Rate", helper.CleanString("DB rate", CleanStringType.Alias | CleanStringType.PascalCase)); - Assert.AreEqual("Special DB Rate", helper.CleanString("special DB rate", CleanStringType.Alias | CleanStringType.PascalCase)); - Assert.AreEqual("Xml Writer", helper.CleanString("XML writer", CleanStringType.Alias | CleanStringType.PascalCase)); - Assert.AreEqual("Special Xml Writer", helper.CleanString("special XML writer", CleanStringType.Alias | CleanStringType.PascalCase)); - } - - #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")] - [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) - { - var output = _helper.CleanStringForSafeAlias(input); - Assert.AreEqual(expected, output); - } - - //#region Cases - //[TestCase("This is my_little_house so cute.", "thisIsMyLittleHouseSoCute", false)] - //[TestCase("This is my_little_house so cute.", "thisIsMy_little_houseSoCute", true)] - //[TestCase("This is my_Little_House so cute.", "thisIsMyLittleHouseSoCute", false)] - //[TestCase("This is my_Little_House so cute.", "thisIsMy_Little_HouseSoCute", true)] - //[TestCase("An UPPER_CASE_TEST to check", "anUpperCaseTestToCheck", false)] - //[TestCase("An UPPER_CASE_TEST to check", "anUpper_case_testToCheck", true)] - //[TestCase("Trailing_", "trailing", false)] - //[TestCase("Trailing_", "trailing_", true)] - //[TestCase("_Leading", "leading", false)] - //[TestCase("_Leading", "leading", true)] - //[TestCase("Repeat___Repeat", "repeatRepeat", false)] - //[TestCase("Repeat___Repeat", "repeat___Repeat", true)] - //[TestCase("Repeat___repeat", "repeatRepeat", false)] - //[TestCase("Repeat___repeat", "repeat___repeat", true)] - //#endregion - //public void CleanStringWithUnderscore(string input, string expected, bool allowUnderscoreInTerm) - //{ - // var helper = new DefaultShortStringHelper() - // .WithConfig(allowUnderscoreInTerm: allowUnderscoreInTerm); - // var output = helper.CleanString(input, CleanStringType.Alias | CleanStringType.Ascii | CleanStringType.CamelCase); - // 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-h1z-n")] - [TestCase("Räksmörgås", "raksmorgas")] - [TestCase("'em guys-over there, are#goin' a \"little\"bit crazy eh!! :)", "em-guys-over-there-are-goin-a-little-bit-crazy-eh")] - [TestCase("汉#字*/漢?字", "")] - [TestCase("Réalösk fix bran#lo'sk", "realosk-fix-bran-losk")] - [TestCase("200 ways to be happy", "200-ways-to-be-happy")] - #endregion - public void CleanStringForUrlSegment(string input, string expected) - { - var output = _helper.CleanStringForUrlSegment(input); - 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")] // works! - [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")] - #endregion - public void SplitPascalCasing(string input, string expected) - { - var output = _helper.SplitPascalCasing(input, ' '); - Assert.AreEqual(expected, output); - - output = _helper.SplitPascalCasing(input, '*'); - expected = expected.Replace(' ', '*'); - Assert.AreEqual(expected, output); - } - - #region Cases - [TestCase("sauté dans l'espace", "saute-dans-espace", "fr-FR", CleanStringType.UrlSegment | CleanStringType.Ascii | CleanStringType.LowerCase)] - [TestCase("sauté dans l'espace", "sauté-dans-espace", "fr-FR", CleanStringType.UrlSegment | CleanStringType.Utf8 | CleanStringType.LowerCase)] - [TestCase("sauté dans l'espace", "SauteDansLEspace", "fr-FR", CleanStringType.Alias | CleanStringType.Ascii | CleanStringType.PascalCase)] - [TestCase("he doesn't want", "he-doesnt-want", null, CleanStringType.UrlSegment | CleanStringType.Ascii | CleanStringType.LowerCase)] - [TestCase("he doesn't want", "heDoesntWant", null, CleanStringType.Alias | CleanStringType.Ascii | CleanStringType.CamelCase)] - #endregion - public void CleanStringWithTypeAndCulture(string input, string expected, string culture, CleanStringType stringType) - { - var cinfo = culture == null ? CultureInfo.InvariantCulture : new CultureInfo(culture); - - // picks the proper config per culture - // and overrides some stringType params (ascii...) - var output = _helper.CleanString(input, stringType, cinfo); - Assert.AreEqual(expected, 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")] - [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", "nil-nil-nil.txt")] - [TestCase("taradabum", "taradabum")] - [TestCase("tara$$da:b/u (char.IsLetterOrDigit(c) || c == '_') && DefaultShortStringHelper.IsValidFileNameChar(c), + StringType = CleanStringType.LowerCase | CleanStringType.Ascii, + Separator = '-' + }) + .WithConfig(CleanStringType.UrlSegment, new DefaultShortStringHelper.Config + { + PreFilter = StripQuotes, + IsTerm = (c, leading) => char.IsLetterOrDigit(c) || c == '_', + StringType = CleanStringType.LowerCase | CleanStringType.Ascii, + Separator = '-' + }) + .WithConfig(new CultureInfo("fr-FR"), CleanStringType.UrlSegment, new DefaultShortStringHelper.Config + { + PreFilter = FilterFrenchElisions, + IsTerm = (c, leading) => leading ? char.IsLetter(c) : (char.IsLetterOrDigit(c) || c == '_'), + StringType = CleanStringType.LowerCase | CleanStringType.Ascii, + Separator = '-' + }) + .WithConfig(CleanStringType.Alias, new DefaultShortStringHelper.Config + { + PreFilter = StripQuotes, + IsTerm = (c, leading) => leading ? char.IsLetter(c) : char.IsLetterOrDigit(c), + StringType = CleanStringType.UmbracoCase | CleanStringType.Ascii + }) + .WithConfig(new CultureInfo("fr-FR"), CleanStringType.Alias, new DefaultShortStringHelper.Config + { + PreFilter = WhiteQuotes, + IsTerm = (c, leading) => leading ? char.IsLetter(c) : char.IsLetterOrDigit(c), + StringType = CleanStringType.UmbracoCase | CleanStringType.Ascii + }) + .WithConfig(CleanStringType.ConvertCase, new DefaultShortStringHelper.Config + { + PreFilter = null, + IsTerm = (c, leading) => char.IsLetterOrDigit(c) || c == '_', // letter, digit or underscore + StringType = CleanStringType.Ascii, + BreakTermsOnUpper = true + }); + + ShortStringHelperResolver.Reset(); + ShortStringHelperResolver.Current = new ShortStringHelperResolver(_helper); + Resolution.Freeze(); + } + + [TearDown] + public override void TearDown() + { + base.TearDown(); + ShortStringHelperResolver.Reset(); + } + + static readonly Regex FrenchElisionsRegex = new Regex("\\b(c|d|j|l|m|n|qu|s|t)('|\u8217)", RegexOptions.Compiled | RegexOptions.IgnoreCase); + + private static string FilterFrenchElisions(string s) + { + return FrenchElisionsRegex.Replace(s, ""); + } + + private static string StripQuotes(string s) + { + s = s.ReplaceMany(new Dictionary {{"'", ""}, {"\u8217", ""}}); + return s; + } + + private static string WhiteQuotes(string s) + { + s = s.ReplaceMany(new Dictionary { { "'", " " }, { "\u8217", " " } }); + return s; + } + + [Test] + public void U4_4055_4056() + { + var settings = SettingsForTests.GenerateMockSettings(); + var contentMock = Mock.Get(settings.RequestHandler); + contentMock.Setup(x => x.CharCollection).Returns(Enumerable.Empty()); + contentMock.Setup(x => x.ConvertUrlsToAscii).Returns(false); + SettingsForTests.ConfigureSettings(settings); + + const string input = "publishedVersion"; + + Assert.AreEqual("PublishedVersion", input.ConvertCase(StringAliasCaseType.PascalCase)); // obsolete, use the one below + Assert.AreEqual("PublishedVersion", input.ToCleanString(CleanStringType.ConvertCase | CleanStringType.PascalCase | CleanStringType.Ascii)); // role, case and code + } + + [Test] + public void U4_4056() + { + var settings = SettingsForTests.GenerateMockSettings(); + var contentMock = Mock.Get(settings.RequestHandler); + contentMock.Setup(x => x.CharCollection).Returns(Enumerable.Empty()); + contentMock.Setup(x => x.ConvertUrlsToAscii).Returns(false); + SettingsForTests.ConfigureSettings(settings); + + const string input = "ÆØÅ and æøå and 中文测试 and אודות האתר and größer БбДдЖж page"; + + var helper = new DefaultShortStringHelper().WithDefaultConfig(); // unicode + var output = helper.CleanStringForUrlSegment(input); + Assert.AreEqual("æøå-and-æøå-and-中文测试-and-אודות-האתר-and-größer-ббдджж-page", output); + + helper = new DefaultShortStringHelper() + .WithConfig(CleanStringType.UrlSegment, new DefaultShortStringHelper.Config + { + IsTerm = (c, leading) => char.IsLetterOrDigit(c) || c == '_', + StringType = CleanStringType.LowerCase | CleanStringType.Ascii, // ascii + Separator = '-' + }); + output = helper.CleanStringForUrlSegment(input); + Assert.AreEqual("aeoa-and-aeoa-and-and-and-grosser-bbddzhzh-page", output); + } + + [Test] + public void CleanStringUnderscoreInTerm() + { + var helper = new DefaultShortStringHelper() + .WithConfig(CleanStringType.Alias, new DefaultShortStringHelper.Config + { + // underscore is accepted within terms + IsTerm = (c, leading) => char.IsLetterOrDigit(c) || c == '_', + StringType = CleanStringType.Utf8 | CleanStringType.Unchanged, + Separator = '*' + }); + Assert.AreEqual("foo_bar*nil", helper.CleanString("foo_bar nil", CleanStringType.Alias)); + + helper = new DefaultShortStringHelper() + .WithConfig(CleanStringType.Alias, new DefaultShortStringHelper.Config + { + // underscore is not accepted within terms + IsTerm = (c, leading) => char.IsLetterOrDigit(c), + StringType = CleanStringType.Utf8 | CleanStringType.Unchanged, + Separator = '*' + }); + Assert.AreEqual("foo*bar*nil", helper.CleanString("foo_bar nil", CleanStringType.Alias)); + } + + [Test] + public void CleanStringLeadingChars() + { + var helper = new DefaultShortStringHelper() + .WithConfig(CleanStringType.Alias, new DefaultShortStringHelper.Config + { + // letters and digits are valid leading chars + IsTerm = (c, leading) => char.IsLetterOrDigit(c), + StringType = CleanStringType.Utf8 | CleanStringType.Unchanged, + Separator = '*' + }); + Assert.AreEqual("0123foo*bar*543*nil*321", helper.CleanString("0123foo_bar 543 nil 321", CleanStringType.Alias)); + + helper = new DefaultShortStringHelper() + .WithConfig(CleanStringType.Alias, new DefaultShortStringHelper.Config + { + // only letters are valid leading chars + IsTerm = (c, leading) => leading ? char.IsLetter(c) : char.IsLetterOrDigit(c), + StringType = CleanStringType.Utf8 | CleanStringType.Unchanged, + Separator = '*' + }); + Assert.AreEqual("foo*bar*543*nil*321", helper.CleanString("0123foo_bar 543 nil 321", CleanStringType.Alias)); + Assert.AreEqual("foo*bar*543*nil*321", helper.CleanString("0123 foo_bar 543 nil 321", CleanStringType.Alias)); + + helper = new DefaultShortStringHelper().WithDefaultConfig(); + Assert.AreEqual("child2", helper.CleanStringForSafeAlias("1child2")); + } + + [Test] + public void CleanStringTermOnUpper() + { + var helper = new DefaultShortStringHelper() + .WithConfig(CleanStringType.Alias, new DefaultShortStringHelper.Config + { + StringType = CleanStringType.Utf8 | CleanStringType.Unchanged, + // uppercase letter means new term + BreakTermsOnUpper = true, + Separator = '*' + }); + Assert.AreEqual("foo*Bar", helper.CleanString("fooBar", CleanStringType.Alias)); + + helper = new DefaultShortStringHelper() + .WithConfig(CleanStringType.Alias, new DefaultShortStringHelper.Config + { + StringType = CleanStringType.Utf8 | CleanStringType.Unchanged, + // uppercase letter is part of term + BreakTermsOnUpper = false, + Separator = '*' + }); + Assert.AreEqual("fooBar", helper.CleanString("fooBar", CleanStringType.Alias)); + } + + [Test] + public void CleanStringAcronymOnNonUpper() + { + var helper = new DefaultShortStringHelper() + .WithConfig(CleanStringType.Alias, new DefaultShortStringHelper.Config + { + StringType = CleanStringType.Utf8 | CleanStringType.Unchanged, + // non-uppercase letter means cut acronym + CutAcronymOnNonUpper = true, + Separator = '*' + }); + Assert.AreEqual("foo*BAR*Rnil", helper.CleanString("foo BARRnil", CleanStringType.Alias)); + Assert.AreEqual("foo*BA*Rnil", helper.CleanString("foo BARnil", CleanStringType.Alias)); + Assert.AreEqual("foo*BAnil", helper.CleanString("foo BAnil", CleanStringType.Alias)); + Assert.AreEqual("foo*Bnil", helper.CleanString("foo Bnil", CleanStringType.Alias)); + + helper = new DefaultShortStringHelper() + .WithConfig(CleanStringType.Alias, new DefaultShortStringHelper.Config + { + StringType = CleanStringType.Utf8 | CleanStringType.Unchanged, + // non-uppercase letter means word + CutAcronymOnNonUpper = false, + Separator = '*' + }); + Assert.AreEqual("foo*BARRnil", helper.CleanString("foo BARRnil", CleanStringType.Alias)); + Assert.AreEqual("foo*BARnil", helper.CleanString("foo BARnil", CleanStringType.Alias)); + Assert.AreEqual("foo*BAnil", helper.CleanString("foo BAnil", CleanStringType.Alias)); + Assert.AreEqual("foo*Bnil", helper.CleanString("foo Bnil", CleanStringType.Alias)); + } + + [Test] + public void CleanStringGreedyAcronyms() + { + var helper = new DefaultShortStringHelper() + .WithConfig(CleanStringType.Alias, new DefaultShortStringHelper.Config + { + StringType = CleanStringType.Utf8 | CleanStringType.Unchanged, + CutAcronymOnNonUpper = true, + GreedyAcronyms = true, + Separator = '*' + }); + Assert.AreEqual("foo*BARR*nil", helper.CleanString("foo BARRnil", CleanStringType.Alias)); + Assert.AreEqual("foo*BAR*nil", helper.CleanString("foo BARnil", CleanStringType.Alias)); + Assert.AreEqual("foo*BA*nil", helper.CleanString("foo BAnil", CleanStringType.Alias)); + Assert.AreEqual("foo*Bnil", helper.CleanString("foo Bnil", CleanStringType.Alias)); + + helper = new DefaultShortStringHelper() + .WithConfig(CleanStringType.Alias, new DefaultShortStringHelper.Config + { + StringType = CleanStringType.Utf8 | CleanStringType.Unchanged, + CutAcronymOnNonUpper = true, + GreedyAcronyms = false, + Separator = '*' + }); + Assert.AreEqual("foo*BAR*Rnil", helper.CleanString("foo BARRnil", CleanStringType.Alias)); + Assert.AreEqual("foo*BA*Rnil", helper.CleanString("foo BARnil", CleanStringType.Alias)); + Assert.AreEqual("foo*BAnil", helper.CleanString("foo BAnil", CleanStringType.Alias)); + Assert.AreEqual("foo*Bnil", helper.CleanString("foo Bnil", CleanStringType.Alias)); + } + + [Test] + public void CleanStringWhiteSpace() + { + var helper = new DefaultShortStringHelper() + .WithConfig(CleanStringType.Alias, new DefaultShortStringHelper.Config + { + StringType = CleanStringType.Utf8 | CleanStringType.Unchanged, + Separator = '*' + }); + Assert.AreEqual("foo", helper.CleanString(" foo ", CleanStringType.Alias)); + Assert.AreEqual("foo*bar", helper.CleanString(" foo bar ", CleanStringType.Alias)); + } + + [Test] + public void CleanStringSeparator() + { + var helper = new DefaultShortStringHelper() + .WithConfig(CleanStringType.Alias, new DefaultShortStringHelper.Config + { + StringType = CleanStringType.Utf8 | CleanStringType.Unchanged, + Separator = '*' + }); + Assert.AreEqual("foo*bar", helper.CleanString("foo bar", CleanStringType.Alias)); + + helper = new DefaultShortStringHelper() + .WithConfig(CleanStringType.Alias, new DefaultShortStringHelper.Config + { + StringType = CleanStringType.Utf8 | CleanStringType.Unchanged, + Separator = ' ' + }); + Assert.AreEqual("foo bar", helper.CleanString("foo bar", CleanStringType.Alias)); + + helper = new DefaultShortStringHelper() + .WithConfig(CleanStringType.Alias, new DefaultShortStringHelper.Config + { + StringType = CleanStringType.Utf8 | CleanStringType.Unchanged + }); + Assert.AreEqual("foobar", helper.CleanString("foo bar", CleanStringType.Alias)); + + helper = new DefaultShortStringHelper() + .WithConfig(CleanStringType.Alias, new DefaultShortStringHelper.Config + { + StringType = CleanStringType.Utf8 | CleanStringType.Unchanged, + Separator = '文' + }); + Assert.AreEqual("foo文bar", helper.CleanString("foo bar", CleanStringType.Alias)); + } + + [Test] + public void CleanStringSymbols() + { + var helper = new DefaultShortStringHelper() + .WithConfig(CleanStringType.Alias, new DefaultShortStringHelper.Config + { + StringType = CleanStringType.Utf8 | CleanStringType.Unchanged, + Separator = '*' + }); + Assert.AreEqual("house*2", helper.CleanString("house (2)", CleanStringType.Alias)); + + // FIXME but for a filename we want to keep them! + // FIXME and what about a url? + } + + [Test] + public void Utf8Surrogates() + { + // Unicode values between 0x10000 and 0x10FFF are represented by two 16-bit "surrogate" characters + const string str = "a\U00010F00z\uA74Ft"; + Assert.AreEqual(6, str.Length); + Assert.IsTrue(char.IsSurrogate(str[1])); + Assert.IsTrue(char.IsHighSurrogate(str[1])); + Assert.IsTrue(char.IsSurrogate(str[2])); + Assert.IsTrue(char.IsLowSurrogate(str[2])); + Assert.AreEqual('z', str[3]); + Assert.IsFalse(char.IsSurrogate(str[4])); + Assert.AreEqual('\uA74F', str[4]); + Assert.AreEqual('t', str[5]); + + Assert.AreEqual("z", str.Substring(3, 1)); + Assert.AreEqual("\U00010F00", str.Substring(1, 2)); + + var bytes = Encoding.UTF8.GetBytes(str); + Assert.AreEqual(10, bytes.Length); + Assert.AreEqual('a', bytes[0]); + // then next string element is two chars (surrogate pair) or 4 bytes, 21 bits of code point + Assert.AreEqual('z', bytes[5]); + // then next string element is one char and 3 bytes, 16 bits of code point + Assert.AreEqual('t', bytes[9]); + //foreach (var b in bytes) + // Console.WriteLine("{0:X}", b); + + Console.WriteLine("\U00010B70"); + } + + [Test] + public void Utf8ToAsciiConverter() + { + const string str = "a\U00010F00z\uA74Ftéô"; + var output = Core.Strings.Utf8ToAsciiConverter.ToAsciiString(str); + Assert.AreEqual("a?zooteo", output); + } + + [Test] + public void CleanStringEncoding() + { + var helper = new DefaultShortStringHelper() + .WithConfig(CleanStringType.Alias, new DefaultShortStringHelper.Config + { + StringType = CleanStringType.Utf8 | CleanStringType.Unchanged, + Separator = '*' + }); + Assert.AreEqual("中文测试", helper.CleanString("中文测试", CleanStringType.Alias)); + Assert.AreEqual("léger*中文测试*ZÔRG", helper.CleanString("léger 中文测试 ZÔRG", CleanStringType.Alias)); + + helper = new DefaultShortStringHelper() + .WithConfig(CleanStringType.Alias, new DefaultShortStringHelper.Config + { + StringType = CleanStringType.Ascii | CleanStringType.Unchanged, + Separator = '*' + }); + Assert.AreEqual("", helper.CleanString("中文测试", CleanStringType.Alias)); + Assert.AreEqual("leger*ZORG", helper.CleanString("léger 中文测试 ZÔRG", CleanStringType.Alias)); + } + + [Test] + public void CleanStringDefaultConfig() + { + var settings = SettingsForTests.GenerateMockSettings(); + var contentMock = Mock.Get(settings.RequestHandler); + contentMock.Setup(x => x.CharCollection).Returns(Enumerable.Empty()); + contentMock.Setup(x => x.ConvertUrlsToAscii).Returns(false); + SettingsForTests.ConfigureSettings(settings); + + var helper = new DefaultShortStringHelper().WithDefaultConfig(); + + const string input = "0123 中文测试 中文测试 léger ZÔRG (2) a?? *x"; + + var alias = helper.CleanStringForSafeAlias(input); + var filename = helper.CleanStringForSafeFileName(input); + var segment = helper.CleanStringForUrlSegment(input); + + // umbraco-cased ascii alias, must begin with a proper letter + Assert.AreEqual("legerZORG2AX", alias, "alias"); + + // lower-cased, utf8 filename, removing illegal filename chars, using dash-separator + Assert.AreEqual("0123-中文测试-中文测试-léger-zôrg-2-a-x", filename, "filename"); + + // lower-cased, utf8 url segment, only letters and digits, using dash-separator + Assert.AreEqual("0123-中文测试-中文测试-léger-zôrg-2-a-x", segment, "segment"); + } + + [Test] + public void CleanStringCasing() + { + var helper = new DefaultShortStringHelper() + .WithConfig(CleanStringType.Alias, new DefaultShortStringHelper.Config + { + StringType = CleanStringType.Utf8 | CleanStringType.Unchanged, + Separator = ' ' + }); + + // BBB is an acronym + // E is a word (too short to be an acronym) + // FF is an acronym + + // FIXME "C" can't be an acronym + // FIXME "DBXreview" = acronym?! + + Assert.AreEqual("aaa BBB CCc Ddd E FF", helper.CleanString("aaa BBB CCc Ddd E FF", CleanStringType.Alias)); // unchanged + Assert.AreEqual("aaa Bbb Ccc Ddd E FF", helper.CleanString("aaa BBB CCc Ddd E FF", CleanStringType.Alias | CleanStringType.CamelCase)); + Assert.AreEqual("Aaa Bbb Ccc Ddd E FF", helper.CleanString("aaa BBB CCc Ddd E FF", CleanStringType.Alias | CleanStringType.PascalCase)); + Assert.AreEqual("aaa bbb ccc ddd e ff", helper.CleanString("aaa BBB CCc Ddd E FF", CleanStringType.Alias | CleanStringType.LowerCase)); + Assert.AreEqual("AAA BBB CCC DDD E FF", helper.CleanString("aaa BBB CCc Ddd E FF", CleanStringType.Alias | CleanStringType.UpperCase)); + Assert.AreEqual("aaa BBB CCc Ddd E FF", helper.CleanString("aaa BBB CCc Ddd E FF", CleanStringType.Alias | CleanStringType.UmbracoCase)); + + // MS rules & guidelines: + // - Do capitalize both characters of two-character acronyms, except the first word of a camel-cased identifier. + // eg "DBRate" (pascal) or "ioHelper" (camel) - "SpecialDBRate" (pascal) or "specialIOHelper" (camel) + // - Do capitalize only the first character of acronyms with three or more characters, except the first word of a camel-cased identifier. + // eg "XmlWriter (pascal) or "htmlReader" (camel) - "SpecialXmlWriter" (pascal) or "specialHtmlReader" (camel) + // - Do not capitalize any of the characters of any acronyms, whatever their length, at the beginning of a camel-cased identifier. + // eg "xmlWriter" or "dbWriter" (camel) + + Assert.AreEqual("aaa BB Ccc", helper.CleanString("aaa BB ccc", CleanStringType.Alias | CleanStringType.CamelCase)); + Assert.AreEqual("aa Bb Ccc", helper.CleanString("AA bb ccc", CleanStringType.Alias | CleanStringType.CamelCase)); + Assert.AreEqual("aaa Bb Ccc", helper.CleanString("AAA bb ccc", CleanStringType.Alias | CleanStringType.CamelCase)); + Assert.AreEqual("db Rate", helper.CleanString("DB rate", CleanStringType.Alias | CleanStringType.CamelCase)); + Assert.AreEqual("special DB Rate", helper.CleanString("special DB rate", CleanStringType.Alias | CleanStringType.CamelCase)); + Assert.AreEqual("xml Writer", helper.CleanString("XML writer", CleanStringType.Alias | CleanStringType.CamelCase)); + Assert.AreEqual("special Xml Writer", helper.CleanString("special XML writer", CleanStringType.Alias | CleanStringType.CamelCase)); + + Assert.AreEqual("Aaa BB Ccc", helper.CleanString("aaa BB ccc", CleanStringType.Alias | CleanStringType.PascalCase)); + Assert.AreEqual("AA Bb Ccc", helper.CleanString("AA bb ccc", CleanStringType.Alias | CleanStringType.PascalCase)); + Assert.AreEqual("Aaa Bb Ccc", helper.CleanString("AAA bb ccc", CleanStringType.Alias | CleanStringType.PascalCase)); + Assert.AreEqual("DB Rate", helper.CleanString("DB rate", CleanStringType.Alias | CleanStringType.PascalCase)); + Assert.AreEqual("Special DB Rate", helper.CleanString("special DB rate", CleanStringType.Alias | CleanStringType.PascalCase)); + Assert.AreEqual("Xml Writer", helper.CleanString("XML writer", CleanStringType.Alias | CleanStringType.PascalCase)); + Assert.AreEqual("Special Xml Writer", helper.CleanString("special XML writer", CleanStringType.Alias | CleanStringType.PascalCase)); + } + + #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")] + [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) + { + var output = _helper.CleanStringForSafeAlias(input); + Assert.AreEqual(expected, output); + } + + //#region Cases + //[TestCase("This is my_little_house so cute.", "thisIsMyLittleHouseSoCute", false)] + //[TestCase("This is my_little_house so cute.", "thisIsMy_little_houseSoCute", true)] + //[TestCase("This is my_Little_House so cute.", "thisIsMyLittleHouseSoCute", false)] + //[TestCase("This is my_Little_House so cute.", "thisIsMy_Little_HouseSoCute", true)] + //[TestCase("An UPPER_CASE_TEST to check", "anUpperCaseTestToCheck", false)] + //[TestCase("An UPPER_CASE_TEST to check", "anUpper_case_testToCheck", true)] + //[TestCase("Trailing_", "trailing", false)] + //[TestCase("Trailing_", "trailing_", true)] + //[TestCase("_Leading", "leading", false)] + //[TestCase("_Leading", "leading", true)] + //[TestCase("Repeat___Repeat", "repeatRepeat", false)] + //[TestCase("Repeat___Repeat", "repeat___Repeat", true)] + //[TestCase("Repeat___repeat", "repeatRepeat", false)] + //[TestCase("Repeat___repeat", "repeat___repeat", true)] + //#endregion + //public void CleanStringWithUnderscore(string input, string expected, bool allowUnderscoreInTerm) + //{ + // var helper = new DefaultShortStringHelper() + // .WithConfig(allowUnderscoreInTerm: allowUnderscoreInTerm); + // var output = helper.CleanString(input, CleanStringType.Alias | CleanStringType.Ascii | CleanStringType.CamelCase); + // 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-h1z-n")] + [TestCase("Räksmörgås", "raksmorgas")] + [TestCase("'em guys-over there, are#goin' a \"little\"bit crazy eh!! :)", "em-guys-over-there-are-goin-a-little-bit-crazy-eh")] + [TestCase("汉#字*/漢?字", "")] + [TestCase("Réalösk fix bran#lo'sk", "realosk-fix-bran-losk")] + [TestCase("200 ways to be happy", "200-ways-to-be-happy")] + #endregion + public void CleanStringForUrlSegment(string input, string expected) + { + var output = _helper.CleanStringForUrlSegment(input); + 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")] // works! + [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")] + #endregion + public void SplitPascalCasing(string input, string expected) + { + var output = _helper.SplitPascalCasing(input, ' '); + Assert.AreEqual(expected, output); + + output = _helper.SplitPascalCasing(input, '*'); + expected = expected.Replace(' ', '*'); + Assert.AreEqual(expected, output); + } + + #region Cases + [TestCase("sauté dans l'espace", "saute-dans-espace", "fr-FR", CleanStringType.UrlSegment | CleanStringType.Ascii | CleanStringType.LowerCase)] + [TestCase("sauté dans l'espace", "sauté-dans-espace", "fr-FR", CleanStringType.UrlSegment | CleanStringType.Utf8 | CleanStringType.LowerCase)] + [TestCase("sauté dans l'espace", "SauteDansLEspace", "fr-FR", CleanStringType.Alias | CleanStringType.Ascii | CleanStringType.PascalCase)] + [TestCase("he doesn't want", "he-doesnt-want", null, CleanStringType.UrlSegment | CleanStringType.Ascii | CleanStringType.LowerCase)] + [TestCase("he doesn't want", "heDoesntWant", null, CleanStringType.Alias | CleanStringType.Ascii | CleanStringType.CamelCase)] + #endregion + public void CleanStringWithTypeAndCulture(string input, string expected, string culture, CleanStringType stringType) + { + var cinfo = culture == null ? CultureInfo.InvariantCulture : new CultureInfo(culture); + + // picks the proper config per culture + // and overrides some stringType params (ascii...) + var output = _helper.CleanString(input, stringType, cinfo); + Assert.AreEqual(expected, 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")] + [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", "nil-nil-nil.txt")] + [TestCase("taradabum", "taradabum")] + [TestCase("tara$$da:b/u 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 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.ToUrlAlias(replacements, true, true, false); - var url2 = name2.ToUrlAlias(replacements, true, true, false); - var url3 = name3.ToUrlAlias(replacements, true, true, false); - var url4 = name4.ToUrlAlias(replacements, true, true, false); - var url5 = name5.ToUrlAlias(replacements, true, true, false); - var url6 = name6.ToUrlAlias(replacements, true, true, false); - var url7 = name6.ToUrlAlias(replacements, true, false, false); - var url8 = name6.ToUrlAlias(replacements, true, false, true); - - 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.ConvertCase(StringAliasCaseType.CamelCase); - var camelCase2 = name2.ConvertCase(StringAliasCaseType.CamelCase); - var camelCase3 = name3.ConvertCase(StringAliasCaseType.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.ToUmbracoAlias(); - var alias2 = name2.ToUmbracoAlias(); - var alias3 = name3.ToUmbracoAlias(); - var alias4 = name4.ToUmbracoAlias(); - var alias5 = name5.ToUmbracoAlias(/*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); - } - - } -} +using System.Collections.Generic; +using NUnit.Framework; +using Umbraco.Core; +using Umbraco.Core.ObjectResolution; +using Umbraco.Core.Strings; + +namespace Umbraco.Tests.Strings +{ + [TestFixture] + public class LegacyStringExtensionsTests + { + [SetUp] + public void Setup() + { + ShortStringHelperResolver.Reset(); + ShortStringHelperResolver.Current = new ShortStringHelperResolver(new LegacyShortStringHelper()); + Resolution.Freeze(); + } + + [TearDown] + public void TearDown() + { + ShortStringHelperResolver.Reset(); + } + + [TestCase("This is a string to encrypt")] + [TestCase("This is a string to encrypt\nThis is a second line")] + [TestCase(" White space is preserved ")] + [TestCase("\nWhite space is preserved\n")] + public void Encrypt_And_Decrypt(string input) + { + var encrypted = input.EncryptWithMachineKey(); + var decrypted = encrypted.DecryptWithMachineKey(); + Assert.AreNotEqual(input, encrypted); + Assert.AreEqual(input, decrypted); + } + + [Test()] + public void Encrypt_And_Decrypt_Long_Value() + { + // Generate a really long string + char[] chars = { 'a', 'b', 'c', '1', '2', '3', '\n' }; + + string valueToTest = string.Empty; + + // Create a string 7035 chars long + for (int i = 0; i < 1005; i++) + for (int j = 0; j < chars.Length; j++) + valueToTest += chars[j].ToString(); + + var encrypted = valueToTest.ToString().EncryptWithMachineKey(); + var decrypted = encrypted.DecryptWithMachineKey(); + Assert.AreNotEqual(valueToTest, encrypted); + Assert.AreEqual(valueToTest, decrypted); + } + + [TestCase("Hello this is my string", " string", "Hello this is my")] + [TestCase("Hello this is my string strung", " string", "Hello this is my string strung")] + [TestCase("Hello this is my string string", " string", "Hello this is my")] + [TestCase("Hello this is my string string", "g", "Hello this is my string strin")] + [TestCase("Hello this is my string string", "ello this is my string string", "H")] + [TestCase("Hello this is my string string", "Hello this is my string string", "")] + public void TrimEnd(string input, string forTrimming, string shouldBe) + { + var trimmed = input.TrimEnd(forTrimming); + Assert.AreEqual(shouldBe, trimmed); + } + + [TestCase("Hello this is my string", "hello", " this is my string")] + [TestCase("Hello this is my string", "Hello this", " is my string")] + [TestCase("Hello this is my string", "Hello this is my ", "string")] + [TestCase("Hello this is my string", "Hello this is my string", "")] + public void TrimStart(string input, string forTrimming, string shouldBe) + { + var trimmed = input.TrimStart(forTrimming); + Assert.AreEqual(shouldBe, trimmed); + } + + + [TestCase] + public void StringExtensions_To_Url_Alias() + { + var replacements = new Dictionary + { + {" ", "-"}, + {"\"", ""}, + {""", ""}, + {"@", ""}, + {"%", ""}, + {".", ""}, + {";", ""}, + {"/", ""}, + {":", ""}, + {"#", ""}, + {"+", ""}, + {"*", ""}, + {"&", ""}, + {"?", ""} + }; + + 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.ToUrlAlias(replacements, true, true, false); + var url2 = name2.ToUrlAlias(replacements, true, true, false); + var url3 = name3.ToUrlAlias(replacements, true, true, false); + var url4 = name4.ToUrlAlias(replacements, true, true, false); + var url5 = name5.ToUrlAlias(replacements, true, true, false); + var url6 = name6.ToUrlAlias(replacements, true, true, false); + var url7 = name6.ToUrlAlias(replacements, true, false, false); + var url8 = name6.ToUrlAlias(replacements, true, false, true); + + 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.ConvertCase(StringAliasCaseType.CamelCase); + var camelCase2 = name2.ConvertCase(StringAliasCaseType.CamelCase); + var camelCase3 = name3.ConvertCase(StringAliasCaseType.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.ToUmbracoAlias(); + var alias2 = name2.ToUmbracoAlias(); + var alias3 = name3.ToUmbracoAlias(); + var alias4 = name4.ToUmbracoAlias(); + var alias5 = name5.ToUmbracoAlias(/*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/CoreStrings/MockShortStringHelper.cs b/src/Umbraco.Tests/Strings/MockShortStringHelper.cs similarity index 95% rename from src/Umbraco.Tests/CoreStrings/MockShortStringHelper.cs rename to src/Umbraco.Tests/Strings/MockShortStringHelper.cs index 1b2dd5a370..dfdb307502 100644 --- a/src/Umbraco.Tests/CoreStrings/MockShortStringHelper.cs +++ b/src/Umbraco.Tests/Strings/MockShortStringHelper.cs @@ -1,92 +1,92 @@ -using System.Collections.Generic; -using Umbraco.Core.Strings; - -namespace Umbraco.Tests.CoreStrings -{ - class MockShortStringHelper : IShortStringHelper - { - public void Freeze() - { - IsFrozen = true; - } - - public bool IsFrozen { get; private set; } - - public string GetShortStringServicesJavaScript(string controllerPath) { return "SSSJS"; } - - public string CleanStringForSafeAlias(string text) - { - return "SAFE-ALIAS::" + text; - } - - public string CleanStringForSafeCamelAlias(string text) - { - return "SAFE-ALIAS::" + text; - } - - public string CleanStringForSafeAlias(string text, System.Globalization.CultureInfo culture) - { - return "SAFE-ALIAS-CULTURE::" + text; - } - - public string CleanStringForSafeCamelAlias(string text, System.Globalization.CultureInfo culture) - { - return "SAFE-ALIAS-CULTURE::" + text; - } - - public string CleanStringForUrlSegment(string text) - { - return "URL-SEGMENT::" + text; - } - - public string CleanStringForUrlSegment(string text, System.Globalization.CultureInfo culture) - { - return "URL-SEGMENT-CULTURE::" + text; - } - - public string CleanStringForSafeFileName(string text) - { - return "SAFE-FILE-NAME::" + text; - } - - public string CleanStringForSafeFileName(string text, System.Globalization.CultureInfo culture) - { - return "SAFE-FILE-NAME-CULTURE::" + text; - } - - public string SplitPascalCasing(string text, char separator) - { - return "SPLIT-PASCAL-CASING::" + text; - } - - public string ReplaceMany(string text, IDictionary replacements) - { - return "REPLACE-MANY-A::" + text; - } - - public string ReplaceMany(string text, char[] chars, char replacement) - { - return "REPLACE-MANY-B::" + text; - } - - public string CleanString(string text, CleanStringType stringType) - { - return "CLEAN-STRING-A::" + text; - } - - public string CleanString(string text, CleanStringType stringType, char separator) - { - return "CLEAN-STRING-B::" + text; - } - - public string CleanString(string text, CleanStringType stringType, System.Globalization.CultureInfo culture) - { - return "CLEAN-STRING-C::" + text; - } - - public string CleanString(string text, CleanStringType stringType, char separator, System.Globalization.CultureInfo culture) - { - return "CLEAN-STRING-D::" + text; - } - } -} +using System.Collections.Generic; +using Umbraco.Core.Strings; + +namespace Umbraco.Tests.Strings +{ + class MockShortStringHelper : IShortStringHelper + { + public void Freeze() + { + IsFrozen = true; + } + + public bool IsFrozen { get; private set; } + + public string GetShortStringServicesJavaScript(string controllerPath) { return "SSSJS"; } + + public string CleanStringForSafeAlias(string text) + { + return "SAFE-ALIAS::" + text; + } + + public string CleanStringForSafeCamelAlias(string text) + { + return "SAFE-ALIAS::" + text; + } + + public string CleanStringForSafeAlias(string text, System.Globalization.CultureInfo culture) + { + return "SAFE-ALIAS-CULTURE::" + text; + } + + public string CleanStringForSafeCamelAlias(string text, System.Globalization.CultureInfo culture) + { + return "SAFE-ALIAS-CULTURE::" + text; + } + + public string CleanStringForUrlSegment(string text) + { + return "URL-SEGMENT::" + text; + } + + public string CleanStringForUrlSegment(string text, System.Globalization.CultureInfo culture) + { + return "URL-SEGMENT-CULTURE::" + text; + } + + public string CleanStringForSafeFileName(string text) + { + return "SAFE-FILE-NAME::" + text; + } + + public string CleanStringForSafeFileName(string text, System.Globalization.CultureInfo culture) + { + return "SAFE-FILE-NAME-CULTURE::" + text; + } + + public string SplitPascalCasing(string text, char separator) + { + return "SPLIT-PASCAL-CASING::" + text; + } + + public string ReplaceMany(string text, IDictionary replacements) + { + return "REPLACE-MANY-A::" + text; + } + + public string ReplaceMany(string text, char[] chars, char replacement) + { + return "REPLACE-MANY-B::" + text; + } + + public string CleanString(string text, CleanStringType stringType) + { + return "CLEAN-STRING-A::" + text; + } + + public string CleanString(string text, CleanStringType stringType, char separator) + { + return "CLEAN-STRING-B::" + text; + } + + public string CleanString(string text, CleanStringType stringType, System.Globalization.CultureInfo culture) + { + return "CLEAN-STRING-C::" + text; + } + + public string CleanString(string text, CleanStringType stringType, char separator, System.Globalization.CultureInfo culture) + { + return "CLEAN-STRING-D::" + text; + } + } +} diff --git a/src/Umbraco.Tests/CoreStrings/ShortStringHelperResolverTest.cs b/src/Umbraco.Tests/Strings/ShortStringHelperResolverTest.cs similarity index 76% rename from src/Umbraco.Tests/CoreStrings/ShortStringHelperResolverTest.cs rename to src/Umbraco.Tests/Strings/ShortStringHelperResolverTest.cs index 8ac9a87d88..c40adbb9eb 100644 --- a/src/Umbraco.Tests/CoreStrings/ShortStringHelperResolverTest.cs +++ b/src/Umbraco.Tests/Strings/ShortStringHelperResolverTest.cs @@ -1,39 +1,33 @@ -using System; -using System.Collections.Generic; -using System.Globalization; -using System.Security; -using System.Text; -using NUnit.Framework; -using Umbraco.Core; -using Umbraco.Core.Strings; -using Umbraco.Core.ObjectResolution; - -namespace Umbraco.Tests.CoreStrings -{ - [TestFixture] - public class ShortStringHelperResolverTest - { - [SetUp] - public void Setup() - { - ShortStringHelperResolver.Reset(); - } - - [TearDown] - public void TearDown() - { - ShortStringHelperResolver.Reset(); - } - - [Test] - public void FreezesHelperWhenResolutionFreezes() - { - var helper = new MockShortStringHelper(); - ShortStringHelperResolver.Current = new ShortStringHelperResolver(helper); - Assert.IsFalse(helper.IsFrozen); - Resolution.Freeze(); - Assert.AreSame(helper, ShortStringHelperResolver.Current.Helper); - Assert.IsTrue(helper.IsFrozen); - } - } -} +using NUnit.Framework; +using Umbraco.Core.ObjectResolution; +using Umbraco.Core.Strings; + +namespace Umbraco.Tests.Strings +{ + [TestFixture] + public class ShortStringHelperResolverTest + { + [SetUp] + public void Setup() + { + ShortStringHelperResolver.Reset(); + } + + [TearDown] + public void TearDown() + { + ShortStringHelperResolver.Reset(); + } + + [Test] + public void FreezesHelperWhenResolutionFreezes() + { + var helper = new MockShortStringHelper(); + ShortStringHelperResolver.Current = new ShortStringHelperResolver(helper); + Assert.IsFalse(helper.IsFrozen); + Resolution.Freeze(); + Assert.AreSame(helper, ShortStringHelperResolver.Current.Helper); + Assert.IsTrue(helper.IsFrozen); + } + } +} diff --git a/src/Umbraco.Tests/CoreStrings/StringExtensionsTests.cs b/src/Umbraco.Tests/Strings/StringExtensionsTests.cs similarity index 96% rename from src/Umbraco.Tests/CoreStrings/StringExtensionsTests.cs rename to src/Umbraco.Tests/Strings/StringExtensionsTests.cs index 43e5d0fcf9..1bc4661de7 100644 --- a/src/Umbraco.Tests/CoreStrings/StringExtensionsTests.cs +++ b/src/Umbraco.Tests/Strings/StringExtensionsTests.cs @@ -1,220 +1,220 @@ -using System; -using System.Globalization; -using NUnit.Framework; -using Umbraco.Core; -using Umbraco.Core.Strings; -using Umbraco.Core.ObjectResolution; - -namespace Umbraco.Tests.CoreStrings -{ - [TestFixture] - public class StringExtensionsTests - { - [SetUp] - public void Setup() - { - ShortStringHelperResolver.Reset(); - ShortStringHelperResolver.Current = new ShortStringHelperResolver(new MockShortStringHelper()); - Resolution.Freeze(); - } - - [TearDown] - public void TearDown() - { - ShortStringHelperResolver.Reset(); - } - - [TestCase("hello.txt", "hello")] - [TestCase("this.is.a.Txt", "this.is.a")] - [TestCase("this.is.not.a. Txt", "this.is.not.a. Txt")] - [TestCase("not a file","not a file")] - public void Strip_File_Extension(string input, string result) - { - var stripped = input.StripFileExtension(); - Assert.AreEqual(stripped, result); - } - - [TestCase("This is a string to encrypt")] - [TestCase("This is a string to encrypt\nThis is a second line")] - [TestCase(" White space is preserved ")] - [TestCase("\nWhite space is preserved\n")] - public void Encrypt_And_Decrypt(string input) - { - var encrypted = input.EncryptWithMachineKey(); - var decrypted = encrypted.DecryptWithMachineKey(); - Assert.AreNotEqual(input, encrypted); - Assert.AreEqual(input, decrypted); - } - - [Test()] - public void Encrypt_And_Decrypt_Long_Value() - { - // Generate a really long string - char[] chars = { 'a', 'b', 'c', '1', '2', '3', '\n' }; - - string valueToTest = string.Empty; - - // Create a string 7035 chars long - for (int i = 0; i < 1005; i++) - for (int j = 0; j < chars.Length; j++) - valueToTest += chars[j].ToString(); - - var encrypted = valueToTest.EncryptWithMachineKey(); - var decrypted = encrypted.DecryptWithMachineKey(); - Assert.AreNotEqual(valueToTest, encrypted); - Assert.AreEqual(valueToTest, decrypted); - } - - [TestCase("Hello this is my string", " string", "Hello this is my")] - [TestCase("Hello this is my string strung", " string", "Hello this is my string strung")] - [TestCase("Hello this is my string string", " string", "Hello this is my")] - [TestCase("Hello this is my string string", "g", "Hello this is my string strin")] - [TestCase("Hello this is my string string", "ello this is my string string", "H")] - [TestCase("Hello this is my string string", "Hello this is my string string", "")] - public void TrimEnd(string input, string forTrimming, string shouldBe) - { - var trimmed = input.TrimEnd(forTrimming); - Assert.AreEqual(shouldBe, trimmed); - } - - [TestCase("Hello this is my string", "hello", " this is my string")] - [TestCase("Hello this is my string", "Hello this", " is my string")] - [TestCase("Hello this is my string", "Hello this is my ", "string")] - [TestCase("Hello this is my string", "Hello this is my string", "")] - public void TrimStart(string input, string forTrimming, string shouldBe) - { - var trimmed = input.TrimStart(forTrimming); - Assert.AreEqual(shouldBe, trimmed); - } - - [TestCase("Hello this is my string", "hello", "replaced", "replaced this is my string", StringComparison.CurrentCultureIgnoreCase)] - [TestCase("Hello this is hello my string", "hello", "replaced", "replaced this is replaced my string", StringComparison.CurrentCultureIgnoreCase)] - [TestCase("Hello this is my string", "nonexistent", "replaced", "Hello this is my string", StringComparison.CurrentCultureIgnoreCase)] - [TestCase("Hellohello this is my string", "hello", "replaced", "replacedreplaced this is my string", StringComparison.CurrentCultureIgnoreCase)] - // Ensure replacing with the same string doesn't cause infinite loop. - [TestCase("Hello this is my string", "hello", "hello", "hello this is my string", StringComparison.CurrentCultureIgnoreCase)] - public void ReplaceWithStringComparison(string input, string oldString, string newString, string shouldBe, StringComparison stringComparison) - { - var replaced = input.Replace(oldString, newString, stringComparison); - Assert.AreEqual(shouldBe, replaced); - } - - [TestCase(null, null)] - [TestCase("", "")] - [TestCase("x", "X")] - [TestCase("xyzT", "XyzT")] - [TestCase("XyzT", "XyzT")] - public void ToFirstUpper(string input, string expected) - { - var output = input.ToFirstUpper(); - Assert.AreEqual(expected, output); - } - - [TestCase(null, null)] - [TestCase("", "")] - [TestCase("X", "x")] - [TestCase("XyZ", "xyZ")] - [TestCase("xyZ", "xyZ")] - public void ToFirstLower(string input, string expected) - { - var output = input.ToFirstLower(); - Assert.AreEqual(expected, output); - } - - // FORMAT STRINGS - - // note: here we just ensure that the proper helper gets called properly - // but the "legacy" tests have moved to the legacy helper tests - - [Test] - public void ToUrlAlias() - { - var output = "JUST-ANYTHING".ToUrlSegment(); - Assert.AreEqual("URL-SEGMENT::JUST-ANYTHING", output); - } - - [Test] - public void FormatUrl() - { - var output = "JUST-ANYTHING".ToUrlSegment(); - Assert.AreEqual("URL-SEGMENT::JUST-ANYTHING", output); - } - - [Test] - public void ToUmbracoAlias() - { - var output = "JUST-ANYTHING".ToSafeAlias(); - Assert.AreEqual("SAFE-ALIAS::JUST-ANYTHING", output); - } - - [Test] - public void ToSafeAlias() - { - var output = "JUST-ANYTHING".ToSafeAlias(); - Assert.AreEqual("SAFE-ALIAS::JUST-ANYTHING", output); - } - - [Test] - public void ToSafeAliasWithCulture() - { - var output = "JUST-ANYTHING".ToSafeAlias(CultureInfo.InvariantCulture); - Assert.AreEqual("SAFE-ALIAS-CULTURE::JUST-ANYTHING", output); - } - - [Test] - public void ToUrlSegment() - { - var output = "JUST-ANYTHING".ToUrlSegment(); - Assert.AreEqual("URL-SEGMENT::JUST-ANYTHING", output); - } - - [Test] - public void ToUrlSegmentWithCulture() - { - var output = "JUST-ANYTHING".ToUrlSegment(CultureInfo.InvariantCulture); - Assert.AreEqual("URL-SEGMENT-CULTURE::JUST-ANYTHING", output); - } - - [Test] - public void ToSafeFileName() - { - var output = "JUST-ANYTHING".ToSafeFileName(); - Assert.AreEqual("SAFE-FILE-NAME::JUST-ANYTHING", output); - } - - [Test] - public void ToSafeFileNameWithCulture() - { - var output = "JUST-ANYTHING".ToSafeFileName(CultureInfo.InvariantCulture); - Assert.AreEqual("SAFE-FILE-NAME-CULTURE::JUST-ANYTHING", output); - } - - [Test] - public void ConvertCase() - { - var output = "JUST-ANYTHING".ToCleanString(CleanStringType.Unchanged); - Assert.AreEqual("CLEAN-STRING-A::JUST-ANYTHING", output); - } - - [Test] - public void SplitPascalCasing() - { - var output = "JUST-ANYTHING".SplitPascalCasing(); - Assert.AreEqual("SPLIT-PASCAL-CASING::JUST-ANYTHING", output); - } - - [Test] - public void ReplaceManyWithCharMap() - { - var output = "JUST-ANYTHING".ReplaceMany(null); - Assert.AreEqual("REPLACE-MANY-A::JUST-ANYTHING", output); - } - - [Test] - public void ReplaceManyByOneChar() - { - var output = "JUST-ANYTHING".ReplaceMany(new char[] {}, '*'); - Assert.AreEqual("REPLACE-MANY-B::JUST-ANYTHING", output); - } - } -} +using System; +using System.Globalization; +using NUnit.Framework; +using Umbraco.Core; +using Umbraco.Core.ObjectResolution; +using Umbraco.Core.Strings; + +namespace Umbraco.Tests.Strings +{ + [TestFixture] + public class StringExtensionsTests + { + [SetUp] + public void Setup() + { + ShortStringHelperResolver.Reset(); + ShortStringHelperResolver.Current = new ShortStringHelperResolver(new MockShortStringHelper()); + Resolution.Freeze(); + } + + [TearDown] + public void TearDown() + { + ShortStringHelperResolver.Reset(); + } + + [TestCase("hello.txt", "hello")] + [TestCase("this.is.a.Txt", "this.is.a")] + [TestCase("this.is.not.a. Txt", "this.is.not.a. Txt")] + [TestCase("not a file","not a file")] + public void Strip_File_Extension(string input, string result) + { + var stripped = input.StripFileExtension(); + Assert.AreEqual(stripped, result); + } + + [TestCase("This is a string to encrypt")] + [TestCase("This is a string to encrypt\nThis is a second line")] + [TestCase(" White space is preserved ")] + [TestCase("\nWhite space is preserved\n")] + public void Encrypt_And_Decrypt(string input) + { + var encrypted = input.EncryptWithMachineKey(); + var decrypted = encrypted.DecryptWithMachineKey(); + Assert.AreNotEqual(input, encrypted); + Assert.AreEqual(input, decrypted); + } + + [Test()] + public void Encrypt_And_Decrypt_Long_Value() + { + // Generate a really long string + char[] chars = { 'a', 'b', 'c', '1', '2', '3', '\n' }; + + string valueToTest = string.Empty; + + // Create a string 7035 chars long + for (int i = 0; i < 1005; i++) + for (int j = 0; j < chars.Length; j++) + valueToTest += chars[j].ToString(); + + var encrypted = valueToTest.EncryptWithMachineKey(); + var decrypted = encrypted.DecryptWithMachineKey(); + Assert.AreNotEqual(valueToTest, encrypted); + Assert.AreEqual(valueToTest, decrypted); + } + + [TestCase("Hello this is my string", " string", "Hello this is my")] + [TestCase("Hello this is my string strung", " string", "Hello this is my string strung")] + [TestCase("Hello this is my string string", " string", "Hello this is my")] + [TestCase("Hello this is my string string", "g", "Hello this is my string strin")] + [TestCase("Hello this is my string string", "ello this is my string string", "H")] + [TestCase("Hello this is my string string", "Hello this is my string string", "")] + public void TrimEnd(string input, string forTrimming, string shouldBe) + { + var trimmed = input.TrimEnd(forTrimming); + Assert.AreEqual(shouldBe, trimmed); + } + + [TestCase("Hello this is my string", "hello", " this is my string")] + [TestCase("Hello this is my string", "Hello this", " is my string")] + [TestCase("Hello this is my string", "Hello this is my ", "string")] + [TestCase("Hello this is my string", "Hello this is my string", "")] + public void TrimStart(string input, string forTrimming, string shouldBe) + { + var trimmed = input.TrimStart(forTrimming); + Assert.AreEqual(shouldBe, trimmed); + } + + [TestCase("Hello this is my string", "hello", "replaced", "replaced this is my string", StringComparison.CurrentCultureIgnoreCase)] + [TestCase("Hello this is hello my string", "hello", "replaced", "replaced this is replaced my string", StringComparison.CurrentCultureIgnoreCase)] + [TestCase("Hello this is my string", "nonexistent", "replaced", "Hello this is my string", StringComparison.CurrentCultureIgnoreCase)] + [TestCase("Hellohello this is my string", "hello", "replaced", "replacedreplaced this is my string", StringComparison.CurrentCultureIgnoreCase)] + // Ensure replacing with the same string doesn't cause infinite loop. + [TestCase("Hello this is my string", "hello", "hello", "hello this is my string", StringComparison.CurrentCultureIgnoreCase)] + public void ReplaceWithStringComparison(string input, string oldString, string newString, string shouldBe, StringComparison stringComparison) + { + var replaced = input.Replace(oldString, newString, stringComparison); + Assert.AreEqual(shouldBe, replaced); + } + + [TestCase(null, null)] + [TestCase("", "")] + [TestCase("x", "X")] + [TestCase("xyzT", "XyzT")] + [TestCase("XyzT", "XyzT")] + public void ToFirstUpper(string input, string expected) + { + var output = input.ToFirstUpper(); + Assert.AreEqual(expected, output); + } + + [TestCase(null, null)] + [TestCase("", "")] + [TestCase("X", "x")] + [TestCase("XyZ", "xyZ")] + [TestCase("xyZ", "xyZ")] + public void ToFirstLower(string input, string expected) + { + var output = input.ToFirstLower(); + Assert.AreEqual(expected, output); + } + + // FORMAT STRINGS + + // note: here we just ensure that the proper helper gets called properly + // but the "legacy" tests have moved to the legacy helper tests + + [Test] + public void ToUrlAlias() + { + var output = "JUST-ANYTHING".ToUrlSegment(); + Assert.AreEqual("URL-SEGMENT::JUST-ANYTHING", output); + } + + [Test] + public void FormatUrl() + { + var output = "JUST-ANYTHING".ToUrlSegment(); + Assert.AreEqual("URL-SEGMENT::JUST-ANYTHING", output); + } + + [Test] + public void ToUmbracoAlias() + { + var output = "JUST-ANYTHING".ToSafeAlias(); + Assert.AreEqual("SAFE-ALIAS::JUST-ANYTHING", output); + } + + [Test] + public void ToSafeAlias() + { + var output = "JUST-ANYTHING".ToSafeAlias(); + Assert.AreEqual("SAFE-ALIAS::JUST-ANYTHING", output); + } + + [Test] + public void ToSafeAliasWithCulture() + { + var output = "JUST-ANYTHING".ToSafeAlias(CultureInfo.InvariantCulture); + Assert.AreEqual("SAFE-ALIAS-CULTURE::JUST-ANYTHING", output); + } + + [Test] + public void ToUrlSegment() + { + var output = "JUST-ANYTHING".ToUrlSegment(); + Assert.AreEqual("URL-SEGMENT::JUST-ANYTHING", output); + } + + [Test] + public void ToUrlSegmentWithCulture() + { + var output = "JUST-ANYTHING".ToUrlSegment(CultureInfo.InvariantCulture); + Assert.AreEqual("URL-SEGMENT-CULTURE::JUST-ANYTHING", output); + } + + [Test] + public void ToSafeFileName() + { + var output = "JUST-ANYTHING".ToSafeFileName(); + Assert.AreEqual("SAFE-FILE-NAME::JUST-ANYTHING", output); + } + + [Test] + public void ToSafeFileNameWithCulture() + { + var output = "JUST-ANYTHING".ToSafeFileName(CultureInfo.InvariantCulture); + Assert.AreEqual("SAFE-FILE-NAME-CULTURE::JUST-ANYTHING", output); + } + + [Test] + public void ConvertCase() + { + var output = "JUST-ANYTHING".ToCleanString(CleanStringType.Unchanged); + Assert.AreEqual("CLEAN-STRING-A::JUST-ANYTHING", output); + } + + [Test] + public void SplitPascalCasing() + { + var output = "JUST-ANYTHING".SplitPascalCasing(); + Assert.AreEqual("SPLIT-PASCAL-CASING::JUST-ANYTHING", output); + } + + [Test] + public void ReplaceManyWithCharMap() + { + var output = "JUST-ANYTHING".ReplaceMany(null); + Assert.AreEqual("REPLACE-MANY-A::JUST-ANYTHING", output); + } + + [Test] + public void ReplaceManyByOneChar() + { + var output = "JUST-ANYTHING".ReplaceMany(new char[] {}, '*'); + Assert.AreEqual("REPLACE-MANY-B::JUST-ANYTHING", output); + } + } +} diff --git a/src/Umbraco.Tests/CoreStrings/StringValidationTests.cs b/src/Umbraco.Tests/Strings/StringValidationTests.cs similarity index 95% rename from src/Umbraco.Tests/CoreStrings/StringValidationTests.cs rename to src/Umbraco.Tests/Strings/StringValidationTests.cs index c1f8b92438..c1261a570e 100644 --- a/src/Umbraco.Tests/CoreStrings/StringValidationTests.cs +++ b/src/Umbraco.Tests/Strings/StringValidationTests.cs @@ -1,7 +1,7 @@ using System.ComponentModel.DataAnnotations; using NUnit.Framework; -namespace Umbraco.Tests.CoreStrings +namespace Umbraco.Tests.Strings { [TestFixture] public class StringValidationTests diff --git a/src/Umbraco.Tests/Strings/StylesheetHelperTests.cs b/src/Umbraco.Tests/Strings/StylesheetHelperTests.cs new file mode 100644 index 0000000000..3f9f972b16 --- /dev/null +++ b/src/Umbraco.Tests/Strings/StylesheetHelperTests.cs @@ -0,0 +1,132 @@ +using System.Linq; +using System.Text; +using NUnit.Framework; +using Umbraco.Core.Strings.Css; + +namespace Umbraco.Tests.Strings +{ + [TestFixture] + public class StylesheetHelperTests + { + [Test] + public void Replace_Rule() + { + var css = @"body {font-family:Arial;}/** Umb_Name: Test1 */ p { font-size: 1em; } /** umb_name: Test2 */ li {padding:0px;} table {margin:0;}"; + var results = StylesheetHelper.ParseRules(css); + + var result = StylesheetHelper.ReplaceRule(css, results.First().Name, new StylesheetRule() + { + Name = "My new rule", + Selector = "p", + Styles = "font-size:1em; color:blue;" + }); + + Assert.AreEqual(@"body {font-family:Arial;}/**umb_name:My new rule*/ +p{font-size:1em; color:blue;} /** umb_name: Test2 */ li {padding:0px;} table {margin:0;}", result); + } + + [Test] + public void Append_Rule() + { + var css = @"body {font-family:Arial;}/** Umb_Name: Test1 */ p { font-size: 1em; } /** umb_name: Test2 */ li {padding:0px;} table {margin:0;}"; + + var result = StylesheetHelper.AppendRule(css, new StylesheetRule() + { + Name = "My new rule", + Selector = "p", + Styles = "font-size:1em; color:blue;" + }); + + Assert.AreEqual(@"body {font-family:Arial;}/** Umb_Name: Test1 */ p { font-size: 1em; } /** umb_name: Test2 */ li {padding:0px;} table {margin:0;} + +/**umb_name:My new rule*/ +p{font-size:1em; color:blue;}", result); + } + + [Test] + public void Duplicate_Names() + { + var css = @"/** Umb_Name: Test */ p { font-size: 1em; } /** umb_name: Test */ li {padding:0px;}"; + var results = StylesheetHelper.ParseRules(css); + Assert.AreEqual(1, results.Count()); + } + + // Standard rule stle + [TestCase("Test", "p", "font-size: 1em;", @"/** + Umb_Name: Test +*/ +p { + font-size: 1em; +}")] + // All on one line, different casing + [TestCase("Test", "p", "font-size: 1em;", @"/** Umb_Name: Test */ p { font-size: 1em; }")] + // styles on several lines + [TestCase("Test", "p", @"font-size: 1em; +color:red; font-weight:bold; + +text-align:left;", @"/** umb_name: Test */ p { font-size: 1em; +color:red; font-weight:bold; + +text-align:left; + +}")] + // All on one line with no spaces + [TestCase("Test", "p", "font-size: 1em;", @"/**UMB_NAME:Test*/p{font-size: 1em;}")] + // Has a name with spaces + [TestCase("Hello world", "p", "font-size: 1em;", @"/**UMB_NAME:Hello world */p{font-size: 1em;}")] + // Every part on a new line + [TestCase("Test", "p", "font-size: 1em;", @"/** +umb_name: +Test +*/ +p +{ +font-size: 1em; +}")] + public void ParseRules_Parses(string name, string selector, string styles, string css) + { + + // Act + var results = StylesheetHelper.ParseRules(css); + + // Assert + Assert.AreEqual(1, results.Count()); + + //Assert.IsTrue(results.First().RuleId.Value.Value.ToString() == file.Id.Value.Value + "/" + name); + Assert.AreEqual(name, results.First().Name); + Assert.AreEqual(selector, results.First().Selector); + Assert.AreEqual(styles, results.First().Styles); + } + + // No Name: keyword + [TestCase(@"/** Test2 */ +p +{ + font-size: 1em; +}")] + // Has a Name: keyword, but applies to 2 rules, so shouldn't parse + [TestCase(@"/** umb_name: Test2 */ +p, h2 +{ + font-size: 1em; +}")] + // Has it's name wrapping over two lines + [TestCase("/** umb_name: Test\r\n2 */ p { font-size: 1em; }")] + [TestCase("/** umb_name: Test\n2 */ p { font-size: 1em; }")] + //Only a single asterisk + [TestCase("/* umb_name: Test */ p { font-size: 1em; }")] + // Has a name with spaces over multiple lines + [TestCase(@"/**UMB_NAME:Hello + +world */p{font-size: 1em;}")] + public void ParseRules_DoesntParse(string css) + { + + // Act + var results = StylesheetHelper.ParseRules(css); + + // Assert + Assert.IsTrue(results.Count() == 0); + } + } +} diff --git a/src/Umbraco.Tests/Templates/MasterPageHelperTests.cs b/src/Umbraco.Tests/Templates/MasterPageHelperTests.cs index f52b7b68d9..6da4fbc07e 100644 --- a/src/Umbraco.Tests/Templates/MasterPageHelperTests.cs +++ b/src/Umbraco.Tests/Templates/MasterPageHelperTests.cs @@ -4,6 +4,8 @@ using System.Linq; using System.Text; using NUnit.Framework; using umbraco.cms.businesslogic.template; +using Umbraco.Core.IO; +using Umbraco.Core.Services; namespace Umbraco.Tests.Templates { diff --git a/src/Umbraco.Tests/TestHelpers/BaseDatabaseFactoryTest.cs b/src/Umbraco.Tests/TestHelpers/BaseDatabaseFactoryTest.cs index 4618888883..ba20a0b842 100644 --- a/src/Umbraco.Tests/TestHelpers/BaseDatabaseFactoryTest.cs +++ b/src/Umbraco.Tests/TestHelpers/BaseDatabaseFactoryTest.cs @@ -7,11 +7,13 @@ using System.IO; using System.Linq; using System.Web.Routing; using System.Xml; +using Moq; using NUnit.Framework; using SQLCE4Umbraco; using Umbraco.Core; using Umbraco.Core.Cache; using Umbraco.Core.Configuration; +using Umbraco.Core.Configuration.UmbracoSettings; using Umbraco.Core.Logging; using Umbraco.Core.Models.PublishedContent; using Umbraco.Core.ObjectResolution; @@ -68,21 +70,25 @@ namespace Umbraco.Tests.TestHelpers var dbFactory = new DefaultDatabaseFactory( GetDbConnectionString(), - GetDbProviderName()); + GetDbProviderName(), + Logger); + + var repositoryFactory = new RepositoryFactory(cacheHelper, Logger, SqlSyntaxProvider, SettingsForTests.GenerateMockSettings()); _appContext = new ApplicationContext( //assign the db context - new DatabaseContext(dbFactory), + new DatabaseContext(dbFactory, Logger, SqlSyntaxProvider, "System.Data.SqlServerCe.4.0"), //assign the service context - new ServiceContext(new PetaPocoUnitOfWorkProvider(dbFactory), new FileUnitOfWorkProvider(), new PublishingStrategy(), cacheHelper), - cacheHelper) + new ServiceContext(repositoryFactory, new PetaPocoUnitOfWorkProvider(dbFactory), new FileUnitOfWorkProvider(), new PublishingStrategy(), cacheHelper, Logger), + cacheHelper, + ProfilingLogger) { IsReady = true }; base.Initialize(); - using (DisposableTimer.TraceDuration("init")) + using (ProfilingLogger.TraceDuration("init")) { //TODO: Somehow make this faster - takes 5s + @@ -95,6 +101,11 @@ namespace Umbraco.Tests.TestHelpers } } + protected virtual ISqlSyntaxProvider SqlSyntaxProvider + { + get { return new SqlCeSyntaxProvider(); } + } + protected override void SetupApplicationContext() { ApplicationContext.Current = _appContext; @@ -122,7 +133,7 @@ namespace Umbraco.Tests.TestHelpers /// protected virtual string GetDbConnectionString() { - return @"Datasource=|DataDirectory|UmbracoPetaPocoTests.sdf;Flush Interval=1;"; + return @"Datasource=|DataDirectory|UmbracoPetaPocoTests.sdf;Flush Interval=1;"; } /// @@ -134,11 +145,11 @@ namespace Umbraco.Tests.TestHelpers return; var path = TestHelper.CurrentAssemblyDirectory; - + //Get the connectionstring settings from config var settings = ConfigurationManager.ConnectionStrings[Core.Configuration.GlobalSettings.UmbracoConnectionName]; ConfigurationManager.AppSettings.Set( - Core.Configuration.GlobalSettings.UmbracoConnectionName, + Core.Configuration.GlobalSettings.UmbracoConnectionName, GetDbConnectionString()); _dbPath = string.Concat(path, "\\UmbracoPetaPocoTests.sdf"); @@ -150,12 +161,12 @@ namespace Umbraco.Tests.TestHelpers // - _isFirstTestInFixture + DbInitBehavior.NewDbFileAndSchemaPerFixture //if this is the first test in the session, always ensure a new db file is created - if (_isFirstRunInTestSession || File.Exists(_dbPath) == false + if (_isFirstRunInTestSession || File.Exists(_dbPath) == false || DatabaseTestBehavior == DatabaseBehavior.NewDbFileAndSchemaPerTest || (_isFirstTestInFixture && DatabaseTestBehavior == DatabaseBehavior.NewDbFileAndSchemaPerFixture)) { - - using (DisposableTimer.TraceDuration("Remove database file")) + + using (ProfilingLogger.TraceDuration("Remove database file")) { RemoveDatabaseFile(ex => { @@ -167,7 +178,7 @@ namespace Umbraco.Tests.TestHelpers } //Create the Sql CE database - using (DisposableTimer.TraceDuration("Create database file")) + using (ProfilingLogger.TraceDuration("Create database file")) { if (_dbBytes != null) { @@ -176,10 +187,10 @@ namespace Umbraco.Tests.TestHelpers else { var engine = new SqlCeEngine(settings.ConnectionString); - engine.CreateDatabase(); + engine.CreateDatabase(); } } - + } } @@ -190,20 +201,17 @@ namespace Umbraco.Tests.TestHelpers protected override void FreezeResolution() { PropertyEditorResolver.Current = new PropertyEditorResolver( + new ActivatorServiceProvider(), Logger, () => PluginManager.Current.ResolvePropertyEditors()); - - RepositoryResolver.Current = new RepositoryResolver( - new RepositoryFactory(true)); //disable all repo caches for tests! - - SqlSyntaxProvidersResolver.Current = new SqlSyntaxProvidersResolver( - new List { typeof(MySqlSyntaxProvider), typeof(SqlCeSyntaxProvider), typeof(SqlServerSyntaxProvider) }) { CanResolveBeforeFrozen = true }; + new ActivatorServiceProvider(), Logger, MappingResolver.Current = new MappingResolver( + new ActivatorServiceProvider(), Logger, () => PluginManager.Current.ResolveAssignedMapperTypes()); if (PropertyValueConvertersResolver.HasCurrent == false) - PropertyValueConvertersResolver.Current = new PropertyValueConvertersResolver(); + PropertyValueConvertersResolver.Current = new PropertyValueConvertersResolver(new ActivatorServiceProvider(), Logger); if (PublishedContentModelFactoryResolver.HasCurrent == false) PublishedContentModelFactoryResolver.Current = new PublishedContentModelFactoryResolver(); @@ -224,20 +232,22 @@ namespace Umbraco.Tests.TestHelpers // - NewDbFileAndSchemaPerTest // - _isFirstTestInFixture + DbInitBehavior.NewDbFileAndSchemaPerFixture - if (_dbBytes == null && + if (_dbBytes == null && (_isFirstRunInTestSession || DatabaseTestBehavior == DatabaseBehavior.NewDbFileAndSchemaPerTest || (_isFirstTestInFixture && DatabaseTestBehavior == DatabaseBehavior.NewDbFileAndSchemaPerFixture))) { + + var schemaHelper = new DatabaseSchemaHelper(DatabaseContext.Database, Logger, SqlSyntaxProvider); //Create the umbraco database and its base data - DatabaseContext.Database.CreateDatabaseSchema(false); + schemaHelper.CreateDatabaseSchema(false, ApplicationContext); //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(); _dbBytes = File.ReadAllBytes(_dbPath); - } + } } [TestFixtureTearDown] @@ -249,7 +259,7 @@ namespace Umbraco.Tests.TestHelpers [TearDown] public override void TearDown() { - using (DisposableTimer.TraceDuration("teardown")) + using (ProfilingLogger.TraceDuration("teardown")) { _isFirstTestInFixture = false; //ensure this is false before anything! @@ -262,7 +272,7 @@ namespace Umbraco.Tests.TestHelpers SqlSyntaxContext.SqlSyntaxProvider = null; } - + base.TearDown(); } @@ -327,15 +337,15 @@ namespace Umbraco.Tests.TestHelpers } } - protected ServiceContext ServiceContext - { - get { return ApplicationContext.Services; } - } + protected ServiceContext ServiceContext + { + get { return ApplicationContext.Services; } + } - protected DatabaseContext DatabaseContext - { - get { return ApplicationContext.DatabaseContext; } - } + protected DatabaseContext DatabaseContext + { + get { return ApplicationContext.DatabaseContext; } + } protected UmbracoContext GetUmbracoContext(string url, int templateId, RouteData routeData = null, bool setSingleton = false) { diff --git a/src/Umbraco.Tests/TestHelpers/BaseDatabaseTest.cs b/src/Umbraco.Tests/TestHelpers/BaseDatabaseTest.cs index 69000d7709..eedd100a0d 100644 --- a/src/Umbraco.Tests/TestHelpers/BaseDatabaseTest.cs +++ b/src/Umbraco.Tests/TestHelpers/BaseDatabaseTest.cs @@ -2,16 +2,21 @@ using System.Collections.Generic; using System.Data.SqlServerCe; using System.IO; +using Moq; using NUnit.Framework; using Umbraco.Core; using Umbraco.Core.Cache; using Umbraco.Core.Configuration; +using Umbraco.Core.Configuration.UmbracoSettings; +using Umbraco.Core.Logging; using Umbraco.Core.ObjectResolution; using Umbraco.Core.Persistence; using Umbraco.Core.Persistence.SqlSyntax; using Umbraco.Core.Persistence.UnitOfWork; +using Umbraco.Core.Profiling; using Umbraco.Core.Publishing; using Umbraco.Core.Services; +using GlobalSettings = Umbraco.Core.Configuration.GlobalSettings; namespace Umbraco.Tests.TestHelpers { @@ -25,13 +30,15 @@ namespace Umbraco.Tests.TestHelpers public abstract class BaseDatabaseTest { private Database _database; + protected ILogger Logger { get; private set; } [SetUp] public virtual void Initialize() { - TestHelper.SetupLog4NetForTests(); TestHelper.InitializeContentDirectories(); + Logger = new Logger(new FileInfo(TestHelper.MapPathForTest("~/unit-test-log4net.config"))); + string path = TestHelper.CurrentAssemblyDirectory; AppDomain.CurrentDomain.SetData("DataDirectory", path); @@ -53,24 +60,21 @@ namespace Umbraco.Tests.TestHelpers throw; } - - RepositoryResolver.Current = new RepositoryResolver( - new RepositoryFactory(true)); //disable all repo caches for tests! - - SqlSyntaxProvidersResolver.Current = new SqlSyntaxProvidersResolver( - new List { typeof(MySqlSyntaxProvider), typeof(SqlCeSyntaxProvider), typeof(SqlServerSyntaxProvider) }) { CanResolveBeforeFrozen = true }; - Resolution.Freeze(); //disable cache var cacheHelper = CacheHelper.CreateDisabledCacheHelper(); + var logger = new Logger(new FileInfo(TestHelper.MapPathForTest("~/unit-test-log4net.config"))); + var repositoryFactory = new RepositoryFactory(cacheHelper, Logger, SyntaxProvider, SettingsForTests.GenerateMockSettings()); + var dbFactory = new DefaultDatabaseFactory(GlobalSettings.UmbracoConnectionName, logger); ApplicationContext.Current = new ApplicationContext( //assign the db context - new DatabaseContext(new DefaultDatabaseFactory()), + new DatabaseContext(dbFactory, logger, SqlSyntaxProviders.CreateDefault(logger)), //assign the service context - new ServiceContext(new PetaPocoUnitOfWorkProvider(), new FileUnitOfWorkProvider(), new PublishingStrategy(), cacheHelper), - cacheHelper) + new ServiceContext(repositoryFactory, new PetaPocoUnitOfWorkProvider(dbFactory), new FileUnitOfWorkProvider(), new PublishingStrategy(), cacheHelper, logger), + cacheHelper, + new ProfilingLogger(logger, Mock.Of())) { IsReady = true }; @@ -98,8 +102,6 @@ namespace Umbraco.Tests.TestHelpers //reset the app context ApplicationContext.Current = null; - - RepositoryResolver.Reset(); } } } \ No newline at end of file diff --git a/src/Umbraco.Tests/TestHelpers/BaseSeleniumTest.cs b/src/Umbraco.Tests/TestHelpers/BaseSeleniumTest.cs index 1a4ae05160..3f7a59050c 100644 --- a/src/Umbraco.Tests/TestHelpers/BaseSeleniumTest.cs +++ b/src/Umbraco.Tests/TestHelpers/BaseSeleniumTest.cs @@ -3,10 +3,12 @@ using System.Data.SqlServerCe; using System.Diagnostics; using System.IO; using System.Text; +using Moq; using NUnit.Framework; using OpenQA.Selenium; using OpenQA.Selenium.Firefox; using Umbraco.Core; +using Umbraco.Core.Logging; using Umbraco.Core.Persistence; using Umbraco.Core.Persistence.Migrations.Initial; using Umbraco.Core.Persistence.SqlSyntax; @@ -49,12 +51,13 @@ namespace Umbraco.Tests.TestHelpers if (File.Exists(databaseDataPath) == false) engine.CreateDatabase(); - SqlSyntaxContext.SqlSyntaxProvider = new SqlCeSyntaxProvider(); + var syntaxProvider = new SqlCeSyntaxProvider(); + SqlSyntaxContext.SqlSyntaxProvider = syntaxProvider; - _database = new UmbracoDatabase(connectionString, "System.Data.SqlServerCe.4.0"); + _database = new UmbracoDatabase(connectionString, "System.Data.SqlServerCe.4.0", Mock.Of()); // First remove anything in the database - var creation = new DatabaseSchemaCreation(_database); + var creation = new DatabaseSchemaCreation(_database, Mock.Of(), syntaxProvider); creation.UninstallDatabaseSchema(); // Then populate it with fresh data diff --git a/src/Umbraco.Tests/TestHelpers/BaseUmbracoApplicationTest.cs b/src/Umbraco.Tests/TestHelpers/BaseUmbracoApplicationTest.cs index 3aa30e2893..63f65adeba 100644 --- a/src/Umbraco.Tests/TestHelpers/BaseUmbracoApplicationTest.cs +++ b/src/Umbraco.Tests/TestHelpers/BaseUmbracoApplicationTest.cs @@ -1,13 +1,17 @@ using System.Collections; using System.Collections.Generic; +using System.IO; using System.Reflection; using AutoMapper; using NUnit.Framework; using Umbraco.Core; +using Umbraco.Core.Logging; using Umbraco.Core.Models.Mapping; using Umbraco.Core.ObjectResolution; 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; @@ -26,26 +30,32 @@ namespace Umbraco.Tests.TestHelpers public abstract class BaseUmbracoApplicationTest : BaseUmbracoConfigurationTest { + [TestFixtureSetUp] + public void InitializeFixture() + { + var logger = new Logger(new FileInfo(TestHelper.MapPathForTest("~/unit-test-log4net.config"))); + ProfilingLogger = new ProfilingLogger(logger, new LogProfiler(logger)); + } + [SetUp] public override void Initialize() { base.Initialize(); - using (DisposableTimer.TraceDuration("init", "init")) - { - TestHelper.InitializeContentDirectories(); - - InitializeLegacyMappingsForCoreEditors(); + TestHelper.InitializeContentDirectories(); - SetupPluginManager(); + SetupCacheHelper(); - SetupApplicationContext(); + InitializeLegacyMappingsForCoreEditors(); - InitializeMappers(); + SetupPluginManager(); + + SetupApplicationContext(); + + InitializeMappers(); + + FreezeResolution(); - FreezeResolution(); - } - } [TearDown] @@ -53,22 +63,20 @@ namespace Umbraco.Tests.TestHelpers { base.TearDown(); - using (DisposableTimer.TraceDuration("teardown")) - { - //reset settings - SettingsForTests.Reset(); - UmbracoContext.Current = null; - TestHelper.CleanContentDirectories(); - TestHelper.CleanUmbracoSettingsConfig(); - //reset the app context, this should reset most things that require resetting like ALL resolvers - ObjectExtensions.DisposeIfDisposable(ApplicationContext.Current); - ApplicationContext.Current = null; - ResetPluginManager(); - } - + LoggerResolver.Reset(); + //reset settings + SettingsForTests.Reset(); + UmbracoContext.Current = null; + TestHelper.CleanContentDirectories(); + TestHelper.CleanUmbracoSettingsConfig(); + //reset the app context, this should reset most things that require resetting like ALL resolvers + ObjectExtensions.DisposeIfDisposable(ApplicationContext.Current); + ApplicationContext.Current = null; + ResetPluginManager(); + } - - private static readonly object Locker = new object(); + + private static readonly object Locker = new object(); private static void InitializeLegacyMappingsForCoreEditors() { @@ -79,9 +87,9 @@ namespace Umbraco.Tests.TestHelpers //Create the legacy prop-eds mapping LegacyPropertyEditorIdToAliasConverter.CreateMappingsForCoreEditors(); } - } + } } - + /// /// If this class requires auto-mapper mapping initialization then init them /// @@ -105,7 +113,7 @@ namespace Umbraco.Tests.TestHelpers { mapper.ConfigureMappings(configuration, ApplicationContext); } - }); + }); } } @@ -126,24 +134,32 @@ namespace Umbraco.Tests.TestHelpers { if (PluginManagerResetRequired) { - PluginManager.Current = null; + PluginManager.Current = null; } } + protected virtual void SetupCacheHelper() + { + CacheHelper = CacheHelper.CreateDisabledCacheHelper(); + } + /// /// Inheritors can override this if they wish to create a custom application context /// protected virtual void SetupApplicationContext() { - //disable cache - var cacheHelper = CacheHelper.CreateDisabledCacheHelper(); + + var sqlSyntax = new SqlCeSyntaxProvider(); + var repoFactory = new RepositoryFactory(CacheHelper.CreateDisabledCacheHelper(), Logger, sqlSyntax, SettingsForTests.GenerateMockSettings()); ApplicationContext.Current = new ApplicationContext( //assign the db context - new DatabaseContext(new DefaultDatabaseFactory()), + new DatabaseContext(new DefaultDatabaseFactory(Core.Configuration.GlobalSettings.UmbracoConnectionName, Logger), + Logger, sqlSyntax, "System.Data.SqlServerCe.4.0"), //assign the service context - new ServiceContext(new PetaPocoUnitOfWorkProvider(), new FileUnitOfWorkProvider(), new PublishingStrategy(), cacheHelper), - cacheHelper) + new ServiceContext(repoFactory, new PetaPocoUnitOfWorkProvider(Logger), new FileUnitOfWorkProvider(), new PublishingStrategy(), CacheHelper, Logger), + CacheHelper, + ProfilingLogger) { IsReady = true }; @@ -156,19 +172,23 @@ namespace Umbraco.Tests.TestHelpers { if (PluginManager.Current == null || PluginManagerResetRequired) { - PluginManager.Current = new PluginManager(false); - PluginManager.Current.AssembliesToScan = new[] + PluginManager.Current = new PluginManager( + new ActivatorServiceProvider(), + CacheHelper.RuntimeCache, ProfilingLogger, false) { - Assembly.Load("Umbraco.Core"), - Assembly.Load("umbraco"), - Assembly.Load("Umbraco.Tests"), - Assembly.Load("businesslogic"), - Assembly.Load("cms"), - Assembly.Load("controls"), - Assembly.Load("umbraco.editorControls"), - Assembly.Load("umbraco.MacroEngines"), - Assembly.Load("umbraco.providers"), - Assembly.Load("Umbraco.Web.UI"), + AssembliesToScan = new[] + { + Assembly.Load("Umbraco.Core"), + Assembly.Load("umbraco"), + Assembly.Load("Umbraco.Tests"), + Assembly.Load("businesslogic"), + Assembly.Load("cms"), + Assembly.Load("controls"), + Assembly.Load("umbraco.editorControls"), + Assembly.Load("umbraco.MacroEngines"), + Assembly.Load("umbraco.providers"), + Assembly.Load("Umbraco.Web.UI"), + } }; } } @@ -185,5 +205,12 @@ namespace Umbraco.Tests.TestHelpers { get { return ApplicationContext.Current; } } + + protected ILogger Logger + { + get { return ProfilingLogger.Logger; } + } + protected ProfilingLogger ProfilingLogger { get; private set; } + protected CacheHelper CacheHelper { get; private set; } } } \ No newline at end of file diff --git a/src/Umbraco.Tests/TestHelpers/BaseUmbracoConfigurationTest.cs b/src/Umbraco.Tests/TestHelpers/BaseUmbracoConfigurationTest.cs index bf5f0516bd..7f59c3e0b5 100644 --- a/src/Umbraco.Tests/TestHelpers/BaseUmbracoConfigurationTest.cs +++ b/src/Umbraco.Tests/TestHelpers/BaseUmbracoConfigurationTest.cs @@ -10,11 +10,7 @@ namespace Umbraco.Tests.TestHelpers [TestFixture] public abstract class BaseUmbracoConfigurationTest { - [TestFixtureSetUp] - public void InitializeFixture() - { - TestHelper.SetupLog4NetForTests(); - } + [SetUp] public virtual void Initialize() diff --git a/src/Umbraco.Tests/TestHelpers/BaseUsingSqlCeSyntax.cs b/src/Umbraco.Tests/TestHelpers/BaseUsingSqlCeSyntax.cs index 797e935c08..b77b915ac7 100644 --- a/src/Umbraco.Tests/TestHelpers/BaseUsingSqlCeSyntax.cs +++ b/src/Umbraco.Tests/TestHelpers/BaseUsingSqlCeSyntax.cs @@ -1,8 +1,12 @@ -using NUnit.Framework; +using Moq; +using NUnit.Framework; using Umbraco.Core; +using Umbraco.Core.Cache; +using Umbraco.Core.Logging; using Umbraco.Core.ObjectResolution; using Umbraco.Core.Persistence.Mappers; using Umbraco.Core.Persistence.SqlSyntax; +using Umbraco.Core.Profiling; namespace Umbraco.Tests.TestHelpers { @@ -12,9 +16,13 @@ namespace Umbraco.Tests.TestHelpers [SetUp] public virtual void Initialize() { - SqlSyntaxContext.SqlSyntaxProvider = SqlCeSyntax.Provider; - PluginManager.Current = new PluginManager(false); + var logger = new ProfilingLogger(Mock.Of(), Mock.Of()); + SqlSyntaxContext.SqlSyntaxProvider = new SqlCeSyntaxProvider(); + PluginManager.Current = new PluginManager(new ActivatorServiceProvider(), new NullCacheProvider(), + logger, + false); MappingResolver.Current = new MappingResolver( + new ActivatorServiceProvider(), logger.Logger, () => PluginManager.Current.ResolveAssignedMapperTypes()); Resolution.Freeze(); diff --git a/src/Umbraco.Tests/TestHelpers/DisposableUmbracoTest.cs b/src/Umbraco.Tests/TestHelpers/DisposableUmbracoTest.cs index e6de8fb8f3..d261487449 100644 --- a/src/Umbraco.Tests/TestHelpers/DisposableUmbracoTest.cs +++ b/src/Umbraco.Tests/TestHelpers/DisposableUmbracoTest.cs @@ -31,8 +31,6 @@ namespace Umbraco.Tests.TestHelpers private void Init(ApplicationContext applicationContext, UmbracoContext umbracoContext) { - TestHelper.SetupLog4NetForTests(); - ApplicationContext = applicationContext; UmbracoContext = umbracoContext; diff --git a/src/Umbraco.Tests/TestHelpers/Stubs/TestControllerFactory.cs b/src/Umbraco.Tests/TestHelpers/Stubs/TestControllerFactory.cs index 6bd000aaf3..723f621356 100644 --- a/src/Umbraco.Tests/TestHelpers/Stubs/TestControllerFactory.cs +++ b/src/Umbraco.Tests/TestHelpers/Stubs/TestControllerFactory.cs @@ -5,6 +5,8 @@ using System.Web.Mvc; using System.Web.Routing; using System.Web.SessionState; using Umbraco.Core; +using Umbraco.Core.Logging; +using Umbraco.Web; namespace Umbraco.Tests.TestHelpers.Stubs { @@ -13,8 +15,16 @@ namespace Umbraco.Tests.TestHelpers.Stubs /// internal class TestControllerFactory : IControllerFactory { + private readonly UmbracoContext _umbracoContext; + private readonly ILogger _logger; - public IController CreateController(RequestContext requestContext, string controllerName) + public TestControllerFactory(UmbracoContext umbracoContext, ILogger logger) + { + _umbracoContext = umbracoContext; + _logger = logger; + } + + public IController CreateController(RequestContext requestContext, string controllerName) { var types = TypeFinder.FindClassesOfType(new[] { Assembly.GetExecutingAssembly() }); @@ -24,7 +34,20 @@ namespace Umbraco.Tests.TestHelpers.Stubs if (t == null) return null; - return Activator.CreateInstance(t) as IController; + var ctors = t.GetConstructors(); + if (ctors.Any(x => + { + var parameters = x.GetParameters(); + if (parameters.Length != 2) return false; + return parameters.First().ParameterType == typeof (ILogger) && parameters.Last().ParameterType == typeof (UmbracoContext); + })) + { + return Activator.CreateInstance(t, new object[]{_logger, _umbracoContext}) as IController; + } + else + { + return Activator.CreateInstance(t) as IController; + } } public System.Web.SessionState.SessionStateBehavior GetControllerSessionBehavior(RequestContext requestContext, string controllerName) diff --git a/src/Umbraco.Tests/TestHelpers/TestHelper.cs b/src/Umbraco.Tests/TestHelpers/TestHelper.cs index 0a69f5b2d6..7f881ba559 100644 --- a/src/Umbraco.Tests/TestHelpers/TestHelper.cs +++ b/src/Umbraco.Tests/TestHelpers/TestHelper.cs @@ -7,7 +7,6 @@ using System.Reflection; using SqlCE4Umbraco; using Umbraco.Core; using Umbraco.Core.IO; -using log4net.Config; using umbraco.DataLayer; using GlobalSettings = umbraco.GlobalSettings; @@ -72,12 +71,7 @@ namespace Umbraco.Tests.TestHelpers return relativePath.Replace("~/", CurrentAssemblyDirectory + "/"); } - public static void SetupLog4NetForTests() - { - XmlConfigurator.Configure(new FileInfo(MapPathForTest("~/unit-test-log4net.config"))); - } - - public static void InitializeContentDirectories() + public static void InitializeContentDirectories() { CreateDirectories(new[] { SystemDirectories.Masterpages, SystemDirectories.MvcViews, SystemDirectories.Media, SystemDirectories.AppPlugins }); } diff --git a/src/Umbraco.Tests/Umbraco.Tests.csproj b/src/Umbraco.Tests/Umbraco.Tests.csproj index c4096216ca..1408704b2d 100644 --- a/src/Umbraco.Tests/Umbraco.Tests.csproj +++ b/src/Umbraco.Tests/Umbraco.Tests.csproj @@ -168,7 +168,9 @@ - + + + @@ -282,6 +284,7 @@ + @@ -301,12 +304,12 @@ - - - - - - + + + + + + @@ -354,8 +357,6 @@ - - @@ -383,7 +384,6 @@ - @@ -493,7 +493,7 @@ - + diff --git a/src/Umbraco.Tests/XmlHelperTests.cs b/src/Umbraco.Tests/XmlHelperTests.cs index 8050130b51..217e079a5f 100644 --- a/src/Umbraco.Tests/XmlHelperTests.cs +++ b/src/Umbraco.Tests/XmlHelperTests.cs @@ -8,7 +8,6 @@ using System.Xml.XPath; using NUnit.Framework; using Umbraco.Core; using Umbraco.Core.Configuration; -using Umbraco.Tests.TestHelpers; using umbraco; namespace Umbraco.Tests @@ -19,7 +18,6 @@ namespace Umbraco.Tests [SetUp] public void Setup() { - TestHelper.SetupLog4NetForTests(); } [Ignore("This is a benchmark test so is ignored by default")] diff --git a/src/Umbraco.Tests/masterpages/site1/template2.master b/src/Umbraco.Tests/masterpages/site1/template2.master new file mode 100644 index 0000000000..f1a6da0d51 --- /dev/null +++ b/src/Umbraco.Tests/masterpages/site1/template2.master @@ -0,0 +1,5 @@ +<%@ Master Language="C#" MasterPageFile="~/umbraco/masterpages/default.master" AutoEventWireup="true" %> + + + + diff --git a/src/Umbraco.Web.UI.Client/src/common/directives/grid/grid.rte.directive.js b/src/Umbraco.Web.UI.Client/src/common/directives/grid/grid.rte.directive.js index fd617a497e..18cfa77acd 100644 --- a/src/Umbraco.Web.UI.Client/src/common/directives/grid/grid.rte.directive.js +++ b/src/Umbraco.Web.UI.Client/src/common/directives/grid/grid.rte.directive.js @@ -65,6 +65,9 @@ angular.module("umbraco.directives") r.inline = "span"; r.classes = rule.selector.substring(1); }else if (rule.selector[0] === "#") { + //Even though this will render in the style drop down, it will not actually be applied + // to the elements, don't think TinyMCE even supports this and it doesn't really make much sense + // since only one element can have one id. r.inline = "span"; r.attributes = { id: rule.selector.substring(1) }; }else { diff --git a/src/Umbraco.Web.UI.Client/src/common/mocks/umbraco.servervariables.js b/src/Umbraco.Web.UI.Client/src/common/mocks/umbraco.servervariables.js index 8049b452d3..a68606efa7 100644 --- a/src/Umbraco.Web.UI.Client/src/common/mocks/umbraco.servervariables.js +++ b/src/Umbraco.Web.UI.Client/src/common/mocks/umbraco.servervariables.js @@ -20,6 +20,7 @@ Umbraco.Sys.ServerVariables = { "entityApiBaseUrl": "/umbraco/UmbracoApi/Entity/", "dashboardApiBaseUrl": "/umbraco/UmbracoApi/Dashboard/", "updateCheckApiBaseUrl": "/umbraco/Api/UpdateCheck/", + "relationApiBaseUrl": "/umbraco/UmbracoApi/Relation/", "rteApiBaseUrl": "/umbraco/UmbracoApi/RichTextPreValue/" }, umbracoSettings: { diff --git a/src/Umbraco.Web.UI.Client/src/common/resources/relation.resource.js b/src/Umbraco.Web.UI.Client/src/common/resources/relation.resource.js new file mode 100644 index 0000000000..19bfded340 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/common/resources/relation.resource.js @@ -0,0 +1,65 @@ +/** + * @ngdoc service + * @name umbraco.resources.relationResource + * @description Handles loading of relation data + **/ +function relationResource($q, $http, umbRequestHelper) { + return { + + /** + * @ngdoc method + * @name umbraco.resources.relationResource#getByChildId + * @methodOf umbraco.resources.relationResource + * + * @description + * Retrieves the relation data for a given child ID + * + * @param {int} id of the child item + * @param {string} alias of the relation type + * @returns {Promise} resourcePromise object containing the relations array. + * + */ + getByChildId: function (id, alias) { + + return umbRequestHelper.resourcePromise( + $http.get( + umbRequestHelper.getApiUrl( + "relationApiBaseUrl", + "GetByChildId", + [{ childId: id, relationTypeAlias: alias }])), + "Failed to get relation by child ID " + id + " and type of " + alias); + }, + + /** + * @ngdoc method + * @name umbraco.resources.relationResource#deleteById + * @methodOf umbraco.resources.relationResource + * + * @description + * Deletes a relation item with a given id + * + * ##usage + *
+         * relationResource.deleteById(1234)
+         *    .then(function() {
+         *        alert('its gone!');
+         *    });
+         * 
+ * + * @param {Int} id id of relation item to delete + * @returns {Promise} resourcePromise object. + * + */ + deleteById: function (id) { + return umbRequestHelper.resourcePromise( + $http.post( + umbRequestHelper.getApiUrl( + "relationApiBaseUrl", + "DeleteById", + [{ id: id }])), + 'Failed to delete item ' + id); + } + }; +} + +angular.module('umbraco.resources').factory('relationResource', relationResource); \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/common/resources/stylesheet.resource.js b/src/Umbraco.Web.UI.Client/src/common/resources/stylesheet.resource.js index f5eab4e902..36f2b4c591 100644 --- a/src/Umbraco.Web.UI.Client/src/common/resources/stylesheet.resource.js +++ b/src/Umbraco.Web.UI.Client/src/common/resources/stylesheet.resource.js @@ -36,36 +36,7 @@ function stylesheetResource($q, $http, umbRequestHelper) { "stylesheetApiBaseUrl", "GetAll")), 'Failed to retrieve stylesheets '); - }, - - /** - * @ngdoc method - * @name umbraco.resources.stylesheetResource#getRules - * @methodOf umbraco.resources.stylesheetResource - * - * @description - * Returns all defined child rules for a stylesheet with a given ID - * - * ##usage - *
-         * stylesheetResource.getRules(2345)
-         *    .then(function(rules) {
-         *        alert('its here!');
-         *    });
-         * 
- * - * @returns {Promise} resourcePromise object containing the rules. - * - */ - getRules: function (id) { - return umbRequestHelper.resourcePromise( - $http.get( - umbRequestHelper.getApiUrl( - "stylesheetApiBaseUrl", - "GetRules", - [{ id: id }])), - 'Failed to retrieve stylesheets '); - }, + }, /** * @ngdoc method 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 718415831b..865dd8303f 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,4 +1,4 @@ - +
diff --git a/src/Umbraco.Web.UI.Client/src/views/content/content.restore.controller.js b/src/Umbraco.Web.UI.Client/src/views/content/content.restore.controller.js new file mode 100644 index 0000000000..53b7701098 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/views/content/content.restore.controller.js @@ -0,0 +1,72 @@ +angular.module("umbraco").controller("Umbraco.Editors.Content.RestoreController", + function ($scope, relationResource, contentResource, navigationService, appState, treeService) { + var dialogOptions = $scope.dialogOptions; + + var node = dialogOptions.currentNode; + + $scope.error = null; + $scope.success = false; + + relationResource.getByChildId(node.id, "relateParentDocumentOnDelete").then(function (data) { + + if (data.length == 0) { + $scope.success = false; + $scope.error = { + errorMsg: "Cannot automatically restore this item", + data: { + Message: "There is no 'restore' relation found for this node. Use the Move menu item to move it manually." + } + } + return; + } + + $scope.relation = data[0]; + + if ($scope.relation.parentId == -1) { + $scope.target = { id: -1, name: "Root" }; + + } else { + contentResource.getById($scope.relation.parentId).then(function (data) { + $scope.target = data; + + }, function (err) { + $scope.success = false; + $scope.error = err; + }); + } + + }, function (err) { + $scope.success = false; + $scope.error = err; + }); + + $scope.restore = function () { + // this code was copied from `content.move.controller.js` + contentResource.move({ parentId: $scope.target.id, id: node.id }) + .then(function (path) { + + $scope.success = true; + + //first we need to remove the node that launched the dialog + treeService.removeNode($scope.currentNode); + + //get the currently edited node (if any) + var activeNode = appState.getTreeState("selectedNode"); + + //we need to do a double sync here: first sync to the moved content - but don't activate the node, + //then sync to the currenlty edited content (note: this might not be the content that was moved!!) + + navigationService.syncTree({ tree: "content", path: path, forceReload: true, activate: false }).then(function (args) { + if (activeNode) { + var activeNodePath = treeService.getPath(activeNode).join(); + //sync to this node now - depending on what was copied this might already be synced but might not be + navigationService.syncTree({ tree: "content", path: activeNodePath, forceReload: false, activate: true }); + } + }); + + }, function (err) { + $scope.success = false; + $scope.error = err; + }); + }; + }); \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/views/content/restore.html b/src/Umbraco.Web.UI.Client/src/views/content/restore.html new file mode 100644 index 0000000000..c1901c4252 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/views/content/restore.html @@ -0,0 +1,26 @@ +
+
+ + +

+ Restore {{currentNode.name}} to under {{target.name}}? +

+ +
+

{{error.errorMsg}}

+

{{error.data.Message}}

+
+ +
+

{{currentNode.name}} was moved underneath {{target.name}}

+ +
+ +
+
+ + +
\ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/contentpicker/contentpicker.controller.js b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/contentpicker/contentpicker.controller.js index 9d755d7d3f..83c6c3e013 100644 --- a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/contentpicker/contentpicker.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/contentpicker/contentpicker.controller.js @@ -175,8 +175,11 @@ function contentPickerController($scope, dialogService, entityResource, editorSt return d.id == id; }); - entity.icon = iconHelper.convertFromLegacyIcon(entity.icon); - $scope.renderModel.push({ name: entity.name, id: entity.id, icon: entity.icon }); + if (entity) { + entity.icon = iconHelper.convertFromLegacyIcon(entity.icon); + $scope.renderModel.push({ name: entity.name, id: entity.id, icon: entity.icon }); + } + }); diff --git a/src/Umbraco.Web.UI/config/trees.Release.config b/src/Umbraco.Web.UI/config/trees.Release.config index 2124c72560..bb60356cd4 100644 --- a/src/Umbraco.Web.UI/config/trees.Release.config +++ b/src/Umbraco.Web.UI/config/trees.Release.config @@ -9,11 +9,11 @@ - + - + diff --git a/src/Umbraco.Web.UI/config/trees.config b/src/Umbraco.Web.UI/config/trees.config index 2124c72560..8a85f26788 100644 --- a/src/Umbraco.Web.UI/config/trees.config +++ b/src/Umbraco.Web.UI/config/trees.config @@ -9,11 +9,11 @@ - + - + @@ -37,5 +37,5 @@ + iconClosed="icon-folder" iconOpen="icon-folder" sortOrder="10" />--> \ No newline at end of file diff --git a/src/Umbraco.Web.UI/umbraco/config/lang/en.xml b/src/Umbraco.Web.UI/umbraco/config/lang/en.xml index e43af2752f..8acd5e3933 100644 --- a/src/Umbraco.Web.UI/umbraco/config/lang/en.xml +++ b/src/Umbraco.Web.UI/umbraco/config/lang/en.xml @@ -27,6 +27,7 @@ Unpublish Reload nodes Republish entire site + Restore Permissions Rollback Send To Publish 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 0d700fa50f..26df92a44b 100644 --- a/src/Umbraco.Web.UI/umbraco/config/lang/en_us.xml +++ b/src/Umbraco.Web.UI/umbraco/config/lang/en_us.xml @@ -27,6 +27,7 @@ Unpublish Reload nodes Republish entire site + Restore Permissions Rollback Send To Publish diff --git a/src/Umbraco.Web.UI/umbraco/settings/stylesheet/editstylesheet.aspx b/src/Umbraco.Web.UI/umbraco/settings/stylesheet/editstylesheet.aspx index f107edad96..55b243c94c 100644 --- a/src/Umbraco.Web.UI/umbraco/settings/stylesheet/editstylesheet.aspx +++ b/src/Umbraco.Web.UI/umbraco/settings/stylesheet/editstylesheet.aspx @@ -13,7 +13,7 @@ $(document).ready(function () { var editor = new Umbraco.Editors.EditStyleSheet({ nameTxtBox: $('#<%= NameTxt.ClientID %>'), - originalFileName: '<%= NameTxt.Text %>', + originalFileName: '<%= NameTxt.Text.Replace("\\", "\\\\") %>', cssId: '<%= Request.QueryString["id"] %>', saveButton: $("#<%= ((Control)SaveButton).ClientID %>"), editorSourceElement: $('#<%= editorSource.ClientID %>'), diff --git a/src/Umbraco.Web.UI/umbraco/settings/stylesheet/property/EditStyleSheetProperty.aspx b/src/Umbraco.Web.UI/umbraco/settings/stylesheet/property/EditStyleSheetProperty.aspx index c554ab88b9..96991df575 100644 --- a/src/Umbraco.Web.UI/umbraco/settings/stylesheet/property/EditStyleSheetProperty.aspx +++ b/src/Umbraco.Web.UI/umbraco/settings/stylesheet/property/EditStyleSheetProperty.aspx @@ -13,6 +13,7 @@ <%=umbraco.ui.Text("name", UmbracoUser)%>: +
<%=umbraco.ui.Text("stylesheet", "nameHelp", UmbracoUser)%> diff --git a/src/Umbraco.Web.UI/umbraco_client/Editors/EditStyleSheet.js b/src/Umbraco.Web.UI/umbraco_client/Editors/EditStyleSheet.js index b67e224d7b..7d0ab93bd8 100644 --- a/src/Umbraco.Web.UI/umbraco_client/Editors/EditStyleSheet.js +++ b/src/Umbraco.Web.UI/umbraco_client/Editors/EditStyleSheet.js @@ -37,14 +37,14 @@ codeVal = UmbEditor.GetCode(); } umbraco.presentation.webservices.codeEditorSave.SaveCss( - fileName, self._opts.originalFileName, codeVal, self._opts.cssId, - function(t) { self.submitSucces(t); }, + fileName, self._opts.originalFileName, codeVal, 0, + function (t) { self.submitSucces(t, fileName); }, function(t) { self.submitFailure(t); }); }, - submitSucces: function(t) { + submitSucces: function (t, fileName) { if (t != 'true') { top.UmbSpeechBubble.ShowMessage('error', unescape(this._opts.text.cssErrorHeader), unescape(this._opts.text.cssErrorText)); } @@ -53,7 +53,7 @@ } UmbClientMgr.mainTree().setActiveTreeType('stylesheets'); - UmbClientMgr.mainTree().syncTree("-1,init," + this._opts.cssId, true); + UmbClientMgr.mainTree().syncTree("-1,init," + fileName, true); //update the originalFileName prop this._opts.originalFileName = this._opts.nameTxtBox.val(); diff --git a/src/Umbraco.Web.UI/umbraco_client/Editors/EditTemplate.js b/src/Umbraco.Web.UI/umbraco_client/Editors/EditTemplate.js index 0a3bb45c5c..d9b1a28505 100644 --- a/src/Umbraco.Web.UI/umbraco_client/Editors/EditTemplate.js +++ b/src/Umbraco.Web.UI/umbraco_client/Editors/EditTemplate.js @@ -148,6 +148,9 @@ } path = args.path; } + if (args.contents) { + UmbEditor.SetCode(args.contents); + } top.UmbSpeechBubble.ShowMessage('save', header, msg); UmbClientMgr.mainTree().setActiveTreeType('templates'); diff --git a/src/Umbraco.Web.UI/umbraco_client/Editors/EditView.js b/src/Umbraco.Web.UI/umbraco_client/Editors/EditView.js index 17f151bd2c..554d0bafc8 100644 --- a/src/Umbraco.Web.UI/umbraco_client/Editors/EditView.js +++ b/src/Umbraco.Web.UI/umbraco_client/Editors/EditView.js @@ -155,6 +155,9 @@ } path = args.path; } + if (args.contents) { + UmbEditor.SetCode(args.contents); + } UmbClientMgr.mainTree().setActiveTreeType(this._opts.currentTreeType); diff --git a/src/Umbraco.Web/Cache/ContentTypeCacheRefresher.cs b/src/Umbraco.Web/Cache/ContentTypeCacheRefresher.cs index 3db1e30fa7..d07aa61f58 100644 --- a/src/Umbraco.Web/Cache/ContentTypeCacheRefresher.cs +++ b/src/Umbraco.Web/Cache/ContentTypeCacheRefresher.cs @@ -9,7 +9,7 @@ using Umbraco.Core.Models; using Umbraco.Core.Models.EntityBase; using Umbraco.Core.Models.PublishedContent; using Umbraco.Core.Models.Rdbms; -using Umbraco.Core.Persistence.Caching; + using Umbraco.Web.PublishedCache; using Umbraco.Web.PublishedCache.XmlPublishedCache; @@ -126,8 +126,8 @@ namespace Umbraco.Web.Cache public override void RefreshAll() { - RuntimeCacheProvider.Current.Clear(typeof(IContent)); - RuntimeCacheProvider.Current.Clear(typeof(IContentType)); + ApplicationContext.Current.ApplicationCache.RuntimeCache.ClearCacheObjectTypes(); + ApplicationContext.Current.ApplicationCache.RuntimeCache.ClearCacheObjectTypes(); //all property type cache ApplicationContext.Current.ApplicationCache.RuntimeCache.ClearCacheByKeySearch(CacheKeys.PropertyTypeCacheKey); @@ -177,7 +177,6 @@ namespace Umbraco.Web.Cache /// -- CacheKeys.ContentTypePropertiesCacheKey + contentType.Id /// - ContentType.RemoveFromDataTypeCache (clears static object/dictionary cache) /// - InMemoryCacheProvider.Current.Clear(); - /// - RuntimeCacheProvider.Current.Clear(); /// - RoutesCache.Clear(); /// private static void ClearContentTypeCache(JsonPayload[] payloads) @@ -212,18 +211,18 @@ namespace Umbraco.Web.Cache { if (payloads.Any(x => x.Type == typeof (IContentType).Name)) { - RuntimeCacheProvider.Current.Clear(typeof(IContent)); - RuntimeCacheProvider.Current.Clear(typeof(IContentType)); + ApplicationContext.Current.ApplicationCache.RuntimeCache.ClearCacheObjectTypes(); + ApplicationContext.Current.ApplicationCache.RuntimeCache.ClearCacheObjectTypes(); } if (payloads.Any(x => x.Type == typeof(IMediaType).Name)) { - RuntimeCacheProvider.Current.Clear(typeof(IMedia)); - RuntimeCacheProvider.Current.Clear(typeof(IMediaType)); + ApplicationContext.Current.ApplicationCache.RuntimeCache.ClearCacheObjectTypes(); + ApplicationContext.Current.ApplicationCache.RuntimeCache.ClearCacheObjectTypes(); } if (payloads.Any(x => x.Type == typeof(IMemberType).Name)) { - RuntimeCacheProvider.Current.Clear(typeof(IMember)); - RuntimeCacheProvider.Current.Clear(typeof(IMemberType)); + ApplicationContext.Current.ApplicationCache.RuntimeCache.ClearCacheObjectTypes(); + ApplicationContext.Current.ApplicationCache.RuntimeCache.ClearCacheObjectTypes(); } diff --git a/src/Umbraco.Web/Cache/DataTypeCacheRefresher.cs b/src/Umbraco.Web/Cache/DataTypeCacheRefresher.cs index af16301a6f..52ea71769f 100644 --- a/src/Umbraco.Web/Cache/DataTypeCacheRefresher.cs +++ b/src/Umbraco.Web/Cache/DataTypeCacheRefresher.cs @@ -5,7 +5,7 @@ using Umbraco.Core.Cache; using System.Linq; using Umbraco.Core.Models; using Umbraco.Core.Models.PublishedContent; -using Umbraco.Core.Persistence.Caching; + namespace Umbraco.Web.Cache { @@ -92,12 +92,13 @@ namespace Umbraco.Web.Cache //we need to clear the ContentType runtime cache since that is what caches the // db data type to store the value against and anytime a datatype changes, this also might change // we basically need to clear all sorts of runtime caches here because so many things depend upon a data type - RuntimeCacheProvider.Current.Clear(typeof(IContent)); - RuntimeCacheProvider.Current.Clear(typeof (IContentType)); - RuntimeCacheProvider.Current.Clear(typeof(IMedia)); - RuntimeCacheProvider.Current.Clear(typeof(IMediaType)); - RuntimeCacheProvider.Current.Clear(typeof(IMember)); - RuntimeCacheProvider.Current.Clear(typeof(IMemberType)); + + ApplicationContext.Current.ApplicationCache.RuntimeCache.ClearCacheObjectTypes(); + ApplicationContext.Current.ApplicationCache.RuntimeCache.ClearCacheObjectTypes(); + ApplicationContext.Current.ApplicationCache.RuntimeCache.ClearCacheObjectTypes(); + ApplicationContext.Current.ApplicationCache.RuntimeCache.ClearCacheObjectTypes(); + ApplicationContext.Current.ApplicationCache.RuntimeCache.ClearCacheObjectTypes(); + ApplicationContext.Current.ApplicationCache.RuntimeCache.ClearCacheObjectTypes(); payloads.ForEach(payload => { diff --git a/src/Umbraco.Web/Cache/DictionaryCacheRefresher.cs b/src/Umbraco.Web/Cache/DictionaryCacheRefresher.cs index 8ee199c6fa..8209d247a2 100644 --- a/src/Umbraco.Web/Cache/DictionaryCacheRefresher.cs +++ b/src/Umbraco.Web/Cache/DictionaryCacheRefresher.cs @@ -1,7 +1,8 @@ using System; +using Umbraco.Core; using Umbraco.Core.Cache; using Umbraco.Core.Models; -using Umbraco.Core.Persistence.Caching; + namespace Umbraco.Web.Cache { @@ -27,19 +28,13 @@ namespace Umbraco.Web.Cache public override void Refresh(int id) { - RuntimeCacheProvider.Current.Clear(typeof(IDictionaryItem)); - global::umbraco.cms.businesslogic.Dictionary.ClearCache(); - //when a dictionary item is updated we must also clear the text cache! - global::umbraco.cms.businesslogic.language.Item.ClearCache(); + ApplicationContext.Current.ApplicationCache.RuntimeCache.ClearCacheObjectTypes(); base.Refresh(id); } public override void Remove(int id) { - RuntimeCacheProvider.Current.Clear(typeof(IDictionaryItem)); - global::umbraco.cms.businesslogic.Dictionary.ClearCache(); - //when a dictionary item is removed we must also clear the text cache! - global::umbraco.cms.businesslogic.language.Item.ClearCache(); + ApplicationContext.Current.ApplicationCache.RuntimeCache.ClearCacheObjectTypes(); base.Remove(id); } } diff --git a/src/Umbraco.Web/Cache/LanguageCacheRefresher.cs b/src/Umbraco.Web/Cache/LanguageCacheRefresher.cs index 1dbd5a84a6..019be66b15 100644 --- a/src/Umbraco.Web/Cache/LanguageCacheRefresher.cs +++ b/src/Umbraco.Web/Cache/LanguageCacheRefresher.cs @@ -2,7 +2,7 @@ using Umbraco.Core; using Umbraco.Core.Cache; using Umbraco.Core.Models; -using Umbraco.Core.Persistence.Caching; + namespace Umbraco.Web.Cache { @@ -28,17 +28,13 @@ namespace Umbraco.Web.Cache public override void Refresh(int id) { - RuntimeCacheProvider.Current.Clear(typeof(ILanguage)); - ApplicationContext.Current.ApplicationCache.ClearCacheItem(CacheKeys.LanguageCacheKey); + ApplicationContext.Current.ApplicationCache.RuntimeCache.ClearCacheObjectTypes(); base.Refresh(id); } public override void Remove(int id) { - RuntimeCacheProvider.Current.Clear(typeof(ILanguage)); - ApplicationContext.Current.ApplicationCache.ClearCacheItem(CacheKeys.LanguageCacheKey); - //when a language is removed we must also clear the text cache! - global::umbraco.cms.businesslogic.language.Item.ClearCache(); + ApplicationContext.Current.ApplicationCache.RuntimeCache.ClearCacheObjectTypes(); base.Remove(id); } } diff --git a/src/Umbraco.Web/Cache/MacroCacheRefresher.cs b/src/Umbraco.Web/Cache/MacroCacheRefresher.cs index 19f56997ac..a06501032f 100644 --- a/src/Umbraco.Web/Cache/MacroCacheRefresher.cs +++ b/src/Umbraco.Web/Cache/MacroCacheRefresher.cs @@ -4,7 +4,8 @@ using Umbraco.Core; using Umbraco.Core.Cache; using Umbraco.Core.Models; using umbraco; -using Umbraco.Core.Persistence.Caching; + +using Umbraco.Core.Persistence.Repositories; using umbraco.interfaces; using System.Linq; using Macro = umbraco.cms.businesslogic.macro.Macro; @@ -170,12 +171,12 @@ namespace Umbraco.Web.Cache public override void RefreshAll() { - ApplicationContext.Current.ApplicationCache.ClearCacheObjectTypes(); + ApplicationContext.Current.ApplicationCache.RuntimeCache.ClearCacheObjectTypes(); GetAllMacroCacheKeys().ForEach( prefix => - ApplicationContext.Current.ApplicationCache.ClearCacheByKeySearch(prefix)); + ApplicationContext.Current.ApplicationCache.RuntimeCache.ClearCacheByKeySearch(prefix)); - RuntimeCacheProvider.Current.Clear(typeof (IMacro)); + ApplicationContext.Current.ApplicationCache.RuntimeCache.ClearCacheObjectTypes(); base.RefreshAll(); } @@ -188,9 +189,9 @@ namespace Umbraco.Web.Cache { GetCacheKeysForAlias(payload.Alias).ForEach( alias => - ApplicationContext.Current.ApplicationCache.ClearCacheByKeySearch(alias)); + ApplicationContext.Current.ApplicationCache.RuntimeCache.ClearCacheByKeySearch(alias)); - RuntimeCacheProvider.Current.Delete(typeof(IMacro), payload.Id); + ApplicationContext.Current.ApplicationCache.RuntimeCache.ClearCacheItem(RepositoryBase.GetCacheIdKey(payload.Id)); }); base.Refresh(jsonPayload); diff --git a/src/Umbraco.Web/Cache/MediaCacheRefresher.cs b/src/Umbraco.Web/Cache/MediaCacheRefresher.cs index bd12261b44..fd323c4bd1 100644 --- a/src/Umbraco.Web/Cache/MediaCacheRefresher.cs +++ b/src/Umbraco.Web/Cache/MediaCacheRefresher.cs @@ -7,7 +7,8 @@ using Umbraco.Core.Cache; using Umbraco.Core.Events; using Umbraco.Core.IO; using Umbraco.Core.Models; -using Umbraco.Core.Persistence.Caching; + +using Umbraco.Core.Persistence.Repositories; using umbraco.interfaces; using System.Linq; @@ -160,7 +161,7 @@ namespace Umbraco.Web.Cache //if there's no path, then just use id (this will occur on permanent deletion like emptying recycle bin) if (payload.Path.IsNullOrWhiteSpace()) { - ApplicationContext.Current.ApplicationCache.ClearCacheByKeySearch( + ApplicationContext.Current.ApplicationCache.RuntimeCache.ClearCacheByKeySearch( string.Format("{0}_{1}", CacheKeys.MediaCacheKey, payload.Id)); } else @@ -170,15 +171,16 @@ namespace Umbraco.Web.Cache int idPartAsInt; if (int.TryParse(idPart, out idPartAsInt)) { - RuntimeCacheProvider.Current.Delete(typeof(IMedia), idPartAsInt); + ApplicationContext.Current.ApplicationCache.RuntimeCache.ClearCacheItem( + RepositoryBase.GetCacheIdKey(idPartAsInt)); } - ApplicationContext.Current.ApplicationCache.ClearCacheByKeySearch( + ApplicationContext.Current.ApplicationCache.RuntimeCache.ClearCacheByKeySearch( string.Format("{0}_{1}_True", CacheKeys.MediaCacheKey, idPart)); // Also clear calls that only query this specific item! if (idPart == payload.Id.ToString(CultureInfo.InvariantCulture)) - ApplicationContext.Current.ApplicationCache.ClearCacheByKeySearch( + ApplicationContext.Current.ApplicationCache.RuntimeCache.ClearCacheByKeySearch( string.Format("{0}_{1}", CacheKeys.MediaCacheKey, payload.Id)); } diff --git a/src/Umbraco.Web/Cache/MemberCacheRefresher.cs b/src/Umbraco.Web/Cache/MemberCacheRefresher.cs index 97afd092a7..b57b3b343b 100644 --- a/src/Umbraco.Web/Cache/MemberCacheRefresher.cs +++ b/src/Umbraco.Web/Cache/MemberCacheRefresher.cs @@ -2,8 +2,10 @@ using Umbraco.Core; using Umbraco.Core.Cache; using Umbraco.Core.Models; -using Umbraco.Core.Persistence.Caching; +using Umbraco.Core.Models.Membership; + using umbraco.cms.businesslogic.member; +using Umbraco.Core.Persistence.Repositories; using umbraco.interfaces; namespace Umbraco.Web.Cache @@ -60,12 +62,12 @@ namespace Umbraco.Web.Cache { ApplicationContext.Current.ApplicationCache.ClearPartialViewCache(); - ApplicationContext.Current.ApplicationCache. + ApplicationContext.Current.ApplicationCache.RuntimeCache. ClearCacheByKeySearch(string.Format("{0}_{1}", CacheKeys.MemberLibraryCacheKey, id)); - ApplicationContext.Current.ApplicationCache. + ApplicationContext.Current.ApplicationCache.RuntimeCache. ClearCacheByKeySearch(string.Format("{0}{1}", CacheKeys.MemberBusinessLogicCacheKey, id)); - RuntimeCacheProvider.Current.Delete(typeof(IMember), id); + ApplicationContext.Current.ApplicationCache.RuntimeCache.ClearCacheItem(RepositoryBase.GetCacheIdKey(id)); } } } \ No newline at end of file diff --git a/src/Umbraco.Web/Cache/MemberGroupCacheRefresher.cs b/src/Umbraco.Web/Cache/MemberGroupCacheRefresher.cs index df3b936207..e410ab560c 100644 --- a/src/Umbraco.Web/Cache/MemberGroupCacheRefresher.cs +++ b/src/Umbraco.Web/Cache/MemberGroupCacheRefresher.cs @@ -4,7 +4,8 @@ using System.Web.Script.Serialization; using Umbraco.Core; using Umbraco.Core.Cache; using Umbraco.Core.Models; -using Umbraco.Core.Persistence.Caching; + +using Umbraco.Core.Persistence.Repositories; namespace Umbraco.Web.Cache { @@ -109,7 +110,7 @@ namespace Umbraco.Web.Cache { ApplicationContext.Current.ApplicationCache.RuntimeCache .ClearCacheByKeySearch(string.Format("{0}.{1}", typeof(IMemberGroup).FullName, payload.Name)); - RuntimeCacheProvider.Current.Delete(typeof(IMemberGroup), payload.Id); + ApplicationContext.Current.ApplicationCache.RuntimeCache.ClearCacheItem(RepositoryBase.GetCacheIdKey(payload.Id)); } }); diff --git a/src/Umbraco.Web/Cache/TemplateCacheRefresher.cs b/src/Umbraco.Web/Cache/TemplateCacheRefresher.cs index 42026a7523..5ef1fbf468 100644 --- a/src/Umbraco.Web/Cache/TemplateCacheRefresher.cs +++ b/src/Umbraco.Web/Cache/TemplateCacheRefresher.cs @@ -2,7 +2,7 @@ using Umbraco.Core; using Umbraco.Core.Cache; using Umbraco.Core.Models; -using Umbraco.Core.Persistence.Caching; + using umbraco; using umbraco.interfaces; @@ -52,15 +52,15 @@ namespace Umbraco.Web.Cache private void RemoveFromCache(int id) { - ApplicationContext.Current.ApplicationCache.ClearCacheItem( + ApplicationContext.Current.ApplicationCache.RuntimeCache.ClearCacheItem( string.Format("{0}{1}", CacheKeys.TemplateFrontEndCacheKey, id)); - ApplicationContext.Current.ApplicationCache.ClearCacheItem( + ApplicationContext.Current.ApplicationCache.RuntimeCache.ClearCacheItem( string.Format("{0}{1}", CacheKeys.TemplateBusinessLogicCacheKey, id)); //need to clear the runtime cache for template instances //NOTE: This is temp until we implement the correct ApplicationCache and then we can remove the RuntimeCache, etc... - RuntimeCacheProvider.Current.Clear(typeof(ITemplate)); + ApplicationContext.Current.ApplicationCache.RuntimeCache.ClearCacheObjectTypes(); } } diff --git a/src/Umbraco.Web/Cache/UnpublishedPageCacheRefresher.cs b/src/Umbraco.Web/Cache/UnpublishedPageCacheRefresher.cs index cce6f3f878..1cf661a78f 100644 --- a/src/Umbraco.Web/Cache/UnpublishedPageCacheRefresher.cs +++ b/src/Umbraco.Web/Cache/UnpublishedPageCacheRefresher.cs @@ -1,10 +1,12 @@ using System; using System.Web.Script.Serialization; using umbraco; +using Umbraco.Core; using Umbraco.Core.Cache; using Umbraco.Core.Models; using System.Linq; -using Umbraco.Core.Persistence.Caching; + +using Umbraco.Core.Persistence.Repositories; using Umbraco.Core.Sync; namespace Umbraco.Web.Cache @@ -75,34 +77,34 @@ namespace Umbraco.Web.Cache public override void RefreshAll() { - RuntimeCacheProvider.Current.Clear(typeof(IContent)); + ApplicationContext.Current.ApplicationCache.RuntimeCache.ClearCacheObjectTypes(); base.RefreshAll(); } public override void Refresh(int id) { - RuntimeCacheProvider.Current.Delete(typeof(IContent), id); + ApplicationContext.Current.ApplicationCache.RuntimeCache.ClearCacheItem(RepositoryBase.GetCacheIdKey(id)); content.Instance.UpdateSortOrder(id); base.Refresh(id); } public override void Remove(int id) { - RuntimeCacheProvider.Current.Delete(typeof(IContent), id); + ApplicationContext.Current.ApplicationCache.RuntimeCache.ClearCacheItem(RepositoryBase.GetCacheIdKey(id)); base.Remove(id); } public override void Refresh(IContent instance) { - RuntimeCacheProvider.Current.Delete(typeof(IContent), instance.Id); + ApplicationContext.Current.ApplicationCache.RuntimeCache.ClearCacheItem(RepositoryBase.GetCacheIdKey(instance.Id)); content.Instance.UpdateSortOrder(instance); base.Refresh(instance); } public override void Remove(IContent instance) { - RuntimeCacheProvider.Current.Delete(typeof(IContent), instance.Id); + ApplicationContext.Current.ApplicationCache.RuntimeCache.ClearCacheItem(RepositoryBase.GetCacheIdKey(instance.Id)); base.Remove(instance); } @@ -114,7 +116,7 @@ namespace Umbraco.Web.Cache { foreach (var payload in DeserializeFromJsonPayload(jsonPayload)) { - RuntimeCacheProvider.Current.Delete(typeof(IContent), payload.Id); + ApplicationContext.Current.ApplicationCache.RuntimeCache.ClearCacheItem(RepositoryBase.GetCacheIdKey(payload.Id)); content.Instance.UpdateSortOrder(payload.Id); } diff --git a/src/Umbraco.Web/Cache/UserCacheRefresher.cs b/src/Umbraco.Web/Cache/UserCacheRefresher.cs index deb36ae894..95a7fdac49 100644 --- a/src/Umbraco.Web/Cache/UserCacheRefresher.cs +++ b/src/Umbraco.Web/Cache/UserCacheRefresher.cs @@ -2,7 +2,8 @@ using Umbraco.Core; using Umbraco.Core.Cache; using Umbraco.Core.Models.Membership; -using Umbraco.Core.Persistence.Caching; + +using Umbraco.Core.Persistence.Repositories; using umbraco.interfaces; namespace Umbraco.Web.Cache @@ -29,9 +30,9 @@ namespace Umbraco.Web.Cache public override void RefreshAll() { - RuntimeCacheProvider.Current.Clear(typeof(IUser)); - ApplicationContext.Current.ApplicationCache.ClearCacheByKeySearch(CacheKeys.UserPermissionsCacheKey); - ApplicationContext.Current.ApplicationCache.ClearCacheByKeySearch(CacheKeys.UserContextCacheKey); + ApplicationContext.Current.ApplicationCache.RuntimeCache.ClearCacheObjectTypes(); + ApplicationContext.Current.ApplicationCache.RuntimeCache.ClearCacheByKeySearch(CacheKeys.UserPermissionsCacheKey); + ApplicationContext.Current.ApplicationCache.RuntimeCache.ClearCacheByKeySearch(CacheKeys.UserContextCacheKey); base.RefreshAll(); } @@ -43,13 +44,13 @@ namespace Umbraco.Web.Cache public override void Remove(int id) { - RuntimeCacheProvider.Current.Delete(typeof (IUser), id); + ApplicationContext.Current.ApplicationCache.RuntimeCache.ClearCacheItem(RepositoryBase.GetCacheIdKey(id)); - ApplicationContext.Current.ApplicationCache.ClearCacheItem(string.Format("{0}{1}", CacheKeys.UserPermissionsCacheKey, id)); + ApplicationContext.Current.ApplicationCache.RuntimeCache.ClearCacheItem(string.Format("{0}{1}", CacheKeys.UserPermissionsCacheKey, id)); //we need to clear all UserContextCacheKey since we cannot invalidate based on ID since the cache is done so based //on the current contextId stored in the database - ApplicationContext.Current.ApplicationCache.ClearCacheByKeySearch(CacheKeys.UserContextCacheKey); + ApplicationContext.Current.ApplicationCache.RuntimeCache.ClearCacheByKeySearch(CacheKeys.UserContextCacheKey); base.Remove(id); } diff --git a/src/Umbraco.Web/Cache/UserTypeCacheRefresher.cs b/src/Umbraco.Web/Cache/UserTypeCacheRefresher.cs index 1a726da815..2beaa4347d 100644 --- a/src/Umbraco.Web/Cache/UserTypeCacheRefresher.cs +++ b/src/Umbraco.Web/Cache/UserTypeCacheRefresher.cs @@ -2,7 +2,8 @@ using Umbraco.Core; using Umbraco.Core.Cache; using Umbraco.Core.Models.Membership; -using Umbraco.Core.Persistence.Caching; + +using Umbraco.Core.Persistence.Repositories; namespace Umbraco.Web.Cache { @@ -28,19 +29,19 @@ namespace Umbraco.Web.Cache public override void RefreshAll() { - RuntimeCacheProvider.Current.Clear(typeof (IUserType)); + ApplicationContext.Current.ApplicationCache.RuntimeCache.ClearCacheObjectTypes(); base.RefreshAll(); } public override void Refresh(int id) { - RuntimeCacheProvider.Current.Delete(typeof(IUserType), id); + ApplicationContext.Current.ApplicationCache.RuntimeCache.ClearCacheItem(RepositoryBase.GetCacheIdKey(id)); base.Refresh(id); } public override void Remove(int id) { - RuntimeCacheProvider.Current.Delete(typeof(IUserType), id); + ApplicationContext.Current.ApplicationCache.RuntimeCache.ClearCacheItem(RepositoryBase.GetCacheIdKey(id)); base.Remove(id); } diff --git a/src/Umbraco.Web/Editors/BackOfficeController.cs b/src/Umbraco.Web/Editors/BackOfficeController.cs index 0cdebea26d..eccc2bd815 100644 --- a/src/Umbraco.Web/Editors/BackOfficeController.cs +++ b/src/Umbraco.Web/Editors/BackOfficeController.cs @@ -212,6 +212,10 @@ namespace Umbraco.Web.Editors "packageInstallApiBaseUrl", Url.GetUmbracoApiServiceBaseUrl( controller => controller.Fetch(string.Empty)) }, + { + "relationApiBaseUrl", Url.GetUmbracoApiServiceBaseUrl( + controller => controller.GetById(0)) + }, { "rteApiBaseUrl", Url.GetUmbracoApiServiceBaseUrl( controller => controller.GetConfiguration()) diff --git a/src/Umbraco.Web/Editors/PackageInstallController.cs b/src/Umbraco.Web/Editors/PackageInstallController.cs index c96a078fe0..0b1c1a56dd 100644 --- a/src/Umbraco.Web/Editors/PackageInstallController.cs +++ b/src/Umbraco.Web/Editors/PackageInstallController.cs @@ -87,7 +87,7 @@ namespace Umbraco.Web.Editors ins.LoadConfig(IOHelper.MapPath(model.TemporaryDirectoryPath)); ins.InstallCleanUp(model.Id, IOHelper.MapPath(model.TemporaryDirectoryPath)); - var clientDependencyConfig = new Umbraco.Core.Configuration.ClientDependencyConfiguration(); + var clientDependencyConfig = new Umbraco.Core.Configuration.ClientDependencyConfiguration(ApplicationContext.ProfilingLogger.Logger); var clientDependencyUpdated = clientDependencyConfig.IncreaseVersionNumber(); //clear the tree cache - we'll do this here even though the browser will reload, but just in case it doesn't can't hurt. diff --git a/src/Umbraco.Web/Editors/RelationController.cs b/src/Umbraco.Web/Editors/RelationController.cs new file mode 100644 index 0000000000..099d5b5c13 --- /dev/null +++ b/src/Umbraco.Web/Editors/RelationController.cs @@ -0,0 +1,71 @@ +using System.Collections.Generic; +using System.Linq; +using System.Net; +using System.Net.Http; +using System.Web.Http; +using AutoMapper; +using Umbraco.Core; +using Umbraco.Core.Models; +using Umbraco.Web.Mvc; +using Umbraco.Web.WebApi.Filters; +using Constants = Umbraco.Core.Constants; +using Relation = Umbraco.Web.Models.ContentEditing.Relation; + +namespace Umbraco.Web.Editors +{ + [PluginController("UmbracoApi")] + [UmbracoApplicationAuthorizeAttribute(Constants.Applications.Content)] + public class RelationController : UmbracoAuthorizedJsonController + { + public RelationController() + : this(UmbracoContext.Current) + { + } + + public RelationController(UmbracoContext umbracoContext) + : base(umbracoContext) + { + } + + public Relation GetById(int id) + { + return Mapper.Map(Services.RelationService.GetById(id)); + } + + //[EnsureUserPermissionForContent("childId")] + public IEnumerable GetByChildId(int childId, string relationTypeAlias = "") + { + var relations = Services.RelationService.GetByChildId(childId).ToArray(); + + if (relations.Any() == false) + { + return Enumerable.Empty(); + } + + if (string.IsNullOrWhiteSpace(relationTypeAlias) == false) + { + return + Mapper.Map, IEnumerable>( + relations.Where(x => x.RelationType.Alias.InvariantEquals(relationTypeAlias))); + } + + return Mapper.Map, IEnumerable>(relations); + } + + [HttpDelete] + [HttpPost] + public HttpResponseMessage DeleteById(int id) + { + var foundRelation = Services.RelationService.GetById(id); + + if (foundRelation == null) + { + return Request.CreateErrorResponse(HttpStatusCode.NotFound, "No relation found with the specified id"); + } + + Services.RelationService.Delete(foundRelation); + + return Request.CreateResponse(HttpStatusCode.OK); + } + } +} \ No newline at end of file diff --git a/src/Umbraco.Web/Editors/StylesheetController.cs b/src/Umbraco.Web/Editors/StylesheetController.cs index 85dd63c022..38318541a4 100644 --- a/src/Umbraco.Web/Editors/StylesheetController.cs +++ b/src/Umbraco.Web/Editors/StylesheetController.cs @@ -11,6 +11,7 @@ using System.Web.Http; using System.Web.Services.Description; using Newtonsoft.Json.Linq; using umbraco.cms.businesslogic.web; +using Umbraco.Core; using Umbraco.Core.IO; using Umbraco.Web.Models.ContentEditing; using Umbraco.Web.Mvc; @@ -27,32 +28,21 @@ namespace Umbraco.Web.Editors { public IEnumerable GetAll() { - return StyleSheet.GetAll() + return Services.FileService.GetStylesheets() .Select(x => new Stylesheet() { - Name = x.Text, - Id = x.Id, - Path = SystemDirectories.Css + "/" + x.Text + ".css" + Name = x.Alias, + Path = x.VirtualPath }); } - - public IEnumerable GetRules(int id) - { - var css = StyleSheet.GetStyleSheet(id, true, true); - if (css == null) - return Enumerable.Empty(); - - return css.Properties.Select(x => new StylesheetRule() { Id = x.Id, Name = x.Text, Selector = x.Alias }); - } public IEnumerable GetRulesByName(string name) { - var css = StyleSheet.GetByName(name); - + var css = Services.FileService.GetStylesheetByName(name.EnsureEndsWith(".css")); if (css == null) return Enumerable.Empty(); - return css.Properties.Select(x => new StylesheetRule() { Id = x.Id, Name = x.Text, Selector = x.Alias }); + return css.Properties.Select(x => new StylesheetRule() { Name = x.Name, Selector = x.Alias }); } } diff --git a/src/Umbraco.Web/Install/Controllers/InstallApiController.cs b/src/Umbraco.Web/Install/Controllers/InstallApiController.cs index ed29d49418..f4dbdf5dfd 100644 --- a/src/Umbraco.Web/Install/Controllers/InstallApiController.cs +++ b/src/Umbraco.Web/Install/Controllers/InstallApiController.cs @@ -254,7 +254,7 @@ namespace Umbraco.Web.Install.Controllers internal InstallSetupResult ExecuteStep(InstallSetupStep step, JToken instruction) { - using (DisposableTimer.TraceDuration("Executing installation step: " + step.Name, "Step completed")) + using (ApplicationContext.ProfilingLogger.TraceDuration("Executing installation step: " + step.Name, "Step completed")) { var model = instruction == null ? null : instruction.ToObject(step.StepType); var genericStepType = typeof(InstallSetupStep<>); diff --git a/src/Umbraco.Web/Install/InstallSteps/SetUmbracoVersionStep.cs b/src/Umbraco.Web/Install/InstallSteps/SetUmbracoVersionStep.cs index fc2fa33cc8..e4f18fdcab 100644 --- a/src/Umbraco.Web/Install/InstallSteps/SetUmbracoVersionStep.cs +++ b/src/Umbraco.Web/Install/InstallSteps/SetUmbracoVersionStep.cs @@ -37,7 +37,7 @@ namespace Umbraco.Web.Install.InstallSteps GlobalSettings.ConfigurationStatus = UmbracoVersion.Current.ToString(3); // Update ClientDependency version - var clientDependencyConfig = new ClientDependencyConfiguration(); + var clientDependencyConfig = new ClientDependencyConfiguration(_applicationContext.ProfilingLogger.Logger); var clientDependencyUpdated = clientDependencyConfig.IncreaseVersionNumber(); var security = new WebSecurity(_httpContext, _applicationContext); diff --git a/src/Umbraco.Web/Media/ImageUrlProviderResolver.cs b/src/Umbraco.Web/Media/ImageUrlProviderResolver.cs index d11036919b..c52d937d8f 100644 --- a/src/Umbraco.Web/Media/ImageUrlProviderResolver.cs +++ b/src/Umbraco.Web/Media/ImageUrlProviderResolver.cs @@ -1,6 +1,7 @@ using System; using System.Collections.Generic; using System.Linq; +using Umbraco.Core.Logging; using Umbraco.Core.Media; using Umbraco.Core.ObjectResolution; using Umbraco.Web.Media.ImageUrlProviders; @@ -9,12 +10,15 @@ namespace Umbraco.Web.Media { internal sealed class ImageUrlProviderResolver : ManyObjectsResolverBase { - internal ImageUrlProviderResolver(IEnumerable value) : base(value) { } + internal ImageUrlProviderResolver(IServiceProvider serviceProvider, ILogger logger, IEnumerable value) + : base(serviceProvider, logger, value) + { + } public IImageUrlProvider GetProvider(string provider) { - return string.IsNullOrEmpty(provider) ? - Values.First(v => v.Name.Equals(ImageUrlProvider.DefaultName, StringComparison.InvariantCultureIgnoreCase)) : + return string.IsNullOrEmpty(provider) ? + Values.First(v => v.Name.Equals(ImageUrlProvider.DefaultName, StringComparison.InvariantCultureIgnoreCase)) : Values.First(v => v.Name.Equals(provider, StringComparison.InvariantCultureIgnoreCase)); } } diff --git a/src/Umbraco.Web/Media/ThumbnailProviders/ThumbnailProvidersResolver.cs b/src/Umbraco.Web/Media/ThumbnailProviders/ThumbnailProvidersResolver.cs index 10e019111b..a27bbe7f8e 100644 --- a/src/Umbraco.Web/Media/ThumbnailProviders/ThumbnailProvidersResolver.cs +++ b/src/Umbraco.Web/Media/ThumbnailProviders/ThumbnailProvidersResolver.cs @@ -4,6 +4,7 @@ using System.Linq; using System.Text; using System.Web; using Umbraco.Core; +using Umbraco.Core.Logging; using Umbraco.Core.Media; using Umbraco.Core.ObjectResolution; using umbraco.BusinessLogic; @@ -13,14 +14,14 @@ namespace Umbraco.Web.Media.ThumbnailProviders { internal sealed class ThumbnailProvidersResolver : ManyObjectsResolverBase { - - - /// - /// Constructor - /// - /// - internal ThumbnailProvidersResolver(IEnumerable providers) - : base(providers) + /// + /// Constructor + /// + /// + /// + /// + internal ThumbnailProvidersResolver(IServiceProvider serviceProvider, ILogger logger, IEnumerable providers) + : base(serviceProvider, logger, providers) { } diff --git a/src/Umbraco.Web/Models/ContentEditing/Relation.cs b/src/Umbraco.Web/Models/ContentEditing/Relation.cs new file mode 100644 index 0000000000..b166c67f55 --- /dev/null +++ b/src/Umbraco.Web/Models/ContentEditing/Relation.cs @@ -0,0 +1,43 @@ +using System.Collections.Generic; +using System.Linq; +using System.Runtime.Serialization; +using System.Text; +using System.Threading.Tasks; + +namespace Umbraco.Web.Models.ContentEditing +{ + [DataContract(Name = "relation", Namespace = "")] + public class Relation + { + + public Relation() + { + RelationType = new RelationType(); + } + + /// + /// Gets or sets the Parent Id of the Relation (Source) + /// + [DataMember(Name = "parentId")] + public int ParentId { get; set; } + + /// + /// Gets or sets the Child Id of the Relation (Destination) + /// + [DataMember(Name = "childId")] + public int ChildId { get; set; } + + /// + /// Gets or sets the for the Relation + /// + [DataMember(Name = "relationType", IsRequired = true)] + public RelationType RelationType { get; set; } + + /// + /// Gets or sets a comment for the Relation + /// + [DataMember(Name = "comment")] + public string Comment { get; set; } + + } +} diff --git a/src/Umbraco.Web/Models/ContentEditing/RelationType.cs b/src/Umbraco.Web/Models/ContentEditing/RelationType.cs new file mode 100644 index 0000000000..8c29343319 --- /dev/null +++ b/src/Umbraco.Web/Models/ContentEditing/RelationType.cs @@ -0,0 +1,42 @@ +using System; +using System.Runtime.Serialization; + +namespace Umbraco.Web.Models.ContentEditing +{ + [DataContract(Name = "relationType", Namespace = "")] + public class RelationType + { + + /// + /// Gets or sets the Name of the RelationType + /// + [DataMember(Name = "name", IsRequired = true)] + public string Name { get; set; } + + /// + /// Gets or sets the Alias of the RelationType + /// + [DataMember(Name = "alias", IsRequired = true)] + public string Alias { get; set; } + + /// + /// Gets or sets a boolean indicating whether the RelationType is Bidirectional (true) or Parent to Child (false) + /// + [DataMember(Name = "isBidirectional", IsRequired = true)] + public bool IsBidirectional { get; set; } + + /// + /// Gets or sets the Parents object type id + /// + /// Corresponds to the NodeObjectType in the umbracoNode table + [DataMember(Name = "parentObjectType", IsRequired = true)] + public Guid ParentObjectType { get; set; } + + /// + /// Gets or sets the Childs object type id + /// + /// Corresponds to the NodeObjectType in the umbracoNode table + [DataMember(Name = "childObjectType", IsRequired = true)] + public Guid ChildObjectType { get; set; } + } +} \ No newline at end of file diff --git a/src/Umbraco.Web/Models/ContentEditing/StyleSheet.cs b/src/Umbraco.Web/Models/ContentEditing/StyleSheet.cs index 97387a7083..6162aebfd7 100644 --- a/src/Umbraco.Web/Models/ContentEditing/StyleSheet.cs +++ b/src/Umbraco.Web/Models/ContentEditing/StyleSheet.cs @@ -14,8 +14,5 @@ namespace Umbraco.Web.Models.ContentEditing [DataMember(Name = "path")] public string Path { get; set; } - - [DataMember(Name = "id")] - public int Id { get; set; } } } diff --git a/src/Umbraco.Web/Models/ContentEditing/StylesheetRule.cs b/src/Umbraco.Web/Models/ContentEditing/StylesheetRule.cs index 6d1cb38f65..c8ef582f82 100644 --- a/src/Umbraco.Web/Models/ContentEditing/StylesheetRule.cs +++ b/src/Umbraco.Web/Models/ContentEditing/StylesheetRule.cs @@ -16,7 +16,5 @@ namespace Umbraco.Web.Models.ContentEditing [DataMember(Name = "selector")] public string Selector { get; set; } - [DataMember(Name = "id")] - public int Id { get; set; } } } diff --git a/src/Umbraco.Web/Models/Mapping/RelationModelMapper.cs b/src/Umbraco.Web/Models/Mapping/RelationModelMapper.cs new file mode 100644 index 0000000000..bc133abf96 --- /dev/null +++ b/src/Umbraco.Web/Models/Mapping/RelationModelMapper.cs @@ -0,0 +1,21 @@ +using AutoMapper; +using Umbraco.Core; +using Umbraco.Core.Models; +using Umbraco.Core.Models.Mapping; +using Relation = Umbraco.Web.Models.ContentEditing.Relation; +using RelationType = Umbraco.Web.Models.ContentEditing.RelationType; + +namespace Umbraco.Web.Models.Mapping +{ + internal class RelationModelMapper : MapperConfiguration + { + public override void ConfigureMappings(IConfiguration config, ApplicationContext applicationContext) + { + //FROM IRelationType TO RelationType + config.CreateMap(); + + //FROM IRelation TO Relation + config.CreateMap(); + } + } +} \ 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 ae4f8d519c..1717ecb1b6 100644 --- a/src/Umbraco.Web/Models/Trees/MenuItem.cs +++ b/src/Umbraco.Web/Models/Trees/MenuItem.cs @@ -190,7 +190,7 @@ namespace Umbraco.Web.Models.Trees .OnFailure(() => LegacyTreeDataConverter.GetLegacyConfirmView(Action, currentSection), view => LaunchDialogView( view, - ui.GetText("defaultdialogs", "confirmdelete") + " '" + item.Name + "' ?")); + ui.GetText("defaultdialogs", "confirmdelete") + " '" + (item == null ? "" : item.Name) + "' ?")); } #endregion diff --git a/src/Umbraco.Web/Mvc/FilteredControllerFactoriesResolver.cs b/src/Umbraco.Web/Mvc/FilteredControllerFactoriesResolver.cs index e4fadf7c4b..140c7738fa 100644 --- a/src/Umbraco.Web/Mvc/FilteredControllerFactoriesResolver.cs +++ b/src/Umbraco.Web/Mvc/FilteredControllerFactoriesResolver.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using Umbraco.Core.Logging; using Umbraco.Core.ObjectResolution; namespace Umbraco.Web.Mvc @@ -9,12 +10,14 @@ namespace Umbraco.Web.Mvc /// public sealed class FilteredControllerFactoriesResolver : ManyObjectsResolverBase { - /// - /// Constructor - /// - /// - internal FilteredControllerFactoriesResolver(IEnumerable factories) - : base(factories) + /// + /// Constructor + /// + /// + /// + /// + internal FilteredControllerFactoriesResolver(IServiceProvider serviceProvider, ILogger logger, IEnumerable factories) + : base(serviceProvider, logger, factories) { } diff --git a/src/Umbraco.Web/Mvc/PluginController.cs b/src/Umbraco.Web/Mvc/PluginController.cs index 1814da09b2..66111875f5 100644 --- a/src/Umbraco.Web/Mvc/PluginController.cs +++ b/src/Umbraco.Web/Mvc/PluginController.cs @@ -2,94 +2,110 @@ using System; using System.Collections.Concurrent; using System.Web.Mvc; using Umbraco.Core; +using Umbraco.Core.Logging; using Umbraco.Core.Services; using Umbraco.Web.WebApi; namespace Umbraco.Web.Mvc { - /// - /// A base class for all plugin controllers to inherit from - /// - public abstract class PluginController : Controller - { - /// - /// stores the metadata about plugin controllers - /// - private static readonly ConcurrentDictionary MetadataStorage = new ConcurrentDictionary(); + /// + /// A base class for all plugin controllers to inherit from + /// + public abstract class PluginController : Controller + { + /// + /// stores the metadata about plugin controllers + /// + private static readonly ConcurrentDictionary MetadataStorage = new ConcurrentDictionary(); + /// + /// Default constructor + /// + /// + protected PluginController(UmbracoContext umbracoContext) + { + if (umbracoContext == null) throw new ArgumentNullException("umbracoContext"); + UmbracoContext = umbracoContext; + InstanceId = Guid.NewGuid(); + Umbraco = new UmbracoHelper(umbracoContext); + } - /// - /// Default constructor - /// - /// - protected PluginController(UmbracoContext umbracoContext) - { - if (umbracoContext == null) throw new ArgumentNullException("umbracoContext"); - UmbracoContext = umbracoContext; - InstanceId = Guid.NewGuid(); - Umbraco = new UmbracoHelper(umbracoContext); - } + /// + /// Useful for debugging + /// + internal Guid InstanceId { get; private set; } - /// - /// Useful for debugging - /// - internal Guid InstanceId { get; private set; } + /// + /// Returns an UmbracoHelper object + /// + public UmbracoHelper Umbraco { get; private set; } - /// - /// Returns an UmbracoHelper object - /// - public UmbracoHelper Umbraco { get; private set; } + /// + /// Returns an ILogger + /// + public ILogger Logger + { + get { return ProfilingLogger.Logger; } + } - /// - /// Returns the current UmbracoContext - /// - public UmbracoContext UmbracoContext { get; private set; } + /// + /// Returns a ProfilingLogger + /// + public ProfilingLogger ProfilingLogger + { + get { return UmbracoContext.Application.ProfilingLogger; } + } - /// - /// Returns the current ApplicationContext - /// - public ApplicationContext ApplicationContext - { - get { return UmbracoContext.Application; } - } + /// + /// Returns the current UmbracoContext + /// + public UmbracoContext UmbracoContext { get; private set; } - /// - /// Returns a ServiceContext - /// - public ServiceContext Services - { - get { return ApplicationContext.Services; } - } + /// + /// Returns the current ApplicationContext + /// + public ApplicationContext ApplicationContext + { + get { return UmbracoContext.Application; } + } - /// - /// Returns a DatabaseContext - /// - public DatabaseContext DatabaseContext - { - get { return ApplicationContext.DatabaseContext; } - } + /// + /// Returns a ServiceContext + /// + public ServiceContext Services + { + get { return ApplicationContext.Services; } + } - /// - /// Returns the metadata for this instance - /// - internal PluginControllerMetadata Metadata - { - get { return GetMetadata(this.GetType()); } - } + /// + /// Returns a DatabaseContext + /// + public DatabaseContext DatabaseContext + { + get { return ApplicationContext.DatabaseContext; } + } - /// - /// Returns the metadata for a PluginController - /// - /// - /// - internal static PluginControllerMetadata GetMetadata(Type type) - { - - return MetadataStorage.GetOrAdd(type, type1 => - { + /// + /// Returns the metadata for this instance + /// + internal PluginControllerMetadata Metadata + { + get { return GetMetadata(this.GetType()); } + } + + /// + /// Returns the metadata for a PluginController + /// + /// + /// + internal static PluginControllerMetadata GetMetadata(Type type) + { + + return MetadataStorage.GetOrAdd(type, type1 => + { var pluginAttribute = type.GetCustomAttribute(false); //check if any inherited class of this type contains the IsBackOffice attribute - var backOfficeAttribute = type.GetCustomAttribute(true); + var backOfficeAttribute = type.GetCustomAttribute(true); var meta = new PluginControllerMetadata() { @@ -103,8 +119,8 @@ namespace Umbraco.Web.Mvc MetadataStorage.TryAdd(type, meta); return meta; - }); + }); - } - } + } + } } \ No newline at end of file diff --git a/src/Umbraco.Web/Mvc/RenderMvcController.cs b/src/Umbraco.Web/Mvc/RenderMvcController.cs index 86bccbe224..da3a5d107f 100644 --- a/src/Umbraco.Web/Mvc/RenderMvcController.cs +++ b/src/Umbraco.Web/Mvc/RenderMvcController.cs @@ -20,6 +20,7 @@ namespace Umbraco.Web.Mvc { public RenderMvcController() + : base() { ActionInvoker = new RenderActionInvoker(); } diff --git a/src/Umbraco.Web/Mvc/SurfaceController.cs b/src/Umbraco.Web/Mvc/SurfaceController.cs index 1010db48df..5304821131 100644 --- a/src/Umbraco.Web/Mvc/SurfaceController.cs +++ b/src/Umbraco.Web/Mvc/SurfaceController.cs @@ -2,6 +2,7 @@ using System; using System.Collections.Concurrent; using System.Web.Mvc; using System.Web.Routing; +using Umbraco.Core.Logging; using Umbraco.Core.Models; using Umbraco.Core; using Umbraco.Web.Security; @@ -16,7 +17,6 @@ namespace Umbraco.Web.Mvc [MergeParentContextViewData] public abstract class SurfaceController : PluginController { - /// /// Default constructor /// @@ -95,7 +95,7 @@ namespace Umbraco.Web.Mvc /// protected UmbracoPageResult CurrentUmbracoPage() { - return new UmbracoPageResult(); + return new UmbracoPageResult(ApplicationContext.ProfilingLogger); } /// diff --git a/src/Umbraco.Web/Mvc/SurfaceControllerResolver.cs b/src/Umbraco.Web/Mvc/SurfaceControllerResolver.cs index c3e6b92375..69683261bc 100644 --- a/src/Umbraco.Web/Mvc/SurfaceControllerResolver.cs +++ b/src/Umbraco.Web/Mvc/SurfaceControllerResolver.cs @@ -8,8 +8,8 @@ namespace Umbraco.Web.Mvc { internal sealed class SurfaceControllerResolver : ManyObjectsResolverBase { - public SurfaceControllerResolver(IEnumerable surfaceControllers) - : base(surfaceControllers) + public SurfaceControllerResolver(IServiceProvider serviceProvider, ILogger logger, IEnumerable surfaceControllers) + : base(serviceProvider, logger, surfaceControllers) { } diff --git a/src/Umbraco.Web/Mvc/UmbracoController.cs b/src/Umbraco.Web/Mvc/UmbracoController.cs index d514b56aa6..413680522d 100644 --- a/src/Umbraco.Web/Mvc/UmbracoController.cs +++ b/src/Umbraco.Web/Mvc/UmbracoController.cs @@ -1,6 +1,7 @@ using System; using System.Web.Mvc; using Umbraco.Core; +using Umbraco.Core.Logging; using Umbraco.Core.Services; using Umbraco.Web.Security; @@ -24,6 +25,7 @@ namespace Umbraco.Web.Mvc } private UmbracoHelper _umbraco; + /// /// Returns an UmbracoHelper object /// @@ -32,6 +34,22 @@ namespace Umbraco.Web.Mvc get { return _umbraco ?? (_umbraco = new UmbracoHelper(UmbracoContext)); } } + /// + /// Returns an ILogger + /// + public ILogger Logger + { + get { return ProfilingLogger.Logger; } + } + + /// + /// Returns a ProfilingLogger + /// + public ProfilingLogger ProfilingLogger + { + get { return UmbracoContext.Application.ProfilingLogger; } + } + /// /// Returns the current UmbracoContext /// diff --git a/src/Umbraco.Web/Mvc/UmbracoPageResult.cs b/src/Umbraco.Web/Mvc/UmbracoPageResult.cs index ac981d1512..1c12e7e498 100644 --- a/src/Umbraco.Web/Mvc/UmbracoPageResult.cs +++ b/src/Umbraco.Web/Mvc/UmbracoPageResult.cs @@ -4,6 +4,8 @@ using System.Web; using System.Web.Mvc; using System.Web.Routing; using Umbraco.Core; +using Umbraco.Core.Logging; +using Umbraco.Core.Profiling; namespace Umbraco.Web.Mvc { @@ -12,7 +14,21 @@ namespace Umbraco.Web.Mvc /// public class UmbracoPageResult : ActionResult { - public override void ExecuteResult(ControllerContext context) + private readonly ProfilingLogger _profilingLogger; + + public UmbracoPageResult(ProfilingLogger profilingLogger) + { + _profilingLogger = profilingLogger; + } + + [Obsolete("Use the ctor specifying all depenendencies instead")] + public UmbracoPageResult() + : this(new ProfilingLogger(LoggerResolver.Current.Logger, ProfilerResolver.Current.Profiler)) + { + + } + + public override void ExecuteResult(ControllerContext context) { ResetRouteData(context.RouteData); @@ -52,9 +68,9 @@ namespace Umbraco.Web.Mvc /// /// Executes the controller action /// - private static void ExecuteControllerAction(ControllerContext context, IController controller) + private void ExecuteControllerAction(ControllerContext context, IController controller) { - using (DisposableTimer.TraceDuration("Executing Umbraco RouteDefinition controller", "Finished")) + using (_profilingLogger.TraceDuration("Executing Umbraco RouteDefinition controller", "Finished")) { controller.Execute(context.RequestContext); } @@ -75,7 +91,7 @@ namespace Umbraco.Web.Mvc /// private static void ValidateRouteData(RouteData routeData) { - if (!routeData.DataTokens.ContainsKey("umbraco-route-def")) + if (routeData.DataTokens.ContainsKey("umbraco-route-def") == false) { throw new InvalidOperationException("Can only use " + typeof(UmbracoPageResult).Name + " in the context of an Http POST when using a SurfaceController form"); diff --git a/src/Umbraco.Web/Routing/ContentFinderResolver.cs b/src/Umbraco.Web/Routing/ContentFinderResolver.cs index 78dcbda899..b069f86315 100644 --- a/src/Umbraco.Web/Routing/ContentFinderResolver.cs +++ b/src/Umbraco.Web/Routing/ContentFinderResolver.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using Umbraco.Core.Logging; using Umbraco.Core.ObjectResolution; namespace Umbraco.Web.Routing @@ -9,22 +10,26 @@ namespace Umbraco.Web.Routing /// public sealed class ContentFinderResolver : ManyObjectsResolverBase { - /// - /// Initializes a new instance of the class with an initial list of finder types. - /// - /// The list of finder types - /// The resolver is created by the WebBootManager and thus the constructor remains internal. - internal ContentFinderResolver(IEnumerable finders) - : base(finders) + /// + /// Initializes a new instance of the class with an initial list of finder types. + /// + /// + /// + /// The list of finder types + /// The resolver is created by the WebBootManager and thus the constructor remains internal. + internal ContentFinderResolver(IServiceProvider serviceProvider, ILogger logger, IEnumerable finders) + : base(serviceProvider, logger, finders) { } - /// - /// Initializes a new instance of the class with an initial list of finder types. - /// - /// The list of finder types - /// The resolver is created by the WebBootManager and thus the constructor remains internal. - internal ContentFinderResolver(params Type[] finders) - : base(finders) + /// + /// Initializes a new instance of the class with an initial list of finder types. + /// + /// + /// The list of finder types + /// + /// The resolver is created by the WebBootManager and thus the constructor remains internal. + internal ContentFinderResolver(IServiceProvider serviceProvider, ILogger logger, params Type[] finders) + : base(serviceProvider, logger, finders) { } /// diff --git a/src/Umbraco.Web/Routing/UrlProviderResolver.cs b/src/Umbraco.Web/Routing/UrlProviderResolver.cs index 0cd0346cd9..505e3ff52a 100644 --- a/src/Umbraco.Web/Routing/UrlProviderResolver.cs +++ b/src/Umbraco.Web/Routing/UrlProviderResolver.cs @@ -2,8 +2,8 @@ using System.Collections.Generic; using System.Linq; using System.Text; - -using Umbraco.Core.ObjectResolution; +using Umbraco.Core.Logging; +using Umbraco.Core.ObjectResolution; namespace Umbraco.Web.Routing { @@ -15,19 +15,23 @@ namespace Umbraco.Web.Routing /// /// Initializes a new instance of the class with an initial list of provider types. /// + /// /// The list of provider types. + /// /// The resolver is created by the WebBootManager and thus the constructor remains internal. - internal UrlProviderResolver(IEnumerable providerTypes) - : base(providerTypes) + internal UrlProviderResolver(IServiceProvider serviceProvider, ILogger logger, IEnumerable providerTypes) + : base(serviceProvider, logger, providerTypes) { } /// /// Initializes a new instance of the class with an initial list of provider types. /// + /// /// The list of provider types. + /// /// The resolver is created by the WebBootManager and thus the constructor remains internal. - internal UrlProviderResolver(params Type[] providerTypes) - : base(providerTypes) + internal UrlProviderResolver(IServiceProvider serviceProvider, ILogger logger, params Type[] providerTypes) + : base(serviceProvider, logger, providerTypes) { } /// diff --git a/src/Umbraco.Web/Standalone/ServiceContextManager.cs b/src/Umbraco.Web/Standalone/ServiceContextManager.cs index 561fadfc2c..32c0867429 100644 --- a/src/Umbraco.Web/Standalone/ServiceContextManager.cs +++ b/src/Umbraco.Web/Standalone/ServiceContextManager.cs @@ -2,25 +2,34 @@ using System.Diagnostics; using Umbraco.Core; using Umbraco.Core.Cache; +using Umbraco.Core.Configuration; +using Umbraco.Core.Logging; using Umbraco.Core.Persistence; using Umbraco.Core.Persistence.Mappers; +using Umbraco.Core.Persistence.SqlSyntax; using Umbraco.Core.Persistence.UnitOfWork; using Umbraco.Core.Publishing; using Umbraco.Core.Services; namespace Umbraco.Web.Standalone { + //TODO: Why does this exist? there's the same thing in the Core proj + internal class ServiceContextManager : IDisposable { private readonly string _connectionString; private readonly string _providerName; + private readonly ILogger _logger; + private readonly ISqlSyntaxProvider _syntaxProvider; private ServiceContext _serviceContext; private readonly StandaloneApplication _application; - public ServiceContextManager(string connectionString, string providerName, string baseDirectory) + public ServiceContextManager(string connectionString, string providerName, string baseDirectory, ILogger logger, ISqlSyntaxProvider syntaxProvider) { _connectionString = connectionString; _providerName = providerName; + _logger = logger; + _syntaxProvider = syntaxProvider; Trace.WriteLine("Current AppDomain: " + AppDomain.CurrentDomain.FriendlyName); Trace.WriteLine("Current AppDomain: " + AppDomain.CurrentDomain.BaseDirectory); @@ -44,14 +53,16 @@ namespace Umbraco.Web.Standalone // just not quite sure what this standalone stuff is. new NullCacheProvider()); - var dbFactory = new DefaultDatabaseFactory(_connectionString, _providerName); - var dbContext = new DatabaseContext(dbFactory); + var dbFactory = new DefaultDatabaseFactory(_connectionString, _providerName, _logger); + var dbContext = new DatabaseContext(dbFactory, _logger, _syntaxProvider, _providerName); Database.Mapper = new PetaPocoMapper(); _serviceContext = new ServiceContext( + new RepositoryFactory(cacheHelper, _logger, dbContext.SqlSyntax, UmbracoConfig.For.UmbracoSettings()), new PetaPocoUnitOfWorkProvider(dbFactory), new FileUnitOfWorkProvider(), new PublishingStrategy(), - cacheHelper); + cacheHelper, + new DebugDiagnosticsLogger()); //initialize the DatabaseContext dbContext.Initialize(_providerName); diff --git a/src/Umbraco.Web/Standalone/StandaloneBootManager.cs b/src/Umbraco.Web/Standalone/StandaloneBootManager.cs index 99a1237faf..a5393c9870 100644 --- a/src/Umbraco.Web/Standalone/StandaloneBootManager.cs +++ b/src/Umbraco.Web/Standalone/StandaloneBootManager.cs @@ -3,6 +3,7 @@ using System.Collections.Generic; using System.Linq; using System.Text; using Umbraco.Core; +using Umbraco.Core.Logging; using Umbraco.Core.ObjectResolution; using Umbraco.Web.PublishedCache; using Umbraco.Web.Routing; @@ -57,11 +58,12 @@ namespace Umbraco.Web.Standalone PublishedCachesResolver.Current = new PublishedCachesResolver(caches); - UrlProviderResolver.Current = new UrlProviderResolver(typeof (DefaultUrlProvider)); + UrlProviderResolver.Current = new UrlProviderResolver(ServiceProvider, LoggerResolver.Current.Logger, typeof(DefaultUrlProvider)); SiteDomainHelperResolver.Current = new SiteDomainHelperResolver(new SiteDomainHelper()); ContentLastChanceFinderResolver.Current = new ContentLastChanceFinderResolver(); ContentFinderResolver.Current = new ContentFinderResolver( + ServiceProvider, LoggerResolver.Current.Logger, typeof (ContentFinderByPageIdQuery), typeof (ContentFinderByNiceUrl), typeof (ContentFinderByIdPath) diff --git a/src/Umbraco.Web/Strategies/Migrations/ClearCsrfCookiesAfterUpgrade.cs b/src/Umbraco.Web/Strategies/Migrations/ClearCsrfCookiesAfterUpgrade.cs index 8e76053a09..0b31f53c74 100644 --- a/src/Umbraco.Web/Strategies/Migrations/ClearCsrfCookiesAfterUpgrade.cs +++ b/src/Umbraco.Web/Strategies/Migrations/ClearCsrfCookiesAfterUpgrade.cs @@ -1,4 +1,5 @@ using System.Web; +using Umbraco.Core.Events; using Umbraco.Core.Persistence.Migrations; using Umbraco.Web.WebApi.Filters; using umbraco.interfaces; @@ -8,14 +9,9 @@ namespace Umbraco.Web.Strategies.Migrations /// /// After upgrade we clear out the csrf tokens /// - public class ClearCsrfCookiesAfterUpgrade : IApplicationStartupHandler + public class ClearCsrfCookiesAfterUpgrade : MigrationStartupHander { - public ClearCsrfCookiesAfterUpgrade() - { - MigrationRunner.Migrated += MigrationRunner_Migrated; - } - - void MigrationRunner_Migrated(MigrationRunner sender, Core.Events.MigrationEventArgs e) + protected override void AfterMigration(MigrationRunner sender, MigrationEventArgs e) { if (HttpContext.Current == null) return; diff --git a/src/Umbraco.Web/Strategies/Migrations/ClearMediaXmlCacheForDeletedItemsAfterUpgrade.cs b/src/Umbraco.Web/Strategies/Migrations/ClearMediaXmlCacheForDeletedItemsAfterUpgrade.cs index 3a498ea92f..54b4144fc0 100644 --- a/src/Umbraco.Web/Strategies/Migrations/ClearMediaXmlCacheForDeletedItemsAfterUpgrade.cs +++ b/src/Umbraco.Web/Strategies/Migrations/ClearMediaXmlCacheForDeletedItemsAfterUpgrade.cs @@ -1,5 +1,6 @@ using System; using Umbraco.Core; +using Umbraco.Core.Events; using Umbraco.Core.Logging; using Umbraco.Core.Persistence.Migrations; using Umbraco.Core.Persistence.SqlSyntax; @@ -15,14 +16,9 @@ namespace Umbraco.Web.Strategies.Migrations /// /// * If current is less than or equal to 7.0.0 /// - public class ClearMediaXmlCacheForDeletedItemsAfterUpgrade : IApplicationStartupHandler - { - public ClearMediaXmlCacheForDeletedItemsAfterUpgrade() - { - MigrationRunner.Migrated += MigrationRunner_Migrated; - } - - void MigrationRunner_Migrated(MigrationRunner sender, Core.Events.MigrationEventArgs e) + public class ClearMediaXmlCacheForDeletedItemsAfterUpgrade : MigrationStartupHander + { + protected override void AfterMigration(MigrationRunner sender, MigrationEventArgs e) { var target70 = new Version(7, 0, 0); @@ -34,7 +30,7 @@ namespace Umbraco.Web.Strategies.Migrations var sql = @"DELETE FROM cmsContentXml WHERE nodeId IN (SELECT nodeId FROM (SELECT DISTINCT cmsContentXml.nodeId FROM cmsContentXml INNER JOIN umbracoNode ON cmsContentXml.nodeId = umbracoNode.id - WHERE nodeObjectType = '" + Constants.ObjectTypes.Media +"' AND " + SqlSyntaxContext.SqlSyntaxProvider.GetQuotedColumnName("path") + " LIKE '%-21%') x)"; + WHERE nodeObjectType = '" + Constants.ObjectTypes.Media + "' AND " + SqlSyntaxContext.SqlSyntaxProvider.GetQuotedColumnName("path") + " LIKE '%-21%') x)"; var count = e.MigrationContext.Database.Execute(sql); diff --git a/src/Umbraco.Web/Strategies/Migrations/EnsureAppsTreesUpdatedOnUpgrade.cs b/src/Umbraco.Web/Strategies/Migrations/EnsureAppsTreesUpdatedOnUpgrade.cs index 582980b0bc..96373f60fd 100644 --- a/src/Umbraco.Web/Strategies/Migrations/EnsureAppsTreesUpdatedOnUpgrade.cs +++ b/src/Umbraco.Web/Strategies/Migrations/EnsureAppsTreesUpdatedOnUpgrade.cs @@ -1,4 +1,5 @@ -using Umbraco.Core.Persistence.Migrations.Upgrades.TargetVersionSix; +using Umbraco.Core; +using Umbraco.Core.Persistence.Migrations.Upgrades.TargetVersionSix; using umbraco.BusinessLogic; using umbraco.interfaces; @@ -8,14 +9,30 @@ namespace Umbraco.Web.Strategies.Migrations /// This is kind of a hack to ensure that Apps and Trees that might still reside in the db is /// written to the 'new' applications.config and trees.config files upon upgrade to version 6.0 /// - public class EnsureAppsTreesUpdatedOnUpgrade : IApplicationStartupHandler + public class EnsureAppsTreesUpdatedOnUpgrade : ApplicationEventHandler { - public EnsureAppsTreesUpdatedOnUpgrade() + /// + /// Ensure this is run when not configured + /// + protected override bool ExecuteWhenApplicationNotConfigured + { + get { return true; } + } + + /// + /// Ensure this is run when not configured + /// + protected override bool ExecuteWhenDatabaseNotConfigured + { + get { return true; } + } + + protected override void ApplicationStarting(UmbracoApplicationBase umbracoApplication, ApplicationContext applicationContext) { //This event will be triggered once the EnsureAppsTreesUpdated Up() method is run during upgrades EnsureAppsTreesUpdated.Upgrading += EnsureAppsTreesUpdated_Upgrading; } - + void EnsureAppsTreesUpdated_Upgrading(object sender, EnsureAppsTreesUpdated.UpgradingEventArgs e) { var treeRegistrar = new ApplicationTreeRegistrar(); diff --git a/src/Umbraco.Web/Strategies/Migrations/EnsureListViewDataTypeIsCreated.cs b/src/Umbraco.Web/Strategies/Migrations/EnsureListViewDataTypeIsCreated.cs index ba0ac7b387..610c57b592 100644 --- a/src/Umbraco.Web/Strategies/Migrations/EnsureListViewDataTypeIsCreated.cs +++ b/src/Umbraco.Web/Strategies/Migrations/EnsureListViewDataTypeIsCreated.cs @@ -2,6 +2,7 @@ using System.Collections.Generic; using System.Linq; using Umbraco.Core; +using Umbraco.Core.Events; using Umbraco.Core.Models; using Umbraco.Core.Models.Rdbms; using Umbraco.Core.Persistence; @@ -15,46 +16,20 @@ namespace Umbraco.Web.Strategies.Migrations /// /// Creates the built in list view data types /// - public class EnsureDefaultListViewDataTypesCreated : ApplicationEventHandler + public class EnsureDefaultListViewDataTypesCreated : MigrationStartupHander { - /// - /// Ensure this is run when not configured - /// - protected override bool ExecuteWhenApplicationNotConfigured - { - get { return true; } - } - - /// - /// Ensure this is run when not configured - /// - protected override bool ExecuteWhenDatabaseNotConfigured - { - get { return true; } - } - - /// - /// Attach to event on starting - /// - /// - /// - protected override void ApplicationStarting(UmbracoApplicationBase umbracoApplication, ApplicationContext applicationContext) - { - MigrationRunner.Migrated += MigrationRunner_Migrated; - } - - void MigrationRunner_Migrated(MigrationRunner sender, Core.Events.MigrationEventArgs e) + protected override void AfterMigration(MigrationRunner sender, MigrationEventArgs e) { var target720 = new Version(7, 2, 0); if (e.ConfiguredVersion <= target720) { EnsureListViewDataTypeCreated(e); - + } } - private void EnsureListViewDataTypeCreated(Core.Events.MigrationEventArgs e) + private void EnsureListViewDataTypeCreated(MigrationEventArgs e) { var exists = e.MigrationContext.Database.ExecuteScalar("SELECT COUNT(*) FROM umbracoNode WHERE id=1037"); if (exists > 0) return; diff --git a/src/Umbraco.Web/Strategies/Migrations/MigrationStartupHander.cs b/src/Umbraco.Web/Strategies/Migrations/MigrationStartupHander.cs new file mode 100644 index 0000000000..6b2c92f79f --- /dev/null +++ b/src/Umbraco.Web/Strategies/Migrations/MigrationStartupHander.cs @@ -0,0 +1,49 @@ +using Umbraco.Core; +using Umbraco.Core.Persistence.Migrations; + +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 + { + /// + /// Ensure this is run when not configured + /// + protected override bool ExecuteWhenApplicationNotConfigured + { + get { return true; } + } + + /// + /// Ensure this is run when not configured + /// + protected override bool ExecuteWhenDatabaseNotConfigured + { + get { return true; } + } + + public void Unsubscribe() + { + MigrationRunner.Migrated -= MigrationRunner_Migrated; + } + + /// + /// Attach to event on starting + /// + /// + /// + protected override void ApplicationStarting(UmbracoApplicationBase umbracoApplication, ApplicationContext applicationContext) + { + MigrationRunner.Migrated += MigrationRunner_Migrated; + } + + private void MigrationRunner_Migrated(MigrationRunner sender, Core.Events.MigrationEventArgs e) + { + AfterMigration(sender, e); + } + + protected abstract void AfterMigration(MigrationRunner sender, Core.Events.MigrationEventArgs e); + } +} \ No newline at end of file diff --git a/src/Umbraco.Web/Strategies/Migrations/OverwriteStylesheetFilesFromTempFiles.cs b/src/Umbraco.Web/Strategies/Migrations/OverwriteStylesheetFilesFromTempFiles.cs new file mode 100644 index 0000000000..a8ef08cce0 --- /dev/null +++ b/src/Umbraco.Web/Strategies/Migrations/OverwriteStylesheetFilesFromTempFiles.cs @@ -0,0 +1,54 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Umbraco.Core.Events; +using Umbraco.Core; +using Umbraco.Core.IO; +using Umbraco.Core.Logging; +using Umbraco.Core.Persistence.Migrations; + +namespace Umbraco.Web.Strategies.Migrations +{ + + /// + /// When upgrading version 7.3 the migration MigrateStylesheetDataToFile will execute but we don't want to overwrite the developers + /// 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 + { + protected override void AfterMigration(MigrationRunner sender, MigrationEventArgs e) + { + var target73 = new Version(7, 3, 0); + + if (e.ConfiguredVersion <= target73) + { + var tempCssFolder = IOHelper.MapPath("~/App_Data/TEMP/CssMigration/"); + var cssFolder = IOHelper.MapPath("~/css"); + if (Directory.Exists(tempCssFolder)) + { + var files = Directory.GetFiles(tempCssFolder, "*.css", SearchOption.AllDirectories); + foreach (var file in files) + { + var relativePath = file.TrimStart(tempCssFolder).TrimStart("\\"); + var cssFilePath = Path.Combine(cssFolder, relativePath); + if (File.Exists(cssFilePath)) + { + //backup + var targetPath = Path.Combine(tempCssFolder, relativePath.EnsureEndsWith(".bak")); + e.MigrationContext.Logger.Info("CSS file is being backed up from {0}, to {1} before being migrated to new format", () => cssFilePath, () => targetPath); + File.Copy(cssFilePath, targetPath, true); + } + + //ensure the sub folder eixts + Directory.CreateDirectory(Path.GetDirectoryName(cssFilePath)); + File.Copy(file, cssFilePath, true); + } + } + } + } + } +} diff --git a/src/Umbraco.Web/Strategies/Migrations/PublishAfterUpgradeToVersionSixth.cs b/src/Umbraco.Web/Strategies/Migrations/PublishAfterUpgradeToVersionSixth.cs index 43c0157c7e..3e0df97e88 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 Umbraco.Core.Events; using Umbraco.Core.Models.Rdbms; using Umbraco.Core.Persistence; using Umbraco.Core.Persistence.Migrations; @@ -14,19 +15,9 @@ 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 : IApplicationStartupHandler + public class PublishAfterUpgradeToVersionSixth : MigrationStartupHander { - public PublishAfterUpgradeToVersionSixth() - { - MigrationRunner.Migrated += MigrationRunner_Migrated; - } - - public void Unsubscribe() - { - MigrationRunner.Migrated -= MigrationRunner_Migrated; - } - - void MigrationRunner_Migrated(MigrationRunner sender, Core.Events.MigrationEventArgs e) + protected override void AfterMigration(MigrationRunner sender, MigrationEventArgs e) { var target = new Version(6, 0, 0); if (e.ConfiguredVersion < target) @@ -43,8 +34,6 @@ namespace Umbraco.Web.Strategies.Migrations .Where(x => x.NodeObjectType == new Guid(Constants.ObjectTypes.Document)) .Where(x => x.Path.StartsWith("-1")); - - var dtos = e.MigrationContext.Database.Fetch(sql); var toUpdate = new List(); var versionGroup = dtos.GroupBy(x => x.NodeId); @@ -80,6 +69,7 @@ namespace Umbraco.Web.Strategies.Migrations transaction.Complete(); } } - } + } + } } \ No newline at end of file diff --git a/src/Umbraco.Web/Strategies/Migrations/RebuildMediaXmlCacheAfterUpgrade.cs b/src/Umbraco.Web/Strategies/Migrations/RebuildMediaXmlCacheAfterUpgrade.cs index 72cf6c24ea..fad63c66dc 100644 --- a/src/Umbraco.Web/Strategies/Migrations/RebuildMediaXmlCacheAfterUpgrade.cs +++ b/src/Umbraco.Web/Strategies/Migrations/RebuildMediaXmlCacheAfterUpgrade.cs @@ -1,5 +1,6 @@ using System; using Umbraco.Core; +using Umbraco.Core.Events; using Umbraco.Core.Persistence.Migrations; using Umbraco.Core.Services; using umbraco.interfaces; @@ -16,14 +17,9 @@ namespace Umbraco.Web.Strategies.Migrations /// /// * If current is less than or equal to 7.0.0 /// - public class RebuildMediaXmlCacheAfterUpgrade : IApplicationStartupHandler + public class RebuildMediaXmlCacheAfterUpgrade : MigrationStartupHander { - public RebuildMediaXmlCacheAfterUpgrade() - { - MigrationRunner.Migrated += MigrationRunner_Migrated; - } - - void MigrationRunner_Migrated(MigrationRunner sender, Core.Events.MigrationEventArgs e) + protected override void AfterMigration(MigrationRunner sender, MigrationEventArgs e) { var target70 = new Version(7, 0, 0); @@ -32,7 +28,6 @@ namespace Umbraco.Web.Strategies.Migrations var mediasvc = (MediaService)ApplicationContext.Current.Services.MediaService; mediasvc.RebuildXmlStructures(); } - } } } \ No newline at end of file diff --git a/src/Umbraco.Web/Trees/ContentTreeController.cs b/src/Umbraco.Web/Trees/ContentTreeController.cs index ef17840edf..9ed37b29d6 100644 --- a/src/Umbraco.Web/Trees/ContentTreeController.cs +++ b/src/Umbraco.Web/Trees/ContentTreeController.cs @@ -177,6 +177,7 @@ namespace Umbraco.Web.Trees if (item.Path.Split(new[] {','}, StringSplitOptions.RemoveEmptyEntries).Contains(RecycleBinId.ToInvariantString())) { nodeMenu.DefaultMenuAlias = null; + nodeMenu.Items.Insert(2, new MenuItem(ActionRestore.Instance, ui.Text("actions", ActionRestore.Instance.Alias))); } else { diff --git a/src/Umbraco.Web/Trees/LanguageTreeController.cs b/src/Umbraco.Web/Trees/LanguageTreeController.cs new file mode 100644 index 0000000000..fefbf82307 --- /dev/null +++ b/src/Umbraco.Web/Trees/LanguageTreeController.cs @@ -0,0 +1,99 @@ +using System; +using System.Data.SqlClient; +using System.Globalization; +using System.Net.Http.Formatting; +using System.Web.Services.Description; +using umbraco; +using umbraco.BusinessLogic.Actions; +using Umbraco.Core; +using Umbraco.Core.Models; +using umbraco.presentation.actions; +using Umbraco.Web.Models.Trees; +using Umbraco.Web.Mvc; +using Umbraco.Web.WebApi.Filters; +using Constants = Umbraco.Core.Constants; + +namespace Umbraco.Web.Trees +{ + [UmbracoTreeAuthorize(Constants.Trees.Languages)] + [LegacyBaseTree(typeof(loadLanguages))] + [Tree(Constants.Applications.Settings, Constants.Trees.Languages, "Languages", sortOrder: 4)] + [PluginController("UmbracoTrees")] + [CoreTree] + public class LanguageTreeController : TreeController + { + /// + /// The method called to render the contents of the tree structure + /// + /// + /// + /// All of the query string parameters passed from jsTree + /// + /// + /// We are allowing an arbitrary number of query strings to be pased in so that developers are able to persist custom data from the front-end + /// to the back end to be used in the query for model data. + /// + protected override TreeNodeCollection GetTreeNodes(string id, FormDataCollection queryStrings) + { + var nodes = new TreeNodeCollection(); + + if (id == Constants.System.Root.ToInvariantString()) + { + var languages = Services.LocalizationService.GetAllLanguages(); + foreach (var language in languages) + { + nodes.Add( + CreateTreeNode( + language.Id.ToString(CultureInfo.InvariantCulture), "-1", queryStrings, language.CultureInfo.DisplayName, "icon-flag-alt", false, + //TODO: Rebuild the language 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/settings/editLanguage.aspx?id=" + language.Id))); + } + } + + return nodes; + } + + /// + /// Returns the menu structure for the node + /// + /// + /// + /// + 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(ui.Text("actions", ActionNew.Instance.Alias)) + //Since we haven't implemented anything for languages in angular, this needs to be converted to + //use the legacy format + .ConvertLegacyMenuItem(null, "initlanguages", queryStrings.GetValue("application")); + + //refresh action + menu.Items.Add(ui.Text("actions", ActionRefresh.Instance.Alias), true); + + return menu; + } + + var lang = Services.LocalizationService.GetLanguageById(int.Parse(id)); + if (lang == null) return new MenuItemCollection(); + + //add delete option for all languages + menu.Items.Add(ui.Text("actions", ActionDelete.Instance.Alias)) + //Since we haven't implemented anything for languages in angular, this needs to be converted to + //use the legacy format + .ConvertLegacyMenuItem(new UmbracoEntity + { + Id = lang.Id, + Level = 1, + ParentId = -1, + Name = lang.CultureInfo.DisplayName + }, "language", queryStrings.GetValue("application")); + + return menu; + } + } +} \ No newline at end of file diff --git a/src/Umbraco.Web/Trees/TemplatesTreeController.cs b/src/Umbraco.Web/Trees/TemplatesTreeController.cs new file mode 100644 index 0000000000..9e4b6f71d8 --- /dev/null +++ b/src/Umbraco.Web/Trees/TemplatesTreeController.cs @@ -0,0 +1,139 @@ +using System; +using System.Collections; +using System.Collections.Generic; +using System.Globalization; +using System.IO; +using System.Linq; +using System.Net.Http.Formatting; +using System.Web.Services.Description; +using umbraco; +using umbraco.BusinessLogic.Actions; +using umbraco.cms.businesslogic.template; +using Umbraco.Core; +using Umbraco.Core.Configuration; +using Umbraco.Core.Models; +using Umbraco.Web.Models.Trees; +using Umbraco.Web.Mvc; +using Umbraco.Web.WebApi.Filters; +using Constants = Umbraco.Core.Constants; + +namespace Umbraco.Web.Trees +{ + [UmbracoTreeAuthorize(Constants.Trees.Templates)] + [LegacyBaseTree(typeof (loadTemplates))] + [Tree(Constants.Applications.Settings, Constants.Trees.Templates, "Templates", sortOrder:1)] + [PluginController("UmbracoTrees")] + [CoreTree] + public class TemplatesTreeController : TreeController + { + /// + /// The method called to render the contents of the tree structure + /// + /// + /// + /// All of the query string parameters passed from jsTree + /// + /// + /// We are allowing an arbitrary number of query strings to be pased in so that developers are able to persist custom data from the front-end + /// to the back end to be used in the query for model data. + /// + protected override TreeNodeCollection GetTreeNodes(string id, FormDataCollection queryStrings) + { + var nodes = new TreeNodeCollection(); + + var found = id == Constants.System.Root.ToInvariantString() + ? Services.FileService.GetTemplates(-1) + : Services.FileService.GetTemplates(int.Parse(id)); + + nodes.AddRange(found.Select(template => CreateTreeNode( + template.Id.ToString(CultureInfo.InvariantCulture), + //TODO: Fix parent ID stuff for templates + "-1", + queryStrings, + template.Name, + template.IsMasterTemplate ? "icon-newspaper" : "icon-newspaper-alt", + template.IsMasterTemplate, + GetEditorPath(template, queryStrings)))); + + return nodes; + } + + /// + /// Returns the menu structure for the node + /// + /// + /// + /// + 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(ui.Text("actions", ActionNew.Instance.Alias)) + //Since we haven't implemented anything for templates in angular, this needs to be converted to + //use the legacy format + .ConvertLegacyMenuItem(null, "inittemplates", queryStrings.GetValue("application")); + + //refresh action + menu.Items.Add(ui.Text("actions", ActionRefresh.Instance.Alias), true); + + return menu; + } + + var template = Services.FileService.GetTemplate(int.Parse(id)); + if (template == null) return new MenuItemCollection(); + var entity = FromTemplate(template); + + //Create the create action for creating sub layouts + menu.Items.Add(ui.Text("actions", ActionNew.Instance.Alias)) + //Since we haven't implemented anything for templates in angular, this needs to be converted to + //use the legacy format + .ConvertLegacyMenuItem(entity, "templates", queryStrings.GetValue("application")); + + //don't allow delete if it has child layouts + if (template.IsMasterTemplate == false) + { + //add delete option if it doesn't have children + menu.Items.Add(ui.Text("actions", ActionDelete.Instance.Alias), true) + //Since we haven't implemented anything for languages in angular, this needs to be converted to + //use the legacy format + .ConvertLegacyMenuItem(entity, "templates", queryStrings.GetValue("application")); + } + + //add refresh + menu.Items.Add(ui.Text("actions", ActionRefresh.Instance.Alias), true); + + + return menu; + } + + private UmbracoEntity FromTemplate(ITemplate template) + { + return new UmbracoEntity + { + CreateDate = template.CreateDate, + Id = template.Id, + Key = template.Key, + Name = template.Name, + NodeObjectTypeId = new Guid(Constants.ObjectTypes.Template), + //TODO: Fix parent/paths on templates + ParentId = -1, + Path = template.Path, + UpdateDate = template.UpdateDate + }; + } + + private string GetEditorPath(ITemplate template, FormDataCollection queryStrings) + { + //TODO: Rebuild the language editor in angular, then we dont need to have this at all (which is just a path to the legacy editor) + + return Services.FileService.DetermineTemplateRenderingEngine(template) == RenderingEngine.WebForms + ? "/" + queryStrings.GetValue("application") + "/framed/" + + Uri.EscapeDataString("/umbraco/settings/editTemplate.aspx?templateID=" + template.Id) + : "/" + queryStrings.GetValue("application") + "/framed/" + + Uri.EscapeDataString("/umbraco/settings/Views/EditView.aspx?treeType=" + Constants.Trees.Templates + "&templateID=" + template.Id); + } + } +} \ No newline at end of file diff --git a/src/Umbraco.Web/Trees/TreeControllerBase.cs b/src/Umbraco.Web/Trees/TreeControllerBase.cs index ebf4275c1f..74b2ffc670 100644 --- a/src/Umbraco.Web/Trees/TreeControllerBase.cs +++ b/src/Umbraco.Web/Trees/TreeControllerBase.cs @@ -190,7 +190,12 @@ namespace Umbraco.Web.Trees { var jsonUrl = Url.GetTreeUrl(GetType(), id, queryStrings); var menuUrl = Url.GetMenuUrl(GetType(), id, queryStrings); - var node = new TreeNode(id, parentId, jsonUrl, menuUrl) { Name = title, Icon = icon }; + var node = new TreeNode(id, parentId, jsonUrl, menuUrl) + { + Name = title, + Icon = icon, + NodeType = TreeAlias + }; return node; } diff --git a/src/Umbraco.Web/UI/CdfLogger.cs b/src/Umbraco.Web/UI/CdfLogger.cs index 75c7f33c84..32d12f8293 100644 --- a/src/Umbraco.Web/UI/CdfLogger.cs +++ b/src/Umbraco.Web/UI/CdfLogger.cs @@ -4,6 +4,7 @@ using System.Linq; using System.Text; using ClientDependency.Core.Logging; using Umbraco.Core.Logging; +using ILogger = ClientDependency.Core.Logging.ILogger; namespace Umbraco.Web.UI { diff --git a/src/Umbraco.Web/UI/Controls/UmbracoControl.cs b/src/Umbraco.Web/UI/Controls/UmbracoControl.cs index 66f896312e..4d8bd4ce69 100644 --- a/src/Umbraco.Web/UI/Controls/UmbracoControl.cs +++ b/src/Umbraco.Web/UI/Controls/UmbracoControl.cs @@ -4,6 +4,7 @@ using System.Web.Mvc; using System.Web.Routing; using System.Web.UI; using Umbraco.Core; +using Umbraco.Core.Logging; using Umbraco.Core.Services; using umbraco.BusinessLogic; using umbraco.DataLayer; @@ -15,7 +16,8 @@ namespace Umbraco.Web.UI.Controls /// public abstract class UmbracoControl : Control { - /// + + /// /// Default constructor /// /// @@ -39,6 +41,22 @@ namespace Umbraco.Web.UI.Controls /// public UmbracoHelper Umbraco { get; private set; } + /// + /// Returns an ILogger + /// + public ILogger Logger + { + get { return ProfilingLogger.Logger; } + } + + /// + /// Returns a ProfilingLogger + /// + public ProfilingLogger ProfilingLogger + { + get { return UmbracoContext.Application.ProfilingLogger; } + } + public UmbracoContext UmbracoContext { get; private set; } protected ApplicationContext ApplicationContext diff --git a/src/Umbraco.Web/UI/Controls/UmbracoUserControl.cs b/src/Umbraco.Web/UI/Controls/UmbracoUserControl.cs index 4910dcb2d4..b60c519dd4 100644 --- a/src/Umbraco.Web/UI/Controls/UmbracoUserControl.cs +++ b/src/Umbraco.Web/UI/Controls/UmbracoUserControl.cs @@ -4,6 +4,7 @@ using System.Web.Mvc; using System.Web.Routing; using System.Web.UI; using Umbraco.Core; +using Umbraco.Core.Logging; using Umbraco.Core.Services; using Umbraco.Web.Security; using umbraco.DataLayer; @@ -64,6 +65,22 @@ namespace Umbraco.Web.UI.Controls get { return UmbracoContext.Security; } } + /// + /// Returns an ILogger + /// + public ILogger Logger + { + get { return ProfilingLogger.Logger; } + } + + /// + /// Returns a ProfilingLogger + /// + public ProfilingLogger ProfilingLogger + { + get { return UmbracoContext.Application.ProfilingLogger; } + } + /// /// Returns the current UmbracoContext /// diff --git a/src/Umbraco.Web/UI/LegacyDialogHandler.cs b/src/Umbraco.Web/UI/LegacyDialogHandler.cs index 50539face7..5ae7d0c627 100644 --- a/src/Umbraco.Web/UI/LegacyDialogHandler.cs +++ b/src/Umbraco.Web/UI/LegacyDialogHandler.cs @@ -184,6 +184,26 @@ namespace Umbraco.Web.UI : ""; } + internal static string Create(HttpContextBase httpContext, User umbracoUser, string nodeType, int nodeId, string text, IDictionary additionalValues, int typeId = 0) + { + var typeInstance = GetTaskForOperation(httpContext, umbracoUser, Operation.Create, nodeType); + + typeInstance.TypeID = typeId; + typeInstance.ParentID = nodeId; + typeInstance.Alias = text; + + // check for returning url + var returnUrlTask = typeInstance as LegacyDialogTask; + + returnUrlTask.AdditionalValues = additionalValues; + + typeInstance.Save(); + + return returnUrlTask != null + ? returnUrlTask.ReturnUrl + : ""; + } + private static XmlDocument GetXmlDoc() { // Load task settings diff --git a/src/Umbraco.Web/UI/LegacyDialogTask.cs b/src/Umbraco.Web/UI/LegacyDialogTask.cs index 537141e30a..1975021121 100644 --- a/src/Umbraco.Web/UI/LegacyDialogTask.cs +++ b/src/Umbraco.Web/UI/LegacyDialogTask.cs @@ -89,5 +89,7 @@ namespace Umbraco.Web.UI public abstract string ReturnUrl { get; } public abstract string AssignedApp { get; } + + public IDictionary AdditionalValues { get; set; } } } diff --git a/src/Umbraco.Web/UI/Pages/BasePage.cs b/src/Umbraco.Web/UI/Pages/BasePage.cs index 4fa198f8b6..b9eec4982b 100644 --- a/src/Umbraco.Web/UI/Pages/BasePage.cs +++ b/src/Umbraco.Web/UI/Pages/BasePage.cs @@ -9,6 +9,7 @@ using Umbraco.Core; using Umbraco.Core.Configuration; using Umbraco.Core.IO; using Umbraco.Core.Logging; +using Umbraco.Core.Profiling; using Umbraco.Core.Services; using Umbraco.Web.Security; using umbraco.BusinessLogic; @@ -28,8 +29,6 @@ namespace Umbraco.Web.UI.Pages private ClientTools _clientTools; - - //We won't expose this... people should be using the DatabaseContext for custom queries if they need them. @@ -42,6 +41,25 @@ namespace Umbraco.Web.UI.Pages // get { return global::umbraco.BusinessLogic.Application.SqlHelper; } //} + /// + /// Returns an ILogger + /// + public ILogger Logger + { + get { return ProfilingLogger.Logger; } + } + + /// + /// Returns a ProfilingLogger + /// + public ProfilingLogger ProfilingLogger + { + get { return _logger ?? (_logger = new ProfilingLogger(LoggerResolver.Current.Logger, ProfilerResolver.Current.Profiler)); } + } + + private ProfilingLogger _logger; + + private UrlHelper _url; /// /// Returns a UrlHelper diff --git a/src/Umbraco.Web/Umbraco.Web.csproj b/src/Umbraco.Web/Umbraco.Web.csproj index e5c16ae10a..16cfbb24cf 100644 --- a/src/Umbraco.Web/Umbraco.Web.csproj +++ b/src/Umbraco.Web/Umbraco.Web.csproj @@ -264,8 +264,11 @@ + + + @@ -306,6 +309,7 @@ + @@ -493,17 +497,21 @@ + + + + diff --git a/src/Umbraco.Web/UmbracoApplication.cs b/src/Umbraco.Web/UmbracoApplication.cs index 3435659506..37de741007 100644 --- a/src/Umbraco.Web/UmbracoApplication.cs +++ b/src/Umbraco.Web/UmbracoApplication.cs @@ -3,6 +3,7 @@ using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Linq; +using System.Runtime.InteropServices; using System.Text; using System.Web; using System.Web.Hosting; @@ -22,7 +23,7 @@ namespace Umbraco.Web /// public class UmbracoApplication : UmbracoApplicationBase { - private readonly ManifestWatcher _mw = new ManifestWatcher(); + private ManifestWatcher _mw; protected override void OnApplicationStarted(object sender, EventArgs e) { @@ -30,6 +31,7 @@ namespace Umbraco.Web if (ApplicationContext.Current.IsConfigured && GlobalSettings.DebugMode) { + _mw = new ManifestWatcher(LoggerResolver.Current.Logger); _mw.Start(Directory.GetDirectories(IOHelper.MapPath("~/App_Plugins/"))); } } @@ -38,7 +40,10 @@ namespace Umbraco.Web { base.OnApplicationEnd(sender, e); - _mw.Dispose(); + if (_mw != null) + { + _mw.Dispose(); + } } protected override IBootManager GetBootManager() diff --git a/src/Umbraco.Web/WebApi/Filters/FileUploadCleanupFilterAttribute.cs b/src/Umbraco.Web/WebApi/Filters/FileUploadCleanupFilterAttribute.cs index 9a7b22ee73..f2dbfd7cba 100644 --- a/src/Umbraco.Web/WebApi/Filters/FileUploadCleanupFilterAttribute.cs +++ b/src/Umbraco.Web/WebApi/Filters/FileUploadCleanupFilterAttribute.cs @@ -1,6 +1,8 @@ using System.Linq; using System.Net.Http; using System.Web.Http.Filters; +using Umbraco.Core; +using Umbraco.Core.Logging; using Umbraco.Core.Models; using Umbraco.Web.Models.ContentEditing; using File = System.IO.File; @@ -52,20 +54,70 @@ namespace Umbraco.Web.WebApi.Filters } else { - var objectContent = actionExecutedContext.Response.Content as ObjectContent; + if (actionExecutedContext == null) + { + LogHelper.Warn("The actionExecutedContext is null!!??"); + return; + } + if (actionExecutedContext.Request == null) + { + LogHelper.Warn("The actionExecutedContext.Request is null!!??"); + return; + } + if (actionExecutedContext.Request.Content == null) + { + LogHelper.Warn("The actionExecutedContext.Request.Content is null!!??"); + return; + } + + ObjectContent objectContent; + + try + { + objectContent = actionExecutedContext.Response.Content as ObjectContent; + } + catch (System.Exception ex) + { + LogHelper.Error("Could not acquire actionExecutedContext.Response.Content", ex); + return; + } + if (objectContent != null) { var uploadedFiles = objectContent.Value as IHaveUploadedFiles; if (uploadedFiles != null) { - //cleanup any files associated - foreach (var f in uploadedFiles.UploadedFiles) + if (uploadedFiles.UploadedFiles != null) { - File.Delete(f.TempFilePath); - //clear out the temp path so it's not returned in the response - f.TempFilePath = ""; + //cleanup any files associated + foreach (var f in uploadedFiles.UploadedFiles) + { + if (f.TempFilePath.IsNullOrWhiteSpace() == false) + { + LogHelper.Debug("Removing temp file " + f.TempFilePath); + File.Delete(f.TempFilePath); + //clear out the temp path so it's not returned in the response + f.TempFilePath = ""; + } + else + { + LogHelper.Warn("The f.TempFilePath is null or whitespace!!??"); + } + } } + else + { + LogHelper.Warn("The uploadedFiles.UploadedFiles is null!!??"); + } } + else + { + LogHelper.Warn("The actionExecutedContext.Request.Content.Value is not IHaveUploadedFiles, it is " + objectContent.Value.GetType()); + } + } + else + { + LogHelper.Warn("The actionExecutedContext.Request.Content is not ObjectContent, it is " + actionExecutedContext.Request.Content.GetType()); } } diff --git a/src/Umbraco.Web/WebApi/UmbracoApiController.cs b/src/Umbraco.Web/WebApi/UmbracoApiController.cs index 572e9e5af3..9b1a37f4f7 100644 --- a/src/Umbraco.Web/WebApi/UmbracoApiController.cs +++ b/src/Umbraco.Web/WebApi/UmbracoApiController.cs @@ -5,6 +5,7 @@ using System.Web; using System.Web.Http; using System.Web.Http.ModelBinding; using Umbraco.Core; +using Umbraco.Core.Logging; using Umbraco.Core.Models; using Umbraco.Core.Models.Validation; using Umbraco.Core.Services; @@ -41,6 +42,22 @@ namespace Umbraco.Web.WebApi return Request.TryGetHttpContext(); } + /// + /// Returns an ILogger + /// + public ILogger Logger + { + get { return ProfilingLogger.Logger; } + } + + /// + /// Returns a ProfilingLogger + /// + public ProfilingLogger ProfilingLogger + { + get { return UmbracoContext.Application.ProfilingLogger; } + } + /// /// Returns the current ApplicationContext /// diff --git a/src/Umbraco.Web/WebApi/UmbracoApiControllerResolver.cs b/src/Umbraco.Web/WebApi/UmbracoApiControllerResolver.cs index 1d4d48d4f6..cea26b8de7 100644 --- a/src/Umbraco.Web/WebApi/UmbracoApiControllerResolver.cs +++ b/src/Umbraco.Web/WebApi/UmbracoApiControllerResolver.cs @@ -1,13 +1,14 @@ using System; using System.Collections.Generic; +using Umbraco.Core.Logging; using Umbraco.Core.ObjectResolution; namespace Umbraco.Web.WebApi { internal sealed class UmbracoApiControllerResolver : ManyObjectsResolverBase { - public UmbracoApiControllerResolver(IEnumerable apiControllers) - : base(apiControllers) + public UmbracoApiControllerResolver(IServiceProvider serviceProvider, ILogger logger, IEnumerable apiControllers) + : base(serviceProvider, logger, apiControllers) { } diff --git a/src/Umbraco.Web/WebBootManager.cs b/src/Umbraco.Web/WebBootManager.cs index 93e117e3a1..1d11991664 100644 --- a/src/Umbraco.Web/WebBootManager.cs +++ b/src/Umbraco.Web/WebBootManager.cs @@ -315,7 +315,7 @@ namespace Umbraco.Web { base.InitializeResolvers(); - XsltExtensionsResolver.Current = new XsltExtensionsResolver(() => PluginManager.Current.ResolveXsltExtensions()); + XsltExtensionsResolver.Current = new XsltExtensionsResolver(ServiceProvider, LoggerResolver.Current.Logger, () => PluginManager.Current.ResolveXsltExtensions()); //set the default RenderMvcController DefaultRenderMvcControllerResolver.Current = new DefaultRenderMvcControllerResolver(typeof(RenderMvcController)); @@ -334,18 +334,20 @@ namespace Umbraco.Web } catch (Exception e) { - LogHelper.Error("An error occurred trying to set the IServerMessenger during application startup", e); + LoggerResolver.Current.Logger.Error("An error occurred trying to set the IServerMessenger during application startup", e); return null; } } - LogHelper.Warn("Could not initialize the DefaultServerMessenger, the application is not configured or the database is not configured"); + LoggerResolver.Current.Logger.Warn("Could not initialize the DefaultServerMessenger, the application is not configured or the database is not configured"); return null; })); SurfaceControllerResolver.Current = new SurfaceControllerResolver( + ServiceProvider, LoggerResolver.Current.Logger, PluginManager.Current.ResolveSurfaceControllers()); UmbracoApiControllerResolver.Current = new UmbracoApiControllerResolver( + ServiceProvider, LoggerResolver.Current.Logger, PluginManager.Current.ResolveUmbracoApiControllers()); // both TinyMceValueConverter (in Core) and RteMacroRenderingValueConverter (in Web) will be @@ -366,6 +368,7 @@ namespace Umbraco.Web new NamespaceHttpControllerSelector(GlobalConfiguration.Configuration)); FilteredControllerFactoriesResolver.Current = new FilteredControllerFactoriesResolver( + ServiceProvider, LoggerResolver.Current.Logger, // add all known factories, devs can then modify this list on application // startup either by binding to events or in their own global.asax new[] @@ -374,6 +377,7 @@ namespace Umbraco.Web }); UrlProviderResolver.Current = new UrlProviderResolver( + ServiceProvider, LoggerResolver.Current.Logger, //typeof(AliasUrlProvider), // not enabled by default typeof(DefaultUrlProvider), typeof(CustomRouteUrlProvider) @@ -382,6 +386,7 @@ namespace Umbraco.Web ContentLastChanceFinderResolver.Current = new ContentLastChanceFinderResolver(new ContentFinderByLegacy404()); ContentFinderResolver.Current = new ContentFinderResolver( + ServiceProvider, LoggerResolver.Current.Logger, // all built-in finders in the correct order, devs can then modify this list // on application startup via an application event handler. typeof(ContentFinderByPageIdQuery), @@ -399,9 +404,11 @@ namespace Umbraco.Web PublishedCache.XmlPublishedCache.PublishedContentCache.UnitTesting = _isForTesting; ThumbnailProvidersResolver.Current = new ThumbnailProvidersResolver( + ServiceProvider, LoggerResolver.Current.Logger, PluginManager.Current.ResolveThumbnailProviders()); ImageUrlProviderResolver.Current = new ImageUrlProviderResolver( + ServiceProvider, LoggerResolver.Current.Logger, PluginManager.Current.ResolveImageUrlProviders()); CultureDictionaryFactoryResolver.Current = new CultureDictionaryFactoryResolver( diff --git a/src/Umbraco.Web/WebServices/SaveFileController.cs b/src/Umbraco.Web/WebServices/SaveFileController.cs index 849807098f..651b372988 100644 --- a/src/Umbraco.Web/WebServices/SaveFileController.cs +++ b/src/Umbraco.Web/WebServices/SaveFileController.cs @@ -163,6 +163,8 @@ namespace Umbraco.Web.WebServices [HttpPost] public JsonResult SaveTemplate(string templateName, string templateAlias, string templateContents, int templateId, int masterTemplateId) { + //TODO: Change this over to use the new API - Also this will be migrated to a TemplateEditor or ViewEditor when it's all moved to angular + Template t; bool pathChanged = false; try @@ -174,11 +176,12 @@ namespace Umbraco.Web.WebServices Design = templateContents }; - //check if the master page has changed - if (t.MasterTemplate != masterTemplateId) + //check if the master page has changed - we need to normalize both - if it's 0 or -1, then make it 0... this is easy + // to do with Math.Max + if (Math.Max(t.MasterTemplate, 0) != Math.Max(masterTemplateId, 0)) { - pathChanged = true; - t.MasterTemplate = masterTemplateId; + t.MasterTemplate = Math.Max(masterTemplateId, 0); + pathChanged = true; } } catch (ArgumentException ex) @@ -201,7 +204,11 @@ namespace Umbraco.Web.WebServices var syncPath = "-1,init," + t.Path.Replace("-1,", ""); return Success(ui.Text("speechBubbles", "templateSavedText"), ui.Text("speechBubbles", "templateSavedHeader"), - new { path = syncPath }); + new + { + path = syncPath, + contents = t.Design + }); } catch (Exception ex) { diff --git a/src/Umbraco.Web/WebServices/UmbracoHttpHandler.cs b/src/Umbraco.Web/WebServices/UmbracoHttpHandler.cs index b7c8344788..d50f28b350 100644 --- a/src/Umbraco.Web/WebServices/UmbracoHttpHandler.cs +++ b/src/Umbraco.Web/WebServices/UmbracoHttpHandler.cs @@ -3,6 +3,7 @@ using System.Web; using System.Web.Mvc; using System.Web.Routing; using Umbraco.Core; +using Umbraco.Core.Logging; using Umbraco.Core.Services; using Umbraco.Web.Security; @@ -34,6 +35,22 @@ namespace Umbraco.Web.WebServices get { return UmbracoContext.Application; } } + /// + /// Returns an ILogger + /// + public ILogger Logger + { + get { return ProfilingLogger.Logger; } + } + + /// + /// Returns a ProfilingLogger + /// + public ProfilingLogger ProfilingLogger + { + get { return UmbracoContext.Application.ProfilingLogger; } + } + /// /// Returns the current UmbracoContext /// diff --git a/src/Umbraco.Web/WebServices/UmbracoWebService.cs b/src/Umbraco.Web/WebServices/UmbracoWebService.cs index 5f7dc7da5d..e92e85de1e 100644 --- a/src/Umbraco.Web/WebServices/UmbracoWebService.cs +++ b/src/Umbraco.Web/WebServices/UmbracoWebService.cs @@ -4,6 +4,7 @@ using System.Web.Mvc; using System.Web.Routing; using System.Web.Services; using Umbraco.Core; +using Umbraco.Core.Logging; using Umbraco.Core.Services; using Umbraco.Web.Security; @@ -35,6 +36,22 @@ namespace Umbraco.Web.WebServices get { return UmbracoContext.Application; } } + /// + /// Returns an ILogger + /// + public ILogger Logger + { + get { return ProfilingLogger.Logger; } + } + + /// + /// Returns a ProfilingLogger + /// + public ProfilingLogger ProfilingLogger + { + get { return UmbracoContext.Application.ProfilingLogger; } + } + /// /// Returns the current UmbracoContext /// diff --git a/src/Umbraco.Web/umbraco.presentation/umbraco/Trees/loadLanguages.cs b/src/Umbraco.Web/umbraco.presentation/umbraco/Trees/loadLanguages.cs index 657a85fef3..57e0d3f55a 100644 --- a/src/Umbraco.Web/umbraco.presentation/umbraco/Trees/loadLanguages.cs +++ b/src/Umbraco.Web/umbraco.presentation/umbraco/Trees/loadLanguages.cs @@ -8,7 +8,8 @@ using Umbraco.Core; namespace umbraco { - [Tree(Constants.Applications.Settings, "languages", "Languages", sortOrder: 4)] + [Obsolete("This is no longer used and will be removed from the codebase in the future")] + //[Tree(Constants.Applications.Settings, "languages", "Languages", sortOrder: 4)] public class loadLanguages : BaseTree { public loadLanguages(string application) : base(application) { } diff --git a/src/Umbraco.Web/umbraco.presentation/umbraco/Trees/loadStylesheetProperty.cs b/src/Umbraco.Web/umbraco.presentation/umbraco/Trees/loadStylesheetProperty.cs index 2d3d8b50d6..0756186d7a 100644 --- a/src/Umbraco.Web/umbraco.presentation/umbraco/Trees/loadStylesheetProperty.cs +++ b/src/Umbraco.Web/umbraco.presentation/umbraco/Trees/loadStylesheetProperty.cs @@ -1,4 +1,5 @@ using System; +using System.Globalization; using System.Text; using umbraco.businesslogic; using umbraco.cms.businesslogic.web; @@ -18,27 +19,31 @@ namespace umbraco rootNode.NodeType = "init" + TreeAlias; rootNode.NodeID = "init"; } - + public override void RenderJS(ref StringBuilder Javascript) { Javascript.Append( @" - function openStylesheetProperty(id) { - UmbClientMgr.contentFrame('settings/stylesheet/property/editStylesheetProperty.aspx?id=' + id); + function openStylesheetProperty(name, prop) { + UmbClientMgr.contentFrame('settings/stylesheet/property/editStylesheetProperty.aspx?id=' + name + '&prop=' + prop); } "); } public override void Render(ref XmlTree tree) { - StyleSheet sn = new StyleSheet(m_id); + var sheet = Services.FileService.GetStylesheetByName(NodeKey.EnsureEndsWith(".css")); - foreach (StylesheetProperty n in sn.Properties) + foreach (var prop in sheet.Properties) { - XmlTreeNode xNode = XmlTreeNode.Create(this); - xNode.NodeID = n.Id.ToString(); - xNode.Text = n.Text; - xNode.Action = "javascript:openStylesheetProperty(" + n.Id + ");"; + 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"; diff --git a/src/Umbraco.Web/umbraco.presentation/umbraco/Trees/loadStylesheets.cs b/src/Umbraco.Web/umbraco.presentation/umbraco/Trees/loadStylesheets.cs index aa2dea6007..03ebc3da86 100644 --- a/src/Umbraco.Web/umbraco.presentation/umbraco/Trees/loadStylesheets.cs +++ b/src/Umbraco.Web/umbraco.presentation/umbraco/Trees/loadStylesheets.cs @@ -1,6 +1,7 @@ using System; using System.Collections.Generic; using System.Globalization; +using System.Linq; using System.Text; using umbraco.businesslogic; using umbraco.cms.businesslogic.web; @@ -12,7 +13,7 @@ using Umbraco.Core; namespace umbraco { - [Tree(Constants.Applications.Settings, "stylesheets", "Stylesheets")] + [Tree(Constants.Applications.Settings, Constants.Trees.Stylesheets, "Stylesheets")] public class loadStylesheets : BaseTree { public loadStylesheets(string application) : base(application) { } @@ -28,8 +29,8 @@ namespace umbraco { Javascript.Append( @" - function openStylesheet(id) { - UmbClientMgr.contentFrame('settings/stylesheet/editStylesheet.aspx?id=' + id); + function openStylesheet(name) { + UmbClientMgr.contentFrame('settings/stylesheet/editStylesheet.aspx?id=' + name); } "); } @@ -43,15 +44,18 @@ namespace umbraco public override void Render(ref XmlTree tree) { - foreach (StyleSheet n in StyleSheet.GetAll()) + foreach (var sheet in Services.FileService.GetStylesheets()) { - XmlTreeNode xNode = XmlTreeNode.Create(this); - xNode.NodeID = n.Id.ToString(CultureInfo.InvariantCulture); - xNode.Text = n.Text; - xNode.Action = "javascript:openStylesheet(" + n.Id + ");"; - loadStylesheetProperty styleSheetPropertyTree = new loadStylesheetProperty(this.app); - xNode.Source = styleSheetPropertyTree.GetTreeServiceUrl(n.Id); - xNode.HasChildren = n.HasChildren; + 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. diff --git a/src/Umbraco.Web/umbraco.presentation/umbraco/Trees/loadTemplates.cs b/src/Umbraco.Web/umbraco.presentation/umbraco/Trees/loadTemplates.cs index dc2088bae5..4da68849aa 100644 --- a/src/Umbraco.Web/umbraco.presentation/umbraco/Trees/loadTemplates.cs +++ b/src/Umbraco.Web/umbraco.presentation/umbraco/Trees/loadTemplates.cs @@ -1,11 +1,13 @@ using System; using System.Collections.Generic; +using System.Globalization; using System.IO; using System.Text; using Umbraco.Core; using Umbraco.Core.Configuration; using Umbraco.Core.IO; using umbraco.businesslogic; +using Umbraco.Core.Services; using umbraco.interfaces; using umbraco.cms.businesslogic.template; using umbraco.cms.presentation.Trees; @@ -14,11 +16,13 @@ using umbraco.BusinessLogic.Actions; namespace umbraco { - [Tree(Constants.Applications.Settings, "templates", "Templates", sortOrder: 1)] + [Obsolete("This is no longer used and will be removed from the codebase in the future")] public class loadTemplates : BaseTree { public loadTemplates(string application) : base(application) {} + private ViewHelper _viewHelper = new ViewHelper(new PhysicalFileSystem(SystemDirectories.MvcViews)); + protected override void CreateRootNode(ref XmlTreeNode rootNode) { rootNode.NodeType = "init" + TreeAlias; @@ -165,20 +169,20 @@ namespace umbraco private void RenderTemplates(ref XmlTree tree) { List