Merge remote-tracking branch 'origin/v10/dev' into v10/feature/nullable-reference-types-in-Umbraco-Core

# Conflicts:
#	build/build.ps1
#	src/Umbraco.Core/Configuration/ConfigConnectionString.cs
#	src/Umbraco.Core/Configuration/Models/ConnectionStrings.cs
#	src/Umbraco.Core/Install/InstallSteps/TelemetryIdentifierStep.cs
#	src/Umbraco.Core/Models/ContentType.cs
#	src/Umbraco.Infrastructure/Migrations/Install/DatabaseBuilder.cs
#	tests/Umbraco.Tests.AcceptanceTest/package.json
This commit is contained in:
Nikolaj Geisle
2022-03-16 13:00:38 +01:00
480 changed files with 11569 additions and 6721 deletions

View File

@@ -819,11 +819,17 @@ namespace Umbraco.Cms.Web.BackOffice.Controllers
contentItem.Variants.Where(x => x.Save).Select(x => x.Culture).ToArray(),
defaultCulture);
//get the updated model
bool isBlueprint = contentItem.PersistedContent.Blueprint;
var contentSavedHeader = isBlueprint ? "editBlueprintSavedHeader" : "editContentSavedHeader";
var contentSavedText = isBlueprint ? "editBlueprintSavedText" : "editContentSavedText";
switch (contentItem.Action)
{
case ContentSaveAction.Save:
case ContentSaveAction.SaveNew:
SaveAndNotify(contentItem, saveMethod, variantCount, notifications, globalNotifications, "editContentSavedText", "editVariantSavedText", cultureForInvariantErrors, null, out wasCancelled);
SaveAndNotify(contentItem, saveMethod, variantCount, notifications, globalNotifications, contentSavedHeader, contentSavedText, "editVariantSavedText", cultureForInvariantErrors, null, out wasCancelled);
break;
case ContentSaveAction.Schedule:
case ContentSaveAction.ScheduleNew:
@@ -833,7 +839,8 @@ namespace Umbraco.Cms.Web.BackOffice.Controllers
wasCancelled = false;
break;
}
SaveAndNotify(contentItem, saveMethod, variantCount, notifications, globalNotifications, "editContentScheduledSavedText", "editVariantSavedText", cultureForInvariantErrors, contentSchedule, out wasCancelled);
SaveAndNotify(contentItem, saveMethod, variantCount, notifications, globalNotifications, "editContentSavedHeader", "editContentScheduledSavedText", "editVariantSavedText", cultureForInvariantErrors, contentSchedule, out wasCancelled);
break;
case ContentSaveAction.SendPublish:
@@ -882,7 +889,7 @@ namespace Umbraco.Cms.Web.BackOffice.Controllers
if (!await ValidatePublishBranchPermissionsAsync(contentItem))
{
globalNotifications.AddErrorNotification(
_localizedTextService.Localize(null,"publish"),
_localizedTextService.Localize(null, "publish"),
_localizedTextService.Localize("publish", "invalidPublishBranchPermissions"));
wasCancelled = false;
break;
@@ -899,7 +906,7 @@ namespace Umbraco.Cms.Web.BackOffice.Controllers
if (!await ValidatePublishBranchPermissionsAsync(contentItem))
{
globalNotifications.AddErrorNotification(
_localizedTextService.Localize(null,"publish"),
_localizedTextService.Localize(null, "publish"),
_localizedTextService.Localize("publish", "invalidPublishBranchPermissions"));
wasCancelled = false;
break;
@@ -913,7 +920,7 @@ namespace Umbraco.Cms.Web.BackOffice.Controllers
throw new ArgumentOutOfRangeException();
}
//get the updated model
// We have to map do display after we've actually saved the content, otherwise we'll miss information that's set when saving content, such as ID
var display = mapToDisplay(contentItem.PersistedContent);
//merge the tracked success messages with the outgoing model
@@ -1040,7 +1047,7 @@ namespace Umbraco.Cms.Web.BackOffice.Controllers
/// </remarks>
private void SaveAndNotify(ContentItemSave contentItem, Func<IContent, ContentScheduleCollection, OperationResult> saveMethod, int variantCount,
Dictionary<string, SimpleNotificationModel> notifications, SimpleNotificationModel globalNotifications,
string invariantSavedLocalizationAlias, string variantSavedLocalizationAlias, string cultureForInvariantErrors, ContentScheduleCollection contentSchedule,
string savedContentHeaderLocalizationAlias, string invariantSavedLocalizationAlias, string variantSavedLocalizationAlias, string cultureForInvariantErrors, ContentScheduleCollection contentSchedule,
out bool wasCancelled)
{
var saveResult = saveMethod(contentItem.PersistedContent, contentSchedule);
@@ -1060,15 +1067,15 @@ namespace Umbraco.Cms.Web.BackOffice.Controllers
var variantName = GetVariantName(culture, segment);
AddSuccessNotification(notifications, culture, segment,
_localizedTextService.Localize("speechBubbles", "editContentSavedHeader"),
_localizedTextService.Localize(null,variantSavedLocalizationAlias, new[] { variantName }));
_localizedTextService.Localize("speechBubbles", savedContentHeaderLocalizationAlias),
_localizedTextService.Localize(null, variantSavedLocalizationAlias, new[] { variantName }));
}
}
else if (ModelState.IsValid)
{
globalNotifications.AddSuccessNotification(
_localizedTextService.Localize("speechBubbles", "editContentSavedHeader"),
_localizedTextService.Localize("speechBubbles",invariantSavedLocalizationAlias));
_localizedTextService.Localize("speechBubbles", savedContentHeaderLocalizationAlias),
_localizedTextService.Localize("speechBubbles", invariantSavedLocalizationAlias));
}
}
}
@@ -2112,21 +2119,34 @@ namespace Umbraco.Cms.Web.BackOffice.Controllers
}
var variantIndex = 0;
var defaultCulture = _allLangs.Value.Values.FirstOrDefault(x => x.IsDefault)?.IsoCode;
//loop through each variant, set the correct name and property values
// loop through each variant, set the correct name and property values
foreach (var variant in contentSave.Variants)
{
//Don't update anything for this variant if Save is not true
if (!variant.Save) continue;
// Don't update anything for this variant if Save is not true
if (!variant.Save)
{
continue;
}
//Don't update the name if it is empty
// Don't update the name if it is empty
if (!variant.Name.IsNullOrWhiteSpace())
{
if (contentSave.PersistedContent.ContentType.VariesByCulture())
{
if (variant.Culture.IsNullOrWhiteSpace())
{
throw new InvalidOperationException($"Cannot set culture name without a culture.");
}
contentSave.PersistedContent.SetCultureName(variant.Name, variant.Culture);
// If the variant culture is the default culture we also want to update the name on the Content itself.
if (variant.Culture.Equals(defaultCulture, StringComparison.InvariantCultureIgnoreCase))
{
contentSave.PersistedContent.Name = variant.Name;
}
}
else
{
@@ -2134,7 +2154,7 @@ namespace Umbraco.Cms.Web.BackOffice.Controllers
}
}
//This is important! We only want to process invariant properties with the first variant, for any other variant
// This is important! We only want to process invariant properties with the first variant, for any other variant
// we need to exclude invariant properties from being processed, otherwise they will be double processed for the
// same value which can cause some problems with things such as file uploads.
var propertyCollection = variantIndex == 0
@@ -2142,10 +2162,10 @@ namespace Umbraco.Cms.Web.BackOffice.Controllers
: new ContentPropertyCollectionDto
{
Properties = variant.PropertyCollectionDto.Properties.Where(
x => !x.Culture.IsNullOrWhiteSpace() || !x.Segment.IsNullOrWhiteSpace())
x => !x.Culture.IsNullOrWhiteSpace() || !x.Segment.IsNullOrWhiteSpace()),
};
//for each variant, map the property values
// for each variant, map the property values
MapPropertyValuesForPersistence<IContent, ContentItemSave>(
contentSave,
propertyCollection,
@@ -2166,6 +2186,12 @@ namespace Umbraco.Cms.Web.BackOffice.Controllers
variantIndex++;
}
// Map IsDirty cultures to edited cultures, to make it easier to verify changes on specific variants on Saving and Saved events.
IEnumerable<string> editedCultures = contentSave.PersistedContent.CultureInfos.Values
.Where(x => x.IsDirty())
.Select(x => x.Culture);
contentSave.PersistedContent.SetCultureEdited(editedCultures);
// handle template
if (string.IsNullOrWhiteSpace(contentSave.TemplateAlias)) // cleared: clear if not already null
{
@@ -2176,10 +2202,10 @@ namespace Umbraco.Cms.Web.BackOffice.Controllers
}
else // set: update if different
{
var template = _fileService.GetTemplate(contentSave.TemplateAlias);
if (template == null)
ITemplate template = _fileService.GetTemplate(contentSave.TemplateAlias);
if (template is null)
{
//ModelState.AddModelError("Template", "No template exists with the specified alias: " + contentItem.TemplateAlias);
// ModelState.AddModelError("Template", "No template exists with the specified alias: " + contentItem.TemplateAlias);
_logger.LogWarning("No template exists with the specified alias: {TemplateAlias}", contentSave.TemplateAlias);
}
else if (template.Id != contentSave.PersistedContent.TemplateId)