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, 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. +
+
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() { 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; } } diff --git a/src/Umbraco.Core/PropertyEditors/Validators/DateTimeValidator.cs b/src/Umbraco.Core/PropertyEditors/Validators/DateTimeValidator.cs index 1c8fcedab2..b306efbb10 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.Cms.Core.Models.Validation; using Umbraco.Extensions; @@ -9,6 +10,14 @@ namespace Umbraco.Cms.Core.PropertyEditors.Validators; /// public class DateTimeValidator : IValueValidator { + /// + /// Validates if the value is a valid date/time + /// + /// + /// + /// + /// + /// public IEnumerable Validate(object? value, string? valueType, object? dataTypeConfiguration, PropertyValidationContext validationContext) { // don't validate if empty @@ -17,10 +26,10 @@ 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), + $"The string value {value} cannot be parsed into a DateTime", new[] { // we only store a single value for this editor so the 'member' or 'field' 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); } diff --git a/src/Umbraco.PublishedCache.HybridCache/Services/MediaCacheService.cs b/src/Umbraco.PublishedCache.HybridCache/Services/MediaCacheService.cs index 77e2370dc3..12327489b8 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; diff --git a/tests/Umbraco.Tests.Common/Builders/MediaTypeEditingBuilder.cs b/tests/Umbraco.Tests.Common/Builders/MediaTypeEditingBuilder.cs index eae219ecd1..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; 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..49241acda4 --- /dev/null +++ b/tests/Umbraco.Tests.UnitTests/Umbraco.Core/PropertyEditors/Validators/DateTimeValidatorTests.cs @@ -0,0 +1,47 @@ +using System.Globalization; +using NUnit.Framework; +using Umbraco.Cms.Core.Models.Validation; +using Umbraco.Cms.Core.PropertyEditors.Validators; + +namespace Umbraco.Cms.Tests.UnitTests.Umbraco.Core.PropertyEditors.Validators +{ + /// + /// Unit test fixture for the DateTimeValidator class. + /// + [TestFixture] + public class DateTimeValidatorTests + { + /// + /// Tests that the DateTimeValidator is culture invariant. + /// + /// The culture to set for the current thread. + /// The date format to use for the test. + [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) + { + // Generate a date string using the specified format + var dateString = DateTime.Now.ToString(format); + + // Set the current thread's culture and UI culture + var cultureInfo = new CultureInfo(culture); + Thread.CurrentThread.CurrentCulture = cultureInfo; + Thread.CurrentThread.CurrentUICulture = cultureInfo; + + // Create a new DateTimeValidator instance + var validator = new DateTimeValidator(); + + // Validate the date string + var validationResults = validator.Validate( + dateString, + "DATETIME", + new Dictionary(), + PropertyValidationContext.Empty()); + + // Assert that there are no validation errors + CollectionAssert.IsEmpty(validationResults); + } + } +}