diff --git a/src/Umbraco.Core/Models/ServerRegistration.cs b/src/Umbraco.Core/Models/ServerRegistration.cs index dd352c2c86..c5741a74fc 100644 --- a/src/Umbraco.Core/Models/ServerRegistration.cs +++ b/src/Umbraco.Core/Models/ServerRegistration.cs @@ -6,6 +6,100 @@ using Umbraco.Core.Sync; namespace Umbraco.Core.Models { + internal class Macro : Entity, IAggregateRoot + { + /// + /// Creates an item with pre-filled properties + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + public Macro(int id, bool useInEditor, int refreshRate, string @alias, string name, string controlType, string controlAssembly, string xsltPath, bool cacheByPage, bool cachePersonalized, bool dontRender, string scriptPath) + { + Id = id; + UseInEditor = useInEditor; + RefreshRate = refreshRate; + Alias = alias; + Name = name; + ControlType = controlType; + ControlAssembly = controlAssembly; + XsltPath = xsltPath; + CacheByPage = cacheByPage; + CachePersonalized = cachePersonalized; + DontRender = dontRender; + ScriptPath = scriptPath; + } + + /// + /// Creates an instance for persisting a new item + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + public Macro(string @alias, string name, + string controlType = "", + string controlAssembly = "", + string xsltPath = "", + string scriptPath = "", + bool cacheByPage = false, + bool cachePersonalized = false, + bool dontRender = true, + bool useInEditor = false, + int refreshRate = 0) + { + UseInEditor = useInEditor; + RefreshRate = refreshRate; + Alias = alias; + Name = name; + ControlType = controlType; + ControlAssembly = controlAssembly; + XsltPath = xsltPath; + CacheByPage = cacheByPage; + CachePersonalized = cachePersonalized; + DontRender = dontRender; + ScriptPath = scriptPath; + } + + public bool UseInEditor { get; set; } + + public int RefreshRate { get; set; } + + public string Alias { get; set; } + + public string Name { get; set; } + + public string ControlType { get; set; } + + public string ControlAssembly { get; set; } + + public string XsltPath { get; set; } + + public bool CacheByPage { get; set; } + + public bool CachePersonalized { get; set; } + + public bool DontRender { get; set; } + + public string ScriptPath { get; set; } + } + internal class ServerRegistration : Entity, IServerAddress, IAggregateRoot { private string _serverAddress; diff --git a/src/Umbraco.Core/Persistence/Factories/MacroFactory.cs b/src/Umbraco.Core/Persistence/Factories/MacroFactory.cs new file mode 100644 index 0000000000..1a64ef7cf5 --- /dev/null +++ b/src/Umbraco.Core/Persistence/Factories/MacroFactory.cs @@ -0,0 +1,44 @@ +using System.Globalization; +using Umbraco.Core.Models; +using Umbraco.Core.Models.Rdbms; + +namespace Umbraco.Core.Persistence.Factories +{ + internal class MacroFactory : IEntityFactory + { + #region Implementation of IEntityFactory + + public Macro BuildEntity(MacroDto dto) + { + var model = new Macro(dto.Id, dto.UseInEditor, dto.RefreshRate, dto.Alias, dto.Name, dto.ScriptType, dto.ScriptAssembly, dto.Xslt, dto.CacheByPage, dto.CachePersonalized, dto.DontRender, dto.Python); + //on initial construction we don't want to have dirty properties tracked + // http://issues.umbraco.org/issue/U4-1946 + model.ResetDirtyProperties(false); + return model; + } + + public MacroDto BuildDto(Macro entity) + { + var dto = new MacroDto() + { + Alias = entity.Alias, + CacheByPage = entity.CacheByPage, + CachePersonalized = entity.CachePersonalized, + DontRender = entity.DontRender, + Name = entity.Name, + Python = entity.ScriptPath, + RefreshRate = entity.RefreshRate, + ScriptAssembly = entity.ControlAssembly, + ScriptType = entity.ControlType, + UseInEditor = entity.UseInEditor, + Xslt = entity.XsltPath + }; + if (entity.HasIdentity) + dto.Id = short.Parse(entity.Id.ToString(CultureInfo.InvariantCulture)); + + return dto; + } + + #endregion + } +} \ No newline at end of file diff --git a/src/Umbraco.Core/Persistence/Factories/ServerRegistrationFactory.cs b/src/Umbraco.Core/Persistence/Factories/ServerRegistrationFactory.cs index fc065102e0..d8ddc1fc70 100644 --- a/src/Umbraco.Core/Persistence/Factories/ServerRegistrationFactory.cs +++ b/src/Umbraco.Core/Persistence/Factories/ServerRegistrationFactory.cs @@ -4,7 +4,6 @@ using Umbraco.Core.Models.Rdbms; namespace Umbraco.Core.Persistence.Factories { - internal class ServerRegistrationFactory : IEntityFactory { #region Implementation of IEntityFactory diff --git a/src/Umbraco.Core/Persistence/Mappers/MacroMapper.cs b/src/Umbraco.Core/Persistence/Mappers/MacroMapper.cs new file mode 100644 index 0000000000..5db94eaf12 --- /dev/null +++ b/src/Umbraco.Core/Persistence/Mappers/MacroMapper.cs @@ -0,0 +1,44 @@ +using System.Collections.Concurrent; +using Umbraco.Core.Models; +using Umbraco.Core.Models.Rdbms; + +namespace Umbraco.Core.Persistence.Mappers +{ + [MapperFor(typeof(Macro))] + internal sealed class MacroMapper : BaseMapper + { + private static readonly ConcurrentDictionary PropertyInfoCacheInstance = new ConcurrentDictionary(); + + //NOTE: its an internal class but the ctor must be public since we're using Activator.CreateInstance to create it + // otherwise that would fail because there is no public constructor. + public MacroMapper() + { + BuildMap(); + } + + #region Overrides of BaseMapper + + internal override ConcurrentDictionary PropertyInfoCache + { + get { return PropertyInfoCacheInstance; } + } + + internal override void BuildMap() + { + CacheMap(src => src.Id, dto => dto.Id); + CacheMap(src => src.Alias, dto => dto.Alias); + CacheMap(src => src.CacheByPage, dto => dto.CacheByPage); + CacheMap(src => src.CachePersonalized, dto => dto.CachePersonalized); + CacheMap(src => src.ControlAssembly, dto => dto.ScriptAssembly); + CacheMap(src => src.ControlType, dto => dto.ScriptType); + CacheMap(src => src.DontRender, dto => dto.DontRender); + CacheMap(src => src.Name, dto => dto.Name); + CacheMap(src => src.RefreshRate, dto => dto.RefreshRate); + CacheMap(src => src.ScriptPath, dto => dto.Python); + CacheMap(src => src.UseInEditor, dto => dto.UseInEditor); + CacheMap(src => src.XsltPath, dto => dto.Xslt); + } + + #endregion + } +} \ No newline at end of file diff --git a/src/Umbraco.Core/Persistence/Repositories/MacroRepository.cs b/src/Umbraco.Core/Persistence/Repositories/MacroRepository.cs new file mode 100644 index 0000000000..f0ed6ae0fb --- /dev/null +++ b/src/Umbraco.Core/Persistence/Repositories/MacroRepository.cs @@ -0,0 +1,128 @@ +using System; +using System.Collections.Generic; +using System.Linq; +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.UnitOfWork; + +namespace Umbraco.Core.Persistence.Repositories +{ + internal class MacroRepository : PetaPocoRepositoryBase + { + public MacroRepository(IDatabaseUnitOfWork work) : base(work) + { + } + + public MacroRepository(IDatabaseUnitOfWork work, IRepositoryCacheProvider cache) : base(work, cache) + { + } + + protected override Macro PerformGet(int id) + { + var sql = GetBaseQuery(false); + sql.Where(GetBaseWhereClause(), new { Id = id }); + + var macroDto = Database.First(sql); + if (macroDto == null) + return null; + + var factory = new MacroFactory(); + var entity = factory.BuildEntity(macroDto); + + //on initial construction we don't want to have dirty properties tracked + // http://issues.umbraco.org/issue/U4-1946 + entity.ResetDirtyProperties(false); + + return entity; + } + + protected override IEnumerable PerformGetAll(params int[] ids) + { + if (ids.Any()) + { + foreach (var id in ids) + { + yield return Get(id); + } + } + else + { + var macroDtos = Database.Fetch("WHERE id > 0"); + foreach (var macroDto in macroDtos) + { + yield return Get(macroDto.Id); + } + } + } + + protected override IEnumerable PerformGetByQuery(IQuery query) + { + 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); + } + } + + protected override Sql GetBaseQuery(bool isCount) + { + var sql = new Sql(); + sql.Select(isCount ? "COUNT(*)" : "*") + .From(); + return sql; + } + + protected override string GetBaseWhereClause() + { + return "id = @Id"; + } + + protected override IEnumerable GetDeleteClauses() + { + var list = new List + { + "DELETE FROM cmsMacro WHERE id = @Id" + }; + return list; + } + + protected override Guid NodeObjectTypeId + { + get { throw new NotImplementedException(); } + } + + protected override void PersistNewItem(Macro entity) + { + ((Entity)entity).AddingEntity(); + + var factory = new MacroFactory(); + var dto = factory.BuildDto(entity); + + var id = Convert.ToInt32(Database.Insert(dto)); + entity.Id = id; + + ((ICanBeDirty)entity).ResetDirtyProperties(); + } + + protected override void PersistUpdatedItem(Macro entity) + { + ((Entity)entity).UpdatingEntity(); + + var factory = new MacroFactory(); + var dto = factory.BuildDto(entity); + + Database.Update(dto); + + ((ICanBeDirty)entity).ResetDirtyProperties(); + } + } +} \ 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 f4abb60ffd..f2df870e02 100644 --- a/src/Umbraco.Core/Persistence/Repositories/ServerRegistrationRepository.cs +++ b/src/Umbraco.Core/Persistence/Repositories/ServerRegistrationRepository.cs @@ -11,7 +11,6 @@ using Umbraco.Core.Persistence.UnitOfWork; namespace Umbraco.Core.Persistence.Repositories { - internal class ServerRegistrationRepository : PetaPocoRepositoryBase { public ServerRegistrationRepository(IDatabaseUnitOfWork work) diff --git a/src/Umbraco.Core/Umbraco.Core.csproj b/src/Umbraco.Core/Umbraco.Core.csproj index a0f7f0af55..7b4f5f2baa 100644 --- a/src/Umbraco.Core/Umbraco.Core.csproj +++ b/src/Umbraco.Core/Umbraco.Core.csproj @@ -374,6 +374,7 @@ + @@ -394,7 +395,10 @@ + + + diff --git a/src/Umbraco.Tests/Persistence/Repositories/ServerRegistrationRepositoryTest.cs b/src/Umbraco.Tests/Persistence/Repositories/ServerRegistrationRepositoryTest.cs index ef1bda3c5c..fbd5bb30a1 100644 --- a/src/Umbraco.Tests/Persistence/Repositories/ServerRegistrationRepositoryTest.cs +++ b/src/Umbraco.Tests/Persistence/Repositories/ServerRegistrationRepositoryTest.cs @@ -10,6 +10,269 @@ using Umbraco.Tests.TestHelpers; namespace Umbraco.Tests.Persistence.Repositories { + [TestFixture] + public class MacroRepositoryTest : BaseDatabaseFactoryTest + { + [SetUp] + public override void Initialize() + { + base.Initialize(); + + CreateTestData(); + } + + [Test] + public void Cannot_Add_Duplicate_Macros() + { + // Arrange + var provider = new PetaPocoUnitOfWorkProvider(); + var unitOfWork = provider.GetUnitOfWork(); + + // Act + using (var repository = new MacroRepository(unitOfWork)) + { + var macro = new Macro("test", "Test", "~/usercontrol/blah.ascx", "MyAssembly", "test.xslt", "~/views/macropartials/test.cshtml"); + repository.AddOrUpdate(macro); + + Assert.Throws(unitOfWork.Commit); + } + + } + + [Test] + public void Cannot_Update_To_Duplicate_Macro_Alias() + { + // Arrange + var provider = new PetaPocoUnitOfWorkProvider(); + var unitOfWork = provider.GetUnitOfWork(); + + // Act + using (var repository = new MacroRepository(unitOfWork)) + { + var macro = repository.Get(1); + macro.Alias = "test1"; + repository.AddOrUpdate(macro); + Assert.Throws(unitOfWork.Commit); + } + + } + + [Test] + public void Can_Instantiate_Repository() + { + // Arrange + var provider = new PetaPocoUnitOfWorkProvider(); + var unitOfWork = provider.GetUnitOfWork(); + + // Act + using (var repository = new MacroRepository(unitOfWork)) + { + // Assert + Assert.That(repository, Is.Not.Null); + } + } + + [Test] + public void Can_Perform_Get_On_Repository() + { + // Arrange + var provider = new PetaPocoUnitOfWorkProvider(); + var unitOfWork = provider.GetUnitOfWork(); + using (var repository = new MacroRepository(unitOfWork)) + { + // Act + var macro = repository.Get(1); + + // Assert + Assert.That(macro, Is.Not.Null); + Assert.That(macro.HasIdentity, Is.True); + Assert.That(macro.Alias, Is.EqualTo("test1")); + Assert.That(macro.CacheByPage, Is.EqualTo(false)); + Assert.That(macro.CachePersonalized, Is.EqualTo(false)); + Assert.That(macro.ControlAssembly, Is.EqualTo("MyAssembly1")); + Assert.That(macro.ControlType, Is.EqualTo("~/usercontrol/test1.ascx")); + Assert.That(macro.DontRender, Is.EqualTo(true)); + Assert.That(macro.Name, Is.EqualTo("Test1")); + Assert.That(macro.RefreshRate, Is.EqualTo(0)); + Assert.That(macro.ScriptPath, Is.EqualTo("~/views/macropartials/test1.cshtml")); + Assert.That(macro.UseInEditor, Is.EqualTo(false)); + Assert.That(macro.XsltPath, Is.EqualTo("test1.xslt")); + } + + + } + + [Test] + public void Can_Perform_GetAll_On_Repository() + { + // Arrange + var provider = new PetaPocoUnitOfWorkProvider(); + var unitOfWork = provider.GetUnitOfWork(); + using (var repository = new MacroRepository(unitOfWork)) + { + // Act + var macros = repository.GetAll(); + + // Assert + Assert.That(macros.Count(), Is.EqualTo(3)); + } + + } + + [Test] + public void Can_Perform_GetByQuery_On_Repository() + { + // Arrange + var provider = new PetaPocoUnitOfWorkProvider(); + var unitOfWork = provider.GetUnitOfWork(); + using (var repository = new MacroRepository(unitOfWork)) + { + // Act + var query = Query.Builder.Where(x => x.Alias.ToUpper() == "TEST1"); + var result = repository.GetByQuery(query); + + // Assert + Assert.AreEqual(1, result.Count()); + } + } + + [Test] + public void Can_Perform_Count_On_Repository() + { + // Arrange + var provider = new PetaPocoUnitOfWorkProvider(); + var unitOfWork = provider.GetUnitOfWork(); + using (var repository = new MacroRepository(unitOfWork)) + { + // Act + var query = Query.Builder.Where(x => x.Name.StartsWith("Test")); + int count = repository.Count(query); + + // Assert + Assert.That(count, Is.EqualTo(2)); + } + } + + [Test] + public void Can_Perform_Add_On_Repository() + { + // Arrange + var provider = new PetaPocoUnitOfWorkProvider(); + var unitOfWork = provider.GetUnitOfWork(); + using (var repository = new MacroRepository(unitOfWork)) + { + // Act + var macro = new Macro("test", "Test", "~/usercontrol/blah.ascx", "MyAssembly", "test.xslt", "~/views/macropartials/test.cshtml"); + repository.AddOrUpdate(macro); + unitOfWork.Commit(); + + // Assert + Assert.That(macro.HasIdentity, Is.True); + Assert.That(macro.Id, Is.EqualTo(4));//With 3 existing entries the Id should be 4 + } + } + + [Test] + public void Can_Perform_Update_On_Repository() + { + // Arrange + var provider = new PetaPocoUnitOfWorkProvider(); + var unitOfWork = provider.GetUnitOfWork(); + using (var repository = new MacroRepository(unitOfWork)) + { + // Act + var macro = repository.Get(2); + macro.Name = "Hello"; + macro.RefreshRate = 1234; + macro.CacheByPage = true; + macro.CachePersonalized = true; + macro.ControlAssembly = ""; + macro.ControlType = ""; + macro.DontRender = false; + macro.ScriptPath = "~/newpath.cshtml"; + macro.UseInEditor = true; + macro.XsltPath = ""; + + repository.AddOrUpdate(macro); + unitOfWork.Commit(); + + var macroUpdated = repository.Get(2); + + // Assert + Assert.That(macroUpdated, Is.Not.Null); + Assert.That(macroUpdated.Name, Is.EqualTo("Hello")); + Assert.That(macroUpdated.RefreshRate, Is.EqualTo(1234)); + Assert.That(macroUpdated.CacheByPage, Is.EqualTo(true)); + Assert.That(macroUpdated.CachePersonalized, Is.EqualTo(true)); + Assert.That(macroUpdated.ControlAssembly, Is.EqualTo("")); + Assert.That(macroUpdated.ControlType, Is.EqualTo("")); + Assert.That(macroUpdated.DontRender, Is.EqualTo(false)); + Assert.That(macroUpdated.ScriptPath, Is.EqualTo("~/newpath.cshtml")); + Assert.That(macroUpdated.UseInEditor, Is.EqualTo(true)); + Assert.That(macroUpdated.XsltPath, Is.EqualTo("")); + } + } + + [Test] + public void Can_Perform_Delete_On_Repository() + { + // Arrange + var provider = new PetaPocoUnitOfWorkProvider(); + var unitOfWork = provider.GetUnitOfWork(); + using (var repository = new MacroRepository(unitOfWork)) + { + // Act + var macro = repository.Get(3); + Assert.IsNotNull(macro); + repository.Delete(macro); + unitOfWork.Commit(); + + var exists = repository.Exists(3); + + // Assert + Assert.That(exists, Is.False); + } + } + + [Test] + public void Can_Perform_Exists_On_Repository() + { + // Arrange + var provider = new PetaPocoUnitOfWorkProvider(); + var unitOfWork = provider.GetUnitOfWork(); + using (var repository = new MacroRepository(unitOfWork)) + { + // Act + var exists = repository.Exists(3); + var doesntExist = repository.Exists(10); + + // Assert + Assert.That(exists, Is.True); + Assert.That(doesntExist, Is.False); + } + } + + [TearDown] + public override void TearDown() + { + base.TearDown(); + } + + public void CreateTestData() + { + var provider = new PetaPocoUnitOfWorkProvider(); + using (var unitOfWork = provider.GetUnitOfWork()) + using (var repository = new MacroRepository(unitOfWork)) + { + 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")); + repository.AddOrUpdate(new Macro("test3", "Test3", "~/usercontrol/test3.ascx", "MyAssembly3", "test3.xslt", "~/views/macropartials/test3.cshtml")); + unitOfWork.Commit(); + } + + } + } + [TestFixture] public class ServerRegistrationRepositoryTest : BaseDatabaseFactoryTest {