From ccd02cf2a99c37b9f314f74bd55370231f7d1be8 Mon Sep 17 00:00:00 2001 From: Matthew Care Date: Wed, 9 Oct 2024 08:39:22 +0200 Subject: [PATCH 1/8] Fix internal class being returned from media cache service (#17213) * update backoffice submodule * update backoffice submodule * Fix internal class being returned from media cache service Return the correct models from the media cache service --------- Co-authored-by: Jacob Overgaard <752371+iOvergaard@users.noreply.github.com> --- .../Services/MediaCacheService.cs | 15 ++++++++++----- src/Umbraco.Web.UI.Client | 2 +- 2 files changed, 11 insertions(+), 6 deletions(-) diff --git a/src/Umbraco.PublishedCache.HybridCache/Services/MediaCacheService.cs b/src/Umbraco.PublishedCache.HybridCache/Services/MediaCacheService.cs index 78e456dbf0..e100917346 100644 --- a/src/Umbraco.PublishedCache.HybridCache/Services/MediaCacheService.cs +++ b/src/Umbraco.PublishedCache.HybridCache/Services/MediaCacheService.cs @@ -1,4 +1,4 @@ -using Microsoft.Extensions.Caching.Hybrid; +using Microsoft.Extensions.Caching.Hybrid; using Microsoft.Extensions.Options; using Umbraco.Cms.Core; using Umbraco.Cms.Core.Models; @@ -8,6 +8,7 @@ using Umbraco.Cms.Core.Services; using Umbraco.Cms.Infrastructure.HybridCache.Factories; using Umbraco.Cms.Infrastructure.HybridCache.Persistence; using Umbraco.Cms.Infrastructure.HybridCache.Serialization; +using Umbraco.Extensions; namespace Umbraco.Cms.Infrastructure.HybridCache.Services; @@ -20,6 +21,7 @@ internal class MediaCacheService : IMediaCacheService private readonly IPublishedContentFactory _publishedContentFactory; private readonly ICacheNodeFactory _cacheNodeFactory; private readonly IEnumerable _seedKeyProviders; + private readonly IPublishedModelFactory _publishedModelFactory; private readonly CacheSettings _cacheSettings; private HashSet? _seedKeys; @@ -51,6 +53,7 @@ internal class MediaCacheService : IMediaCacheService IPublishedContentFactory publishedContentFactory, ICacheNodeFactory cacheNodeFactory, IEnumerable seedKeyProviders, + IPublishedModelFactory publishedModelFactory, IOptions cacheSettings) { _databaseCacheRepository = databaseCacheRepository; @@ -60,6 +63,7 @@ internal class MediaCacheService : IMediaCacheService _publishedContentFactory = publishedContentFactory; _cacheNodeFactory = cacheNodeFactory; _seedKeyProviders = seedKeyProviders; + _publishedModelFactory = publishedModelFactory; _cacheSettings = cacheSettings.Value; } @@ -78,7 +82,7 @@ internal class MediaCacheService : IMediaCacheService async cancel => await _databaseCacheRepository.GetMediaSourceAsync(idAttempt.Result)); scope.Complete(); - return contentCacheNode is null ? null : _publishedContentFactory.ToIPublishedMedia(contentCacheNode); + return contentCacheNode is null ? null : _publishedContentFactory.ToIPublishedMedia(contentCacheNode).CreateModel(_publishedModelFactory); } public async Task GetByIdAsync(int id) @@ -94,7 +98,7 @@ internal class MediaCacheService : IMediaCacheService $"{keyAttempt.Result}", // Unique key to the cache entry async cancel => await _databaseCacheRepository.GetMediaSourceAsync(id)); scope.Complete(); - return contentCacheNode is null ? null : _publishedContentFactory.ToIPublishedMedia(contentCacheNode); + return contentCacheNode is null ? null : _publishedContentFactory.ToIPublishedMedia(contentCacheNode).CreateModel(_publishedModelFactory); } public async Task HasContentByIdAsync(int id) @@ -144,7 +148,7 @@ internal class MediaCacheService : IMediaCacheService foreach (Guid key in SeedKeys) { - if(cancellationToken.IsCancellationRequested) + if (cancellationToken.IsCancellationRequested) { break; } @@ -187,7 +191,8 @@ internal class MediaCacheService : IMediaCacheService private HybridCacheEntryOptions GetSeedEntryOptions() => new() { - Expiration = _cacheSettings.SeedCacheDuration, LocalCacheExpiration = _cacheSettings.SeedCacheDuration, + Expiration = _cacheSettings.SeedCacheDuration, + LocalCacheExpiration = _cacheSettings.SeedCacheDuration, }; private string GetCacheKey(Guid key, bool preview) => preview ? $"{key}+draft" : $"{key}"; diff --git a/src/Umbraco.Web.UI.Client b/src/Umbraco.Web.UI.Client index 7d5d6558e3..00e5576244 160000 --- a/src/Umbraco.Web.UI.Client +++ b/src/Umbraco.Web.UI.Client @@ -1 +1 @@ -Subproject commit 7d5d6558e3532f18d1220983e11ee19fceea745d +Subproject commit 00e5576244a11e0fc1ea9aa2b79d3deba04e1609 From 421a3a9bd97578648eb0d1de6ef5891b44e1e312 Mon Sep 17 00:00:00 2001 From: Jason Prothero Date: Fri, 11 Oct 2024 12:37:07 -0700 Subject: [PATCH 2/8] Fix stylecop errors with function parameters on separate lines --- .../Builders/Extensions/BuilderExtensions.cs | 3 +-- .../Umbraco.Tests.Common/Builders/MediaTypeEditingBuilder.cs | 5 ++--- 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/tests/Umbraco.Tests.Common/Builders/Extensions/BuilderExtensions.cs b/tests/Umbraco.Tests.Common/Builders/Extensions/BuilderExtensions.cs index a44c5c7ba9..accee29bae 100644 --- a/tests/Umbraco.Tests.Common/Builders/Extensions/BuilderExtensions.cs +++ b/tests/Umbraco.Tests.Common/Builders/Extensions/BuilderExtensions.cs @@ -232,8 +232,7 @@ public static class BuilderExtensions return builder; } - public static T WithPropertyValues(this T builder, object propertyValues, string? culture = null, - string? segment = null) + public static T WithPropertyValues(this T builder, object propertyValues, string? culture = null, string? segment = null) where T : IWithPropertyValues { builder.PropertyValues = propertyValues; diff --git a/tests/Umbraco.Tests.Common/Builders/MediaTypeEditingBuilder.cs b/tests/Umbraco.Tests.Common/Builders/MediaTypeEditingBuilder.cs index c1291d64db..eb243adc89 100644 --- a/tests/Umbraco.Tests.Common/Builders/MediaTypeEditingBuilder.cs +++ b/tests/Umbraco.Tests.Common/Builders/MediaTypeEditingBuilder.cs @@ -1,4 +1,4 @@ -using Umbraco.Cms.Core; +using Umbraco.Cms.Core; using Umbraco.Cms.Core.Models.ContentTypeEditing; using Umbraco.Cms.Tests.Common.Builders.Extensions; using Umbraco.Cms.Tests.Common.Builders.Interfaces; @@ -41,8 +41,7 @@ public class MediaTypeEditingBuilder : ContentTypeEditingBaseBuilder Date: Sat, 12 Oct 2024 16:33:17 +0300 Subject: [PATCH 3/8] Making Culture Invariant When Validating Date to negate deferent formats (#17257) * CultureInfo.InvariantCulture, * adding unitTests by @Matthew-Wise --- .../Validators/DateTimeValidator.cs | 3 +- .../Validators/DateTimeValidatorTests.cs | 29 +++++++++++++++++++ 2 files changed, 31 insertions(+), 1 deletion(-) create mode 100644 tests/Umbraco.Tests.UnitTests/Umbraco.Core/PropertyEditors/Validators/DateTimeValidatorTests.cs diff --git a/src/Umbraco.Core/PropertyEditors/Validators/DateTimeValidator.cs b/src/Umbraco.Core/PropertyEditors/Validators/DateTimeValidator.cs index 530935d276..8a01c8d257 100644 --- a/src/Umbraco.Core/PropertyEditors/Validators/DateTimeValidator.cs +++ b/src/Umbraco.Core/PropertyEditors/Validators/DateTimeValidator.cs @@ -1,4 +1,5 @@ using System.ComponentModel.DataAnnotations; +using System.Globalization; using Umbraco.Extensions; namespace Umbraco.Cms.Core.PropertyEditors.Validators; @@ -16,7 +17,7 @@ public class DateTimeValidator : IValueValidator yield break; } - if (DateTime.TryParse(value.ToString(), out DateTime dt) == false) + if (DateTime.TryParse(value.ToString(), CultureInfo.InvariantCulture, out DateTime dt) == false) { yield return new ValidationResult( string.Format("The string value {0} cannot be parsed into a DateTime", value), diff --git a/tests/Umbraco.Tests.UnitTests/Umbraco.Core/PropertyEditors/Validators/DateTimeValidatorTests.cs b/tests/Umbraco.Tests.UnitTests/Umbraco.Core/PropertyEditors/Validators/DateTimeValidatorTests.cs new file mode 100644 index 0000000000..7bdd751d3b --- /dev/null +++ b/tests/Umbraco.Tests.UnitTests/Umbraco.Core/PropertyEditors/Validators/DateTimeValidatorTests.cs @@ -0,0 +1,29 @@ +using System.Globalization; +using NUnit.Framework; +using Umbraco.Cms.Core.PropertyEditors.Validators; + +namespace Umbraco.Cms.Tests.UnitTests.Umbraco.Core.PropertyEditors.Validators; + +[TestFixture] +public class DateTimeValidatorTests +{ + [TestCase("en-US", "yyyy-MM-dd HH:mm:ss", TestName = "US Thread, DateTimeValidator")] + [TestCase("en-US", "dd-MM-yyyy HH:mm:ss", TestName = "US Thread, DateTimeValidator ar-SA format")] + [TestCase("ar-SA", "dd-MM-yyyy HH:mm:ss", TestName = "Arabian Saudi Thread, DateTimeValidator")] + [TestCase("ar-SA", "yyyy-MM-dd HH:mm:ss", TestName = "Arabian Saudi Thread, DateTimeValidator US format")] + public void DateTimeValidatorIsCultureInvariant(string culture, string format) + { + var dateString = DateTime.Now.ToString(format); + + var cultureInfo = new CultureInfo(culture); + Thread.CurrentThread.CurrentCulture = cultureInfo; + Thread.CurrentThread.CurrentUICulture = cultureInfo; + + var validator = new DateTimeValidator(); + var validationResults = validator.Validate(dateString, "DATETIME", new Dictionary + { + ["format"] = format + }); + CollectionAssert.IsEmpty(validationResults); + } +} From e4dbf4ce9ff9ca70ed7c82c0c735a4d576aad692 Mon Sep 17 00:00:00 2001 From: Matthew Wise <6782865+Matthew-Wise@users.noreply.github.com> Date: Sat, 12 Oct 2024 16:59:02 +0100 Subject: [PATCH 4/8] fix(#17220): added a sort to the mapping so the UI reflects the database --- .../Mapping/DocumentType/DocumentTypeMapDefinition.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/Umbraco.Cms.Api.Management/Mapping/DocumentType/DocumentTypeMapDefinition.cs b/src/Umbraco.Cms.Api.Management/Mapping/DocumentType/DocumentTypeMapDefinition.cs index 2a5ea3ae7c..958dff64e4 100644 --- a/src/Umbraco.Cms.Api.Management/Mapping/DocumentType/DocumentTypeMapDefinition.cs +++ b/src/Umbraco.Cms.Api.Management/Mapping/DocumentType/DocumentTypeMapDefinition.cs @@ -1,4 +1,4 @@ -using Umbraco.Cms.Api.Management.Mapping.ContentType; +using Umbraco.Cms.Api.Management.Mapping.ContentType; using Umbraco.Cms.Api.Management.ViewModels; using Umbraco.Cms.Api.Management.ViewModels.DocumentType; using Umbraco.Cms.Core.Mapping; @@ -39,6 +39,7 @@ public class DocumentTypeMapDefinition : ContentTypeMapDefinition new DocumentTypeSort { DocumentType = new ReferenceByIdModel(ct.Key), SortOrder = ct.SortOrder }) + .OrderBy(ct => ct.SortOrder) .ToArray() ?? Enumerable.Empty(); target.Compositions = MapNestedCompositions( source.ContentTypeComposition, From 15f42f9ba99774aa57167db3f9519122ea87d7cf Mon Sep 17 00:00:00 2001 From: Owain Jones Date: Sat, 26 Oct 2024 01:37:52 +0100 Subject: [PATCH 5/8] Update Welsh lang file (#17368) * Update Welsh lang file * Adjusted newlines --- .../EmbeddedResources/Lang/cy.xml | 59 ++++++++++++------- 1 file changed, 39 insertions(+), 20 deletions(-) diff --git a/src/Umbraco.Core/EmbeddedResources/Lang/cy.xml b/src/Umbraco.Core/EmbeddedResources/Lang/cy.xml index 201f18059e..5faddf8403 100644 --- a/src/Umbraco.Core/EmbeddedResources/Lang/cy.xml +++ b/src/Umbraco.Core/EmbeddedResources/Lang/cy.xml @@ -1,4 +1,4 @@ - + Method4 Ltd @@ -82,7 +82,8 @@ Mae'r ddolen rydych wedi clicio arno naill ai yn annilys neu wedi dod i ben Umbraco: Ailosod Cyfrinair - + @@ -162,10 +163,12 @@ - ]]> + ]]> + - + + ]]> + Mae'r ieithoedd canlynol wedi'u haddasu %0% - + @@ -256,16 +261,20 @@ - ]]> - Mae'r ieithoedd canlynol wedi'u haddasu:

+ ]]> +
+ + Mae'r ieithoedd canlynol wedi'u haddasu:

%0% - ]]>
+ ]]> + [%0%] Hysbysiad am %1% wedi perfformio am %2% Nid yw'r cyfrinair cadarnhau yn cyfateb â'r cyfrinair newydd! Umbraco: Gwahoddiad - + @@ -355,7 +364,8 @@ - ]]> + ]]> + Mae defnyddiwr gyda'r mewngofnodi hwn eisoes yn bodoli Rhaid bod gan y cyfrinair o leiaf un digid ('0'-'9') Rhaid bod gan y cyfrinair o leiaf un llythrennau bach ('a'-'z') @@ -414,6 +424,8 @@ Modd casgliad dadfygio wedi'i analluogi. Modd casgliad dadfygio wedi'i alluogi. Argymhellwyd analluogi'r gosodiad yma cyn mynd yn fyw. + Mae'r modd rhedeg wedi'i osod i gynhyrchu. + Nid yw'r modd rhedeg wedi'i osod i Gynhyrchu. Argymhellir gosod y Modd Rhedeg i Gynhyrchu ar gyfer amgylcheddau byw/cynhyrchu. @@ -426,14 +438,12 @@ X-Content-Type-Options sy'n cael ei ddefnyddio i amddiffyn yn erbyn gwendidau sniffio MIME wedi'i ganfod.]]> Strict-Transport-Security, hefyd wedi'i adnabod fel HSTS-header, wedi'i ganfod.]]> Strict-Transport-Security wedi'i ganfod.]]> - - Strict-Transport-Security, a elwir hefyd yn HSTS-header. Ni ddylai'r pennyn hwn fod yn bresennol ar localhost.]]> - - - Strict-Transport-Security. Ni ddylai'r pennyn hwn fod yn bresennol ar localhost.]]> - + Strict-Transport-Security, a elwir hefyd yn HSTS-header. Ni ddylai'r pennyn hwn fod yn bresennol ar localhost.]]> + Strict-Transport-Security. Ni ddylai'r pennyn hwn fod yn bresennol ar localhost.]]> X-XSS-Protection wedi'i ganfod.]]> X-XSS-Protection wedi'i ganfod.]]> + Content-Security-Policy (CSP) wedi'i ganfod.]]> + Content-Security-Policy (CSP), a ddefnyddir i atal ymosodiadau sgriptio traws-safle (XSS) a gwendidau pigiad cod eraill, wedi'i ganfod.]]> %0%.]]> Dim peniadau sy'n datgelu gwynodaeth am dechnoleg eich gwefan wedi'u canfod. Gosodiadau SMTP wedi ffurfweddu'n gywir ac mae'r gwasanaeth yn gweithio fel y disgwylir. @@ -463,8 +473,17 @@ Byddwn ond yn anfon ID safle dienw i roi gwybod i ni bod y wefan yn bodoli. Byddwn yn anfon ID safle dienw, fersiwn Umbraco, a phecynnau wedi'u gosod - Byddwn yn anfon: -
  • ID safle dienw, fersiwn Umbraco, a phecynnau wedi'u gosod.
  • Nifer o: Nodau gwraidd, Nodau Cynnwys, Macros, Cyfryngau, Mathau o Ddogfen, Templedi, Ieithoedd, Parthau, Grŵp Defnyddwyr, Defnyddwyr, Aelodau, a Golygyddion Eiddo a ddefnyddir.
  • Gwybodaeth system: Webserver, gweinydd OS, fframwaith gweinydd, iaith gweinyddwr OS, a darparwr cronfa ddata.
  • Gosodiadau cyfluniad: Modd Modelsbuilder, os oes llwybr Umbraco arferol yn bodoli, amgylchedd ASP, ac os ydych chi yn y modd dadfygio.
Efallai y byddwn yn newid yr hyn a anfonwn ar y lefel Fanwl yn y dyfodol. Os felly, fe'i rhestrir uchod. -
Drwy ddewis "Manwl" rydych yn cytuno i wybodaeth ddienw yn awr ac yn y dyfodol gael ei chasglu.
+ Byddwn yn anfon: +
    +
  • ID safle dienw, fersiwn Umbraco, a phecynnau wedi'u gosod.
  • +
  • Nifer o: Nodau gwraidd, Nodau Cynnwys, Macros, Cyfryngau, Mathau o Ddogfen, Templedi, Ieithoedd, Parthau, Grŵp Defnyddwyr, Defnyddwyr, Aelodau, a Golygyddion Eiddo a ddefnyddir.
  • +
  • Gwybodaeth system: Webserver, gweinydd OS, fframwaith gweinydd, iaith gweinyddwr OS, a darparwr cronfa ddata.
  • +
  • Gosodiadau cyfluniad: Modd Modelsbuilder, os oes llwybr Umbraco arferol yn bodoli, amgylchedd ASP, ac os ydych chi yn y modd dadfygio.
  • +
+ + Efallai y byddwn yn newid yr hyn a anfonwn ar y lefel Fanwl yn y dyfodol. Os felly, fe'i rhestrir uchod. +
Drwy ddewis "Manwl" rydych yn cytuno i wybodaeth ddienw yn awr ac yn y dyfodol gael ei chasglu. +
+
From 42f0a5dc53d08c0d74093710dc30cc74cefa9874 Mon Sep 17 00:00:00 2001 From: Matt Brailsford Date: Mon, 4 Nov 2024 16:51:18 +0100 Subject: [PATCH 6/8] [v15] Update obsoletion message for `IPublishedContent.Parent` and `IPublishedContent.Children` to better alternatives (#17419) * Make block editor base classes public * Update BlockEditorValues.cs Change to trigger a new build for #16774 * Update IPublishedContent.cs Provide better suggestions for alternatives to `Childrent` and `Parent` * Updated obsolete message --------- Co-authored-by: Kenn Jacobsen --- src/Umbraco.Core/Models/PublishedContent/IPublishedContent.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Umbraco.Core/Models/PublishedContent/IPublishedContent.cs b/src/Umbraco.Core/Models/PublishedContent/IPublishedContent.cs index 8792baaecc..6fefac9040 100644 --- a/src/Umbraco.Core/Models/PublishedContent/IPublishedContent.cs +++ b/src/Umbraco.Core/Models/PublishedContent/IPublishedContent.cs @@ -100,7 +100,7 @@ public interface IPublishedContent : IPublishedElement /// Gets the parent of the content item. /// /// The parent of root content is null. - [Obsolete("Please use IDocumentNavigationQueryService.TryGetParentKey() instead. Scheduled for removal in V16.")] + [Obsolete("Please use either the IPublishedContent.Parent<>() extension method in the Umbraco.Extensions namespace, or IDocumentNavigationQueryService if you only need keys. Scheduled for removal in V16.")] IPublishedContent? Parent { get; } /// @@ -142,6 +142,6 @@ public interface IPublishedContent : IPublishedElement /// /// Gets the children of the content item that are available for the current culture. /// - [Obsolete("Please use IDocumentNavigationQueryService.TryGetChildrenKeys() instead. Scheduled for removal in V16.")] + [Obsolete("Please use either the IPublishedContent.Children() extension method in the Umbraco.Extensions namespace, or IDocumentNavigationQueryService if you only need keys. Scheduled for removal in V16.")] IEnumerable Children { get; } } From 6705de032977360107397f5903948035a3bbdd85 Mon Sep 17 00:00:00 2001 From: Nathaniel Nunes Date: Thu, 7 Nov 2024 21:11:30 +0530 Subject: [PATCH 7/8] sort the children of a parent content after either deleting or moving its child content (#17315) --- src/Umbraco.Core/Services/ContentService.cs | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/src/Umbraco.Core/Services/ContentService.cs b/src/Umbraco.Core/Services/ContentService.cs index 08147a48a9..8fbc8c8305 100644 --- a/src/Umbraco.Core/Services/ContentService.cs +++ b/src/Umbraco.Core/Services/ContentService.cs @@ -2406,6 +2406,8 @@ public class ContentService : RepositoryService, IContentService using (ICoreScope scope = ScopeProvider.CreateCoreScope()) { + var parentId = content.ParentId; + scope.WriteLock(Constants.Locks.ContentTree); var originalPath = content.Path; @@ -2438,6 +2440,14 @@ public class ContentService : RepositoryService, IContentService movingToRecycleBinNotification)); Audit(AuditType.Move, userId, content.Id, "Moved to recycle bin"); + // sort the children of the parent after deleting the content + IQuery childQuery = Query().Where(x => x.ParentId == parentId && x.Id != content.Id); + IEnumerable children = _documentRepository.Get(childQuery); + if(children.Any()) + { + Sort(children, userId); + } + scope.Complete(); } @@ -2459,6 +2469,8 @@ public class ContentService : RepositoryService, IContentService { EventMessages eventMessages = EventMessagesFactory.Get(); + var parentIdBeforeMove = content.ParentId; + if (content.ParentId == parentId) { return OperationResult.Succeed(eventMessages); @@ -2523,6 +2535,14 @@ public class ContentService : RepositoryService, IContentService Audit(AuditType.Move, userId, content.Id); + // sort the children of the old parent after moving the content + IQuery childQuery = Query().Where(x => x.ParentId == parentIdBeforeMove && x.Id != content.Id); + IEnumerable children = _documentRepository.Get(childQuery); + if (children.Any()) + { + Sort(children, userId); + } + scope.Complete(); return OperationResult.Succeed(eventMessages); } From 7a8ba966823246f4ff51b89add01f56b09112af9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Frederik=20Lundbeck=20J=C3=B8rgensen?= Date: Tue, 15 Oct 2024 18:12:51 +0200 Subject: [PATCH 8/8] append 'YouTube Live' url scheme regex to Youtube embed provider class --- src/Umbraco.Core/Media/EmbedProviders/Youtube.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Umbraco.Core/Media/EmbedProviders/Youtube.cs b/src/Umbraco.Core/Media/EmbedProviders/Youtube.cs index edaf37c0b0..c711f1d81f 100644 --- a/src/Umbraco.Core/Media/EmbedProviders/Youtube.cs +++ b/src/Umbraco.Core/Media/EmbedProviders/Youtube.cs @@ -14,7 +14,7 @@ public class YouTube : OEmbedProviderBase public override string ApiEndpoint => "https://www.youtube.com/oembed"; - public override string[] UrlSchemeRegex => new[] { @"youtu.be/.*", @"youtube.com/watch.*", @"youtube.com/shorts/.*" }; + public override string[] UrlSchemeRegex => new[] { @"youtu.be/.*", @"youtube.com/watch.*", @"youtube.com/shorts/.*", @"youtube.com/live/.*" }; public override Dictionary RequestParams => new() {