Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

If caching a published document, make sure you use the published Name… #11313

Merged
merged 2 commits into from
Oct 11, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 7 additions & 1 deletion src/Umbraco.Core/Strings/DefaultUrlSegmentProvider.cs
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,13 @@ private static string GetUrlSegmentSource(IContentBase content, string culture)
if (content.HasProperty(Constants.Conventions.Content.UrlName))
source = (content.GetValue<string>(Constants.Conventions.Content.UrlName, culture) ?? string.Empty).Trim();
if (string.IsNullOrWhiteSpace(source))
source = content.GetCultureName(culture);
{
// If the name of a node has been updated, but it has not been published, the url should use the published name, not the current node name
// If this node has never been published (GetPublishName is null), use the unpublished name
source = (content is IContent document) && document.Edited && document.GetPublishName(culture) != null
? document.GetPublishName(culture)
: content.GetCultureName(culture);
}
return source;
}
}
Expand Down
158 changes: 158 additions & 0 deletions src/Umbraco.Tests/PublishedContent/NuCacheRebuildTests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,158 @@
using System.Globalization;
using System.Linq;
using Moq;
using NUnit.Framework;
using Umbraco.Core;
using Umbraco.Core.Composing.CompositionExtensions;
using Umbraco.Core.Configuration.UmbracoSettings;
using Umbraco.Core.Services;
using Umbraco.Core.Dictionary;
using Umbraco.Core.Logging;
using Umbraco.Core.Models;
using Umbraco.Core.PropertyEditors;
using Umbraco.Core.Services.Implement;
using Umbraco.Tests.TestHelpers;
using Umbraco.Tests.TestHelpers.Entities;
using Umbraco.Web.Models.ContentEditing;
using Umbraco.Tests.Testing;
using Umbraco.Web.PropertyEditors;

using Current = Umbraco.Web.Composing.Current;
using Umbraco.Web.PublishedCache;
using Umbraco.Web.PublishedCache.NuCache;
using System;
using Umbraco.Core.Cache;
using Umbraco.Web.Cache;
using Umbraco.Core.Sync;
using static Umbraco.Tests.Cache.DistributedCache.DistributedCacheTests;
using static Umbraco.Tests.Integration.ContentEventsTests;
using Umbraco.Tests.Services;
using Umbraco.Core.Persistence.Repositories.Implement;
using Umbraco.Tests.Testing.Objects.Accessors;
using Umbraco.Core.Persistence.Repositories;
using Umbraco.Core.Models.PublishedContent;
using Umbraco.Core.Configuration;
using Umbraco.Web.PublishedCache.NuCache.DataSource;
using Umbraco.Core.Strings;

namespace Umbraco.Tests.PublishedContent
{
[TestFixture]
[UmbracoTest(Database = UmbracoTestOptions.Database.NewSchemaPerTest, PublishedRepositoryEvents = true, WithApplication = true)]
public class NuCacheRebuildTests: TestWithDatabaseBase
{
private IContentTypeService _contentTypeService;
private IContentType _contentType;

protected override void Initialize()
{
base.Initialize();

if (!(PublishedSnapshotService is PublishedSnapshotService))
{
var options = new PublishedSnapshotServiceOptions { IgnoreLocalDb = true };
var runtime = Mock.Of<IRuntimeState>();
PublishedSnapshotService = new PublishedSnapshotService(
options,
null,
runtime,
ServiceContext,
Factory.GetInstance<IPublishedContentTypeFactory>(),
null,
new TestPublishedSnapshotAccessor(),
new TestVariationContextAccessor(),
Mock.Of<IProfilingLogger>(),
ScopeProvider,
Factory.GetInstance<IDocumentRepository>(), Factory.GetInstance<IMediaRepository>(), Factory.GetInstance<IMemberRepository>(),
DefaultCultureAccessor,
new DatabaseDataSource(new JsonContentNestedDataSerializerFactory()),
new GlobalSettings(),
Factory.GetInstance<IEntityXmlSerializer>(),
Factory.GetInstance<IPublishedModelFactory>(),
new UrlSegmentProviderCollection(new[] { new DefaultUrlSegmentProvider() }),
new TestSyncBootStateAccessor(SyncBootState.WarmBoot),
new JsonContentNestedDataSerializerFactory()
);
}
}
public override void SetUp()
{
base.SetUp();
ContentRepositoryBase.ThrowOnWarning = true;
}

public override void TearDown()
{
ContentRepositoryBase.ThrowOnWarning = false;
base.TearDown();
}

protected override void Compose()
{
base.Compose();

Composition.RegisterUnique(factory => Mock.Of<ILocalizedTextService>());
}
[Test]
public void UnpublishedNameChanges()
{
var urlSegmentProvider = new DefaultUrlSegmentProvider();

var contentType = MockedContentTypes.CreateTextPageContentType();
ServiceContext.FileService.SaveTemplate(contentType.DefaultTemplate);
ServiceContext.ContentTypeService.Save(contentType);

var content = MockedContent.CreateTextpageContent(contentType, "hello", Constants.System.Root);

ServiceContext.ContentService.SaveAndPublish(content);
var cachedContent = ServiceContext.ContentService.GetById(content.Id);
var segment = urlSegmentProvider.GetUrlSegment(cachedContent);

// Does a new node work?

Assert.AreEqual("hello", segment);

content.Name = "goodbye";
cachedContent = ServiceContext.ContentService.GetById(content.Id);
segment = urlSegmentProvider.GetUrlSegment(cachedContent);

// We didn't save anything, so all should still be the same

Assert.AreEqual("hello", segment);

ServiceContext.ContentService.Save(content);
cachedContent = ServiceContext.ContentService.GetById(content.Id);
segment = urlSegmentProvider.GetUrlSegment(cachedContent);

// At this point we have saved the new name, but not published. The url should still be the previous name

Assert.AreEqual("hello", segment);

PublishedSnapshotService.Rebuild();

cachedContent = ServiceContext.ContentService.GetById(content.Id);
segment = urlSegmentProvider.GetUrlSegment(cachedContent);

// After a rebuild, the unpublished name should still not be the url.
// This was previously incorrect, per #11074

Assert.AreEqual("hello", segment);

ServiceContext.ContentService.SaveAndPublish(content);
cachedContent = ServiceContext.ContentService.GetById(content.Id);
segment = urlSegmentProvider.GetUrlSegment(cachedContent);

// The page has now been published, so we should see the new url segment
Assert.AreEqual("goodbye", segment);

PublishedSnapshotService.Rebuild();
cachedContent = ServiceContext.ContentService.GetById(content.Id);
segment = urlSegmentProvider.GetUrlSegment(cachedContent);

// Just double checking that things remain after a rebuild
Assert.AreEqual("goodbye", segment);

}

}
}
1 change: 1 addition & 0 deletions src/Umbraco.Tests/Umbraco.Tests.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -157,6 +157,7 @@
<Compile Include="PropertyEditors\NestedContentPropertyComponentTests.cs" />
<Compile Include="PublishedContent\ContentSerializationTests.cs" />
<Compile Include="PublishedContent\NuCacheChildrenTests.cs" />
<Compile Include="PublishedContent\NuCacheRebuildTests.cs" />
<Compile Include="PublishedContent\PublishedContentLanguageVariantTests.cs" />
<Compile Include="PublishedContent\PublishedContentSnapshotTestBase.cs" />
<Compile Include="PublishedContent\SolidPublishedSnapshot.cs" />
Expand Down