From 3d2a0b4a297912a6a8b04fda5bec6817d323f9e0 Mon Sep 17 00:00:00 2001 From: Stephan Date: Mon, 4 Jul 2016 18:22:06 +0200 Subject: [PATCH] U4-8361 - from ids to guids --- .../Configuration/UmbracoVersion.cs | 2 +- src/Umbraco.Core/Models/IRedirectUrl.cs | 19 ++++++ .../Models/Rdbms/RedirectUrlDto.cs | 9 ++- src/Umbraco.Core/Models/RedirectUrl.cs | 34 ++++++---- .../AddRedirectUrlTable2.cs | 37 +++++++++++ .../Interfaces/IRedirectUrlRepository.cs | 61 +++++++++++++++-- .../Repositories/RedirectUrlRepository.cs | 38 +++++++---- .../Services/IRedirectUrlService.cs | 58 +++++++++++++++-- .../Services/RedirectUrlService.cs | 14 ++-- src/Umbraco.Core/Umbraco.Core.csproj | 1 + .../RedirectUrlRepositoryTests.cs | 36 +++++----- .../Redirects/RedirectTrackingEventHandler.cs | 65 ++++++++++++------- 12 files changed, 289 insertions(+), 85 deletions(-) create mode 100644 src/Umbraco.Core/Persistence/Migrations/Upgrades/TargetVersionSevenFiveZero/AddRedirectUrlTable2.cs diff --git a/src/Umbraco.Core/Configuration/UmbracoVersion.cs b/src/Umbraco.Core/Configuration/UmbracoVersion.cs index 8c2fe08dfd..b09aceda56 100644 --- a/src/Umbraco.Core/Configuration/UmbracoVersion.cs +++ b/src/Umbraco.Core/Configuration/UmbracoVersion.cs @@ -24,7 +24,7 @@ namespace Umbraco.Core.Configuration /// Gets the version comment (like beta or RC). /// /// The version comment. - public static string CurrentComment { get { return "beta"; } } + public static string CurrentComment { get { return "beta2"; } } // Get the version of the umbraco.dll by looking at a class in that dll // Had to do it like this due to medium trust issues, see: http://haacked.com/archive/2010/11/04/assembly-location-and-medium-trust.aspx diff --git a/src/Umbraco.Core/Models/IRedirectUrl.cs b/src/Umbraco.Core/Models/IRedirectUrl.cs index 4f15b1e082..419389f60d 100644 --- a/src/Umbraco.Core/Models/IRedirectUrl.cs +++ b/src/Umbraco.Core/Models/IRedirectUrl.cs @@ -4,14 +4,33 @@ using Umbraco.Core.Models.EntityBase; namespace Umbraco.Core.Models { + /// + /// Represents a redirect url. + /// public interface IRedirectUrl : IAggregateRoot, IRememberBeingDirty { + /// + /// Gets or sets the identifier of the content item. + /// [DataMember] int ContentId { get; set; } + /// + /// Gets or sets the unique key identifying the content item. + /// + [DataMember] + Guid ContentKey { get; set; } + + /// + /// Gets or sets the redirect url creation date. + /// [DataMember] DateTime CreateDateUtc { get; set; } + /// + /// Gets or sets the redirect url route. + /// + /// Is a proper Umbraco route eg /path/to/foo or 123/path/tofoo. [DataMember] string Url { get; set; } } diff --git a/src/Umbraco.Core/Models/Rdbms/RedirectUrlDto.cs b/src/Umbraco.Core/Models/Rdbms/RedirectUrlDto.cs index 6ada1dca74..c417a65d99 100644 --- a/src/Umbraco.Core/Models/Rdbms/RedirectUrlDto.cs +++ b/src/Umbraco.Core/Models/Rdbms/RedirectUrlDto.cs @@ -18,11 +18,14 @@ namespace Umbraco.Core.Models.Rdbms [PrimaryKeyColumn(IdentitySeed = 1, Name = "PK_umbracoRedirectUrl")] public int Id { get; set; } - [Column("contentId")] - [NullSetting(NullSetting = NullSettings.NotNull)] - [ForeignKey(typeof(NodeDto), Column = "id")] + [ResultColumn] public int ContentId { get; set; } + [Column("contentKey")] + [NullSetting(NullSetting = NullSettings.NotNull)] + [ForeignKey(typeof(NodeDto), Column = "uniqueID")] + public Guid ContentKey { get; set; } + [Column("createDateUtc")] [NullSetting(NullSetting = NullSettings.NotNull)] public DateTime CreateDateUtc { get; set; } diff --git a/src/Umbraco.Core/Models/RedirectUrl.cs b/src/Umbraco.Core/Models/RedirectUrl.cs index 1706dd38cf..ff7746d0cf 100644 --- a/src/Umbraco.Core/Models/RedirectUrl.cs +++ b/src/Umbraco.Core/Models/RedirectUrl.cs @@ -5,10 +5,16 @@ using Umbraco.Core.Models.EntityBase; namespace Umbraco.Core.Models { + /// + /// Implements . + /// [Serializable] [DataContract(IsReference = true)] public class RedirectUrl : Entity, IRedirectUrl { + /// + /// Initializes a new instance of the class. + /// public RedirectUrl() { CreateDateUtc = DateTime.UtcNow; @@ -16,42 +22,46 @@ namespace Umbraco.Core.Models private static readonly Lazy Ps = new Lazy(); + // ReSharper disable once ClassNeverInstantiated.Local private class PropertySelectors { public readonly PropertyInfo ContentIdSelector = ExpressionHelper.GetPropertyInfo(x => x.ContentId); + public readonly PropertyInfo ContentKeySelector = ExpressionHelper.GetPropertyInfo(x => x.ContentKey); public readonly PropertyInfo CreateDateUtcSelector = ExpressionHelper.GetPropertyInfo(x => x.CreateDateUtc); public readonly PropertyInfo UrlSelector = ExpressionHelper.GetPropertyInfo(x => x.Url); } private int _contentId; + private Guid _contentKey; private DateTime _createDateUtc; private string _url; + /// public int ContentId { get { return _contentId; } - set - { - SetPropertyValueAndDetectChanges(value, ref _contentId, Ps.Value.ContentIdSelector); - } + set { SetPropertyValueAndDetectChanges(value, ref _contentId, Ps.Value.ContentIdSelector); } } + /// + public Guid ContentKey + { + get { return _contentKey; } + set { SetPropertyValueAndDetectChanges(value, ref _contentKey, Ps.Value.ContentKeySelector); } + } + + /// public DateTime CreateDateUtc { get { return _createDateUtc; } - set - { - SetPropertyValueAndDetectChanges(value, ref _createDateUtc, Ps.Value.CreateDateUtcSelector); - } + set { SetPropertyValueAndDetectChanges(value, ref _createDateUtc, Ps.Value.CreateDateUtcSelector); } } + /// public string Url { get { return _url; } - set - { - SetPropertyValueAndDetectChanges(value, ref _url, Ps.Value.UrlSelector); - } + set { SetPropertyValueAndDetectChanges(value, ref _url, Ps.Value.UrlSelector); } } } } \ No newline at end of file diff --git a/src/Umbraco.Core/Persistence/Migrations/Upgrades/TargetVersionSevenFiveZero/AddRedirectUrlTable2.cs b/src/Umbraco.Core/Persistence/Migrations/Upgrades/TargetVersionSevenFiveZero/AddRedirectUrlTable2.cs new file mode 100644 index 0000000000..418c5ded91 --- /dev/null +++ b/src/Umbraco.Core/Persistence/Migrations/Upgrades/TargetVersionSevenFiveZero/AddRedirectUrlTable2.cs @@ -0,0 +1,37 @@ +using System.Linq; +using Umbraco.Core.Configuration; +using Umbraco.Core.Logging; +using Umbraco.Core.Persistence.SqlSyntax; + +namespace Umbraco.Core.Persistence.Migrations.Upgrades.TargetVersionSevenFiveZero +{ + [Migration("7.5.0", 101, GlobalSettings.UmbracoMigrationName)] + public class AddRedirectUrlTable2 : MigrationBase + { + public AddRedirectUrlTable2(ISqlSyntaxProvider sqlSyntax, ILogger logger) + : base(sqlSyntax, logger) + { } + + public override void Up() + { + var columns = SqlSyntax.GetColumnsInSchema(Context.Database).ToArray(); + + if (columns.Any(x => x.TableName.InvariantEquals("umbracoRedirectUrl") && x.ColumnName.InvariantEquals("contentKey"))) + return; + + Execute.Sql("DELETE FROM umbracoRedirectUrl"); // else cannot add non-nullable field + + Delete.Column("contentId").FromTable("umbracoRedirectUrl"); + + Alter.Table("umbracoRedirectUrl") + .AddColumn("contentKey").AsGuid().NotNullable(); + + Create.ForeignKey("FK_umbracoRedirectUrl") + .FromTable("umbracoRedirectUrl").ForeignColumn("contentKey") + .ToTable("umbracoNode").PrimaryColumn("uniqueID"); + } + + public override void Down() + { } + } +} diff --git a/src/Umbraco.Core/Persistence/Repositories/Interfaces/IRedirectUrlRepository.cs b/src/Umbraco.Core/Persistence/Repositories/Interfaces/IRedirectUrlRepository.cs index 66c63513a4..82f2e0e516 100644 --- a/src/Umbraco.Core/Persistence/Repositories/Interfaces/IRedirectUrlRepository.cs +++ b/src/Umbraco.Core/Persistence/Repositories/Interfaces/IRedirectUrlRepository.cs @@ -1,17 +1,70 @@ -using System.Collections.Generic; +using System; +using System.Collections.Generic; using Umbraco.Core.Models; namespace Umbraco.Core.Persistence.Repositories { + /// + /// Defines the repository. + /// public interface IRedirectUrlRepository : IRepositoryQueryable { - IRedirectUrl Get(string url, int contentId); + /// + /// Gets a redirect url. + /// + /// The Umbraco redirect url route. + /// The content unique key. + /// + IRedirectUrl Get(string url, Guid contentKey); + + /// + /// Deletes a redirect url. + /// + /// The redirect url identifier. void Delete(int id); + + /// + /// Deletes all redirect urls. + /// void DeleteAll(); - void DeleteContentUrls(int contentId); + + /// + /// Deletes all redirect urls for a given content. + /// + /// The content unique key. + void DeleteContentUrls(Guid contentKey); + + /// + /// Gets the most recent redirect url corresponding to an Umbraco redirect url route. + /// + /// The Umbraco redirect url route. + /// The most recent redirect url corresponding to the route. IRedirectUrl GetMostRecentUrl(string url); - IEnumerable GetContentUrls(int contentId); + + /// + /// Gets all redirect urls for a content item. + /// + /// The content unique key. + /// All redirect urls for the content item. + IEnumerable GetContentUrls(Guid contentKey); + + /// + /// Gets all redirect urls. + /// + /// The page index. + /// The page size. + /// The total count of redirect urls. + /// The redirect urls. IEnumerable GetAllUrls(long pageIndex, int pageSize, out long total); + + /// + /// Gets all redirect urls below a given content item. + /// + /// The content unique identifier. + /// The page index. + /// The page size. + /// The total count of redirect urls. + /// The redirect urls. IEnumerable GetAllUrls(int rootContentId, long pageIndex, int pageSize, out long total); } } diff --git a/src/Umbraco.Core/Persistence/Repositories/RedirectUrlRepository.cs b/src/Umbraco.Core/Persistence/Repositories/RedirectUrlRepository.cs index 4f5a756815..5491f57f3a 100644 --- a/src/Umbraco.Core/Persistence/Repositories/RedirectUrlRepository.cs +++ b/src/Umbraco.Core/Persistence/Repositories/RedirectUrlRepository.cs @@ -50,7 +50,14 @@ namespace Umbraco.Core.Persistence.Repositories protected override Sql GetBaseQuery(bool isCount) { var sql = new Sql(); - sql.Select(isCount ? "COUNT(*)" : "*").From(SqlSyntax); + if (isCount) + sql.Select(@"COUNT(*) +FROM umbracoRedirectUrl +JOIN umbracoNode ON umbracoRedirectUrl.contentKey=umbracoNode.uniqueID"); + else + sql.Select(@"umbracoRedirectUrl.*, umbracoNode.id AS contentId +FROM umbracoRedirectUrl +JOIN umbracoNode ON umbracoRedirectUrl.contentKey=umbracoNode.uniqueID"); return sql; } @@ -93,7 +100,7 @@ namespace Umbraco.Core.Persistence.Repositories return new RedirectUrlDto { Id = redirectUrl.Id, - ContentId = redirectUrl.ContentId, + ContentKey = redirectUrl.ContentKey, CreateDateUtc = redirectUrl.CreateDateUtc, Url = redirectUrl.Url }; @@ -109,6 +116,7 @@ namespace Umbraco.Core.Persistence.Repositories url.DisableChangeTracking(); url.Id = dto.Id; url.ContentId = dto.ContentId; + url.ContentKey = dto.ContentKey; url.CreateDateUtc = dto.CreateDateUtc; url.Url = dto.Url; return url; @@ -119,9 +127,9 @@ namespace Umbraco.Core.Persistence.Repositories } } - public IRedirectUrl Get(string url, int contentId) + public IRedirectUrl Get(string url, Guid contentKey) { - var sql = GetBaseQuery(false).Where(x => x.Url == url && x.ContentId == contentId); + var sql = GetBaseQuery(false).Where(x => x.Url == url && x.ContentKey == contentKey); var dto = Database.Fetch(sql).FirstOrDefault(); return dto == null ? null : Map(dto); } @@ -131,9 +139,9 @@ namespace Umbraco.Core.Persistence.Repositories Database.Execute("DELETE FROM umbracoRedirectUrl"); } - public void DeleteContentUrls(int contentId) + public void DeleteContentUrls(Guid contentKey) { - Database.Execute("DELETE FROM umbracoRedirectUrl WHERE contentId=@contentId", new { contentId }); + Database.Execute("DELETE FROM umbracoRedirectUrl WHERE contentKey=@contentKey", new { contentKey }); } public void Delete(int id) @@ -143,22 +151,27 @@ namespace Umbraco.Core.Persistence.Repositories public IRedirectUrl GetMostRecentUrl(string url) { - var dtos = Database.Fetch("SELECT * FROM umbracoRedirectUrl WHERE url=@url ORDER BY createDateUtc DESC;", - new { url }); + var sql = GetBaseQuery(false) + .Where(x => x.Url == url) + .OrderByDescending(x => x.CreateDateUtc, SqlSyntax); + var dtos = Database.Fetch(sql); var dto = dtos.FirstOrDefault(); return dto == null ? null : Map(dto); } - public IEnumerable GetContentUrls(int contentId) + public IEnumerable GetContentUrls(Guid contentKey) { - var dtos = Database.Fetch("SELECT * FROM umbracoRedirectUrl WHERE contentId=@id ORDER BY createDateUtc DESC;", - new { id = contentId }); + var sql = GetBaseQuery(false) + .Where(x => x.ContentKey == contentKey) + .OrderByDescending(x => x.CreateDateUtc, SqlSyntax); + var dtos = Database.Fetch(sql); return dtos.Select(Map); } public IEnumerable GetAllUrls(long pageIndex, int pageSize, out long total) { - var sql = GetBaseQuery(false).OrderByDescending(x => x.CreateDateUtc, SqlSyntax); + var sql = GetBaseQuery(false) + .OrderByDescending(x => x.CreateDateUtc, SqlSyntax); var result = Database.Page(pageIndex + 1, pageSize, sql); total = Convert.ToInt32(result.TotalItems); return result.Items.Select(Map); @@ -167,7 +180,6 @@ namespace Umbraco.Core.Persistence.Repositories public IEnumerable GetAllUrls(int rootContentId, long pageIndex, int pageSize, out long total) { var sql = GetBaseQuery(false) - .InnerJoin(SqlSyntax).On(SqlSyntax, left => left.NodeId, right => right.ContentId) .Where("umbracoNode.path LIKE @path", new { path = "%," + rootContentId + ",%" }) .OrderByDescending(x => x.CreateDateUtc, SqlSyntax); var result = Database.Page(pageIndex + 1, pageSize, sql); diff --git a/src/Umbraco.Core/Services/IRedirectUrlService.cs b/src/Umbraco.Core/Services/IRedirectUrlService.cs index 554b4ed0fd..7b21fa9bb7 100644 --- a/src/Umbraco.Core/Services/IRedirectUrlService.cs +++ b/src/Umbraco.Core/Services/IRedirectUrlService.cs @@ -1,26 +1,76 @@ -using System.Collections.Generic; +using System; +using System.Collections.Generic; using Umbraco.Core.Models; namespace Umbraco.Core.Services { + /// + /// + /// public interface IRedirectUrlService : IService { - void Register(string url, int contentId); + /// + /// Registers a redirect url. + /// + /// The Umbraco url route. + /// The content unique key. + /// Is a proper Umbraco route eg /path/to/foo or 123/path/tofoo. + void Register(string url, Guid contentKey); - void DeleteContentRedirectUrls(int contentId); + /// + /// Deletes all redirect urls for a given content. + /// + /// The content unique key. + void DeleteContentRedirectUrls(Guid contentKey); + /// + /// Deletes a redirect url. + /// + /// The redirect url to delete. void Delete(IRedirectUrl redirectUrl); + /// + /// Deletes a redirect url. + /// + /// The redirect url identifier. void Delete(int id); + /// + /// Deletes all redirect urls. + /// void DeleteAll(); + /// + /// Gets the most recent redirect urls corresponding to an Umbraco redirect url route. + /// + /// The Umbraco redirect url route. + /// The most recent redirect urls corresponding to the route. IRedirectUrl GetMostRecentRedirectUrl(string url); - IEnumerable GetContentRedirectUrls(int contentId); + /// + /// Gets all redirect urls for a content item. + /// + /// The content unique key. + /// All redirect urls for the content item. + IEnumerable GetContentRedirectUrls(Guid contentKey); + /// + /// Gets all redirect urls. + /// + /// The page index. + /// The page size. + /// The total count of redirect urls. + /// The redirect urls. IEnumerable GetAllRedirectUrls(long pageIndex, int pageSize, out long total); + /// + /// Gets all redirect urls below a given content item. + /// + /// The content unique identifier. + /// The page index. + /// The page size. + /// The total count of redirect urls. + /// The redirect urls. IEnumerable GetAllRedirectUrls(int rootContentId, long pageIndex, int pageSize, out long total); } } diff --git a/src/Umbraco.Core/Services/RedirectUrlService.cs b/src/Umbraco.Core/Services/RedirectUrlService.cs index 6984942ccd..de698509d0 100644 --- a/src/Umbraco.Core/Services/RedirectUrlService.cs +++ b/src/Umbraco.Core/Services/RedirectUrlService.cs @@ -14,16 +14,16 @@ namespace Umbraco.Core.Services : base(provider, repositoryFactory, logger, eventMessagesFactory) { } - public void Register(string url, int contentId) + public void Register(string url, Guid contentKey) { using (var uow = UowProvider.GetUnitOfWork()) using (var repo = RepositoryFactory.CreateRedirectUrlRepository(uow)) { - var redir = repo.Get(url, contentId); + var redir = repo.Get(url, contentKey); if (redir != null) redir.CreateDateUtc = DateTime.UtcNow; else - redir = new RedirectUrl { Url = url, ContentId = contentId }; + redir = new RedirectUrl { Url = url, ContentKey = contentKey }; repo.AddOrUpdate(redir); uow.Commit(); } @@ -49,12 +49,12 @@ namespace Umbraco.Core.Services } } - public void DeleteContentRedirectUrls(int contentId) + public void DeleteContentRedirectUrls(Guid contentKey) { using (var uow = UowProvider.GetUnitOfWork()) using (var repo = RepositoryFactory.CreateRedirectUrlRepository(uow)) { - repo.DeleteContentUrls(contentId); + repo.DeleteContentUrls(contentKey); uow.Commit(); } } @@ -80,12 +80,12 @@ namespace Umbraco.Core.Services } } - public IEnumerable GetContentRedirectUrls(int contentId) + public IEnumerable GetContentRedirectUrls(Guid contentKey) { using (var uow = UowProvider.GetUnitOfWork()) using (var repo = RepositoryFactory.CreateRedirectUrlRepository(uow)) { - var rules = repo.GetContentUrls(contentId); + var rules = repo.GetContentUrls(contentKey); uow.Commit(); return rules; } diff --git a/src/Umbraco.Core/Umbraco.Core.csproj b/src/Umbraco.Core/Umbraco.Core.csproj index a5e93b53c7..61dc768c43 100644 --- a/src/Umbraco.Core/Umbraco.Core.csproj +++ b/src/Umbraco.Core/Umbraco.Core.csproj @@ -426,6 +426,7 @@ + diff --git a/src/Umbraco.Tests/Persistence/Repositories/RedirectUrlRepositoryTests.cs b/src/Umbraco.Tests/Persistence/Repositories/RedirectUrlRepositoryTests.cs index c511ed21da..dd3065e6d9 100644 --- a/src/Umbraco.Tests/Persistence/Repositories/RedirectUrlRepositoryTests.cs +++ b/src/Umbraco.Tests/Persistence/Repositories/RedirectUrlRepositoryTests.cs @@ -37,7 +37,7 @@ namespace Umbraco.Tests.Persistence.Repositories { var rurl = new RedirectUrl { - ContentId = _textpage.Id, + ContentKey = _textpage.Key, Url = "blah" }; repo.AddOrUpdate(rurl); @@ -67,7 +67,7 @@ namespace Umbraco.Tests.Persistence.Repositories { var rurl = new RedirectUrl { - ContentId = _textpage.Id, + ContentKey = _textpage.Key, Url = "blah" }; repo.AddOrUpdate(rurl); @@ -77,7 +77,7 @@ namespace Umbraco.Tests.Persistence.Repositories rurl = new RedirectUrl { - ContentId = _otherpage.Id, + ContentKey = _otherpage.Key, Url = "blah" }; repo.AddOrUpdate(rurl); @@ -107,7 +107,7 @@ namespace Umbraco.Tests.Persistence.Repositories { var rurl = new RedirectUrl { - ContentId = _textpage.Id, + ContentKey = _textpage.Key, Url = "blah" }; repo.AddOrUpdate(rurl); @@ -117,7 +117,7 @@ namespace Umbraco.Tests.Persistence.Repositories rurl = new RedirectUrl { - ContentId = _textpage.Id, + ContentKey = _textpage.Key, Url = "durg" }; repo.AddOrUpdate(rurl); @@ -129,7 +129,7 @@ namespace Umbraco.Tests.Persistence.Repositories using (var uow = provider.GetUnitOfWork()) using (var repo = CreateRepository(uow)) { - var rurls = repo.GetContentUrls(_textpage.Id).ToArray(); + var rurls = repo.GetContentUrls(_textpage.Key).ToArray(); uow.Commit(); Assert.AreEqual(2, rurls.Length); @@ -148,7 +148,7 @@ namespace Umbraco.Tests.Persistence.Repositories { var rurl = new RedirectUrl { - ContentId = _textpage.Id, + ContentKey = _textpage.Key, Url = "blah" }; repo.AddOrUpdate(rurl); @@ -158,7 +158,7 @@ namespace Umbraco.Tests.Persistence.Repositories rurl = new RedirectUrl { - ContentId = _otherpage.Id, + ContentKey = _otherpage.Key, Url = "durg" }; repo.AddOrUpdate(rurl); @@ -170,10 +170,10 @@ namespace Umbraco.Tests.Persistence.Repositories using (var uow = provider.GetUnitOfWork()) using (var repo = CreateRepository(uow)) { - repo.DeleteContentUrls(_textpage.Id); + repo.DeleteContentUrls(_textpage.Key); uow.Commit(); - var rurls = repo.GetContentUrls(_textpage.Id); + var rurls = repo.GetContentUrls(_textpage.Key); Assert.AreEqual(0, rurls.Count()); } @@ -190,27 +190,29 @@ namespace Umbraco.Tests.Persistence.Repositories { //Create and Save ContentType "umbTextpage" -> (NodeDto.NodeIdSeed) var contentType = MockedContentTypes.CreateSimpleContentType("umbTextpage", "Textpage"); - contentType.Key = new Guid("1D3A8E6E-2EA9-4CC1-B229-1AEE19821522"); + contentType.Key = Guid.NewGuid(); ServiceContext.ContentTypeService.Save(contentType); //Create and Save Content "Homepage" based on "umbTextpage" -> (NodeDto.NodeIdSeed + 1) _textpage = MockedContent.CreateSimpleContent(contentType); - _textpage.Key = new Guid("B58B3AD4-62C2-4E27-B1BE-837BD7C533E0"); - ServiceContext.ContentService.Save(_textpage, 0); + _textpage.Key = Guid.NewGuid(); + ServiceContext.ContentService.Save(_textpage); //Create and Save Content "Text Page 1" based on "umbTextpage" -> (NodeDto.NodeIdSeed + 2) _subpage = MockedContent.CreateSimpleContent(contentType, "Text Page 1", _textpage.Id); - _subpage.Key = new Guid("FF11402B-7E53-4654-81A7-462AC2108059"); - ServiceContext.ContentService.Save(_subpage, 0); + _subpage.Key = Guid.NewGuid(); + ServiceContext.ContentService.Save(_subpage); //Create and Save Content "Text Page 1" based on "umbTextpage" -> (NodeDto.NodeIdSeed + 3) _otherpage = MockedContent.CreateSimpleContent(contentType, "Text Page 2", _textpage.Id); - ServiceContext.ContentService.Save(_otherpage, 0); + _otherpage.Key = Guid.NewGuid(); + ServiceContext.ContentService.Save(_otherpage); //Create and Save Content "Text Page Deleted" based on "umbTextpage" -> (NodeDto.NodeIdSeed + 4) _trashed = MockedContent.CreateSimpleContent(contentType, "Text Page Deleted", -20); + _trashed.Key = Guid.NewGuid(); ((Content) _trashed).Trashed = true; - ServiceContext.ContentService.Save(_trashed, 0); + ServiceContext.ContentService.Save(_trashed); } } } diff --git a/src/Umbraco.Web/Redirects/RedirectTrackingEventHandler.cs b/src/Umbraco.Web/Redirects/RedirectTrackingEventHandler.cs index 60018d73c8..6ba60b3891 100644 --- a/src/Umbraco.Web/Redirects/RedirectTrackingEventHandler.cs +++ b/src/Umbraco.Web/Redirects/RedirectTrackingEventHandler.cs @@ -8,24 +8,27 @@ using Umbraco.Web.Routing; using System.Collections.Generic; using System.Linq; using Umbraco.Core.Cache; +using Umbraco.Core.Logging; +using Umbraco.Core.Models.PublishedContent; using Umbraco.Web.Cache; namespace Umbraco.Web.Redirects { - // when content is renamed or moved, we want to create a permanent 301 redirect from it's old url - // - // not managing domains because we don't know how to do it - // changing domains => must create a higher level strategy using rewriting rules probably - // - // recycle bin = moving to and from does nothing - // to = the node is gone, where would we redirect? from = same - // + /// + /// Implements an Application Event Handler for managing redirect urls tracking. + /// + /// + /// when content is renamed or moved, we want to create a permanent 301 redirect from it's old url + /// not managing domains because we don't know how to do it - changing domains => must create a higher level strategy using rewriting rules probably + /// recycle bin = moving to and from does nothing: to = the node is gone, where would we redirect? from = same + /// public class RedirectTrackingEventHandler : ApplicationEventHandler { private const string ContextKey1 = "Umbraco.Web.Redirects.RedirectTrackingEventHandler.1"; private const string ContextKey2 = "Umbraco.Web.Redirects.RedirectTrackingEventHandler.2"; private const string ContextKey3 = "Umbraco.Web.Redirects.RedirectTrackingEventHandler.3"; + /// protected override void ApplicationStarting(UmbracoApplicationBase umbracoApplication, ApplicationContext applicationContext) { // if any of these dlls are loaded we don't want to run our finder @@ -40,17 +43,15 @@ namespace Umbraco.Web.Redirects }; // assuming all assemblies have been loaded already - foreach (var assembly in AppDomain.CurrentDomain.GetAssemblies()) - { - var name = assembly.FullName.Split(',')[0]; - if (dlls.Contains(name)) - { - ContentFinderResolver.Current.RemoveType(); - return; - } - } + // check if any of them matches one of the above dlls + var found = AppDomain.CurrentDomain.GetAssemblies() + .Select(x => x.FullName.Split(',')[0]) + .Any(x => dlls.Contains(x)); + if (found) + ContentFinderResolver.Current.RemoveType(); } + /// protected override void ApplicationStarted(UmbracoApplicationBase umbracoApplication, ApplicationContext applicationContext) { // events are weird @@ -78,13 +79,13 @@ namespace Umbraco.Web.Redirects // rolled back items have to be published, so publishing will take care of that } - private static Dictionary OldRoutes + private static Dictionary> OldRoutes { get { - var oldRoutes = (Dictionary) UmbracoContext.Current.HttpContext.Items[ContextKey3]; + var oldRoutes = (Dictionary>) UmbracoContext.Current.HttpContext.Items[ContextKey3]; if (oldRoutes == null) - UmbracoContext.Current.HttpContext.Items[ContextKey3] = oldRoutes = new Dictionary(); + UmbracoContext.Current.HttpContext.Items[ContextKey3] = oldRoutes = new Dictionary>(); return oldRoutes; } } @@ -129,13 +130,29 @@ namespace Umbraco.Web.Redirects { var route = contentCache.GetRouteById(x.Id); if (IsNotRoute(route)) continue; - OldRoutes[x.Id] = route; + var wk = UnwrapToKey(x); + if (wk == null) continue; + OldRoutes[x.Id] = Tuple.Create(wk.Key, route); } } LockedEvents = true; // we only want to see the "first batch" } + private static IPublishedContentWithKey UnwrapToKey(IPublishedContent content) + { + if (content == null) return null; + var withKey = content as IPublishedContentWithKey; + if (withKey != null) return withKey; + + var extended = content as PublishedContentExtended; + while (extended != null) + extended = (content = extended.Unwrap()) as PublishedContentExtended; + + withKey = content as IPublishedContentWithKey; + return withKey; + } + private void PageCacheRefresher_CacheUpdated(PageCacheRefresher sender, CacheRefresherEventArgs cacheRefresherEventArgs) { var removeKeys = new List(); @@ -144,7 +161,7 @@ namespace Umbraco.Web.Redirects { // assuming we cannot have 'CacheUpdated' for only part of the infos else we'd need // to set a flag in 'Published' to indicate which entities have been refreshed ok - CreateRedirect(oldRoute.Key, oldRoute.Value); + CreateRedirect(oldRoute.Key, oldRoute.Value.Item1, oldRoute.Value.Item2); removeKeys.Add(oldRoute.Key); } @@ -169,13 +186,13 @@ namespace Umbraco.Web.Redirects LockedEvents = false; } - private static void CreateRedirect(int contentId, string oldRoute) + private static void CreateRedirect(int contentId, Guid contentKey, string oldRoute) { var contentCache = UmbracoContext.Current.ContentCache; var newRoute = contentCache.GetRouteById(contentId); if (IsNotRoute(newRoute) || oldRoute == newRoute) return; var redirectUrlService = ApplicationContext.Current.Services.RedirectUrlService; - redirectUrlService.Register(oldRoute, contentId); + redirectUrlService.Register(oldRoute, contentKey); } private static bool IsNotRoute(string route)