diff --git a/src/Umbraco.Core/Constants-DataTypes.cs b/src/Umbraco.Core/Constants-DataTypes.cs
index 5db4d71efc..e22ca00ae2 100644
--- a/src/Umbraco.Core/Constants-DataTypes.cs
+++ b/src/Umbraco.Core/Constants-DataTypes.cs
@@ -13,6 +13,8 @@ public static partial class Constants
public const int LabelDateTime = -94;
public const int LabelTime = -98;
public const int LabelDecimal = -99;
+ public const int LabelBytes = -104;
+ public const int LabelPixels = -105;
public const int Textarea = -89;
public const int Textbox = -88;
@@ -225,6 +227,16 @@ public static partial class Constants
///
public const string LabelDecimal = "8f1ef1e1-9de4-40d3-a072-6673f631ca64";
+ ///
+ /// Guid for Label as bytes
+ ///
+ public const string LabelBytes = "ba5bdbe6-ab3e-46a8-82b3-2c45f10bc47f";
+
+ ///
+ /// Guid for Label as pixels
+ ///
+ public const string LabelPixels = "5eb57825-e15e-4fc7-8e37-fca65cdafbde";
+
///
/// Guid for Content Picker
///
diff --git a/src/Umbraco.Infrastructure/Migrations/Install/DatabaseDataCreator.cs b/src/Umbraco.Infrastructure/Migrations/Install/DatabaseDataCreator.cs
index 5d56d29b7e..1b707d45db 100644
--- a/src/Umbraco.Infrastructure/Migrations/Install/DatabaseDataCreator.cs
+++ b/src/Umbraco.Infrastructure/Migrations/Install/DatabaseDataCreator.cs
@@ -320,6 +320,10 @@ internal sealed class DatabaseDataCreator
InsertDataTypeNodeDto(Constants.DataTypes.LabelTime, 38, Constants.DataTypes.Guids.LabelTime, "Label (time)");
InsertDataTypeNodeDto(Constants.DataTypes.LabelDecimal, 39, Constants.DataTypes.Guids.LabelDecimal,
"Label (decimal)");
+ InsertDataTypeNodeDto(Constants.DataTypes.LabelBytes, 40, Constants.DataTypes.Guids.LabelBytes,
+ "Label (bytes)");
+ InsertDataTypeNodeDto(Constants.DataTypes.LabelPixels, 41, Constants.DataTypes.Guids.LabelPixels,
+ "Label (pixels)");
ConditionalInsert(
Constants.Configuration.NamedOptions.InstallDefaultData.DataTypes,
@@ -1454,7 +1458,7 @@ internal sealed class DatabaseDataCreator
{
Id = 7,
UniqueId = new Guid("A68D453B-1F62-44F4-9F71-0B6BBD43C355"),
- DataTypeId = Constants.DataTypes.LabelInt,
+ DataTypeId = Constants.DataTypes.LabelPixels,
ContentTypeId = 1032,
PropertyTypeGroupId = 3,
Alias = Constants.Conventions.Media.Width,
@@ -1462,7 +1466,7 @@ internal sealed class DatabaseDataCreator
SortOrder = 0,
Mandatory = false,
ValidationRegExp = null,
- Description = "in pixels",
+ Description = null,
Variations = (byte)ContentVariation.Nothing,
});
_database.Insert(Constants.DatabaseSchema.Tables.PropertyType, "id", false,
@@ -1470,7 +1474,7 @@ internal sealed class DatabaseDataCreator
{
Id = 8,
UniqueId = new Guid("854087F6-648B-40ED-BC98-B8A9789E80B9"),
- DataTypeId = Constants.DataTypes.LabelInt,
+ DataTypeId = Constants.DataTypes.LabelPixels,
ContentTypeId = 1032,
PropertyTypeGroupId = 3,
Alias = Constants.Conventions.Media.Height,
@@ -1478,7 +1482,7 @@ internal sealed class DatabaseDataCreator
SortOrder = 0,
Mandatory = false,
ValidationRegExp = null,
- Description = "in pixels",
+ Description = null,
Variations = (byte)ContentVariation.Nothing,
});
_database.Insert(Constants.DatabaseSchema.Tables.PropertyType, "id", false,
@@ -1486,15 +1490,15 @@ internal sealed class DatabaseDataCreator
{
Id = 9,
UniqueId = new Guid("BD4C5ACE-26E3-4A8B-AF1A-E8206A35FA07"),
- DataTypeId = Constants.DataTypes.LabelBigint,
+ DataTypeId = Constants.DataTypes.LabelBytes,
ContentTypeId = 1032,
PropertyTypeGroupId = 3,
Alias = Constants.Conventions.Media.Bytes,
- Name = "Size",
+ Name = "File size",
SortOrder = 0,
Mandatory = false,
ValidationRegExp = null,
- Description = "in bytes",
+ Description = null,
Variations = (byte)ContentVariation.Nothing,
});
_database.Insert(Constants.DatabaseSchema.Tables.PropertyType, "id", false,
@@ -1502,11 +1506,11 @@ internal sealed class DatabaseDataCreator
{
Id = 10,
UniqueId = new Guid("F7786FE8-724A-4ED0-B244-72546DB32A92"),
- DataTypeId = -92,
+ DataTypeId = Constants.DataTypes.LabelString,
ContentTypeId = 1032,
PropertyTypeGroupId = 3,
Alias = Constants.Conventions.Media.Extension,
- Name = "Type",
+ Name = "File extension",
SortOrder = 0,
Mandatory = false,
ValidationRegExp = null,
@@ -1538,11 +1542,11 @@ internal sealed class DatabaseDataCreator
{
Id = 25,
UniqueId = new Guid("3531C0A3-4E0A-4324-A621-B9D3822B071F"),
- DataTypeId = -92,
+ DataTypeId = Constants.DataTypes.LabelString,
ContentTypeId = 1033,
PropertyTypeGroupId = 4,
Alias = Constants.Conventions.Media.Extension,
- Name = "Type",
+ Name = "File extension",
SortOrder = 0,
Mandatory = false,
ValidationRegExp = null,
@@ -1554,15 +1558,15 @@ internal sealed class DatabaseDataCreator
{
Id = 26,
UniqueId = new Guid("F9527050-59BC-43E4-8FA8-1658D1319FF5"),
- DataTypeId = Constants.DataTypes.LabelBigint,
+ DataTypeId = Constants.DataTypes.LabelBytes,
ContentTypeId = 1033,
PropertyTypeGroupId = 4,
Alias = Constants.Conventions.Media.Bytes,
- Name = "Size",
+ Name = "File size",
SortOrder = 0,
Mandatory = false,
ValidationRegExp = null,
- Description = "in bytes",
+ Description = null,
Variations = (byte)ContentVariation.Nothing,
});
}
@@ -1590,11 +1594,11 @@ internal sealed class DatabaseDataCreator
{
Id = 41,
UniqueId = new Guid("EDD2B3FD-1E57-4E57-935E-096DEFCCDC9B"),
- DataTypeId = -92,
+ DataTypeId = Constants.DataTypes.LabelString,
ContentTypeId = 1034,
PropertyTypeGroupId = 52,
Alias = Constants.Conventions.Media.Extension,
- Name = "Type",
+ Name = "File extension",
SortOrder = 0,
Mandatory = false,
ValidationRegExp = null,
@@ -1606,15 +1610,15 @@ internal sealed class DatabaseDataCreator
{
Id = 42,
UniqueId = new Guid("180EEECF-1F00-409E-8234-BBA967E08B0A"),
- DataTypeId = Constants.DataTypes.LabelBigint,
+ DataTypeId = Constants.DataTypes.LabelBytes,
ContentTypeId = 1034,
PropertyTypeGroupId = 52,
Alias = Constants.Conventions.Media.Bytes,
- Name = "Size",
+ Name = "File size",
SortOrder = 0,
Mandatory = false,
ValidationRegExp = null,
- Description = "in bytes",
+ Description = null,
Variations = (byte)ContentVariation.Nothing,
});
}
@@ -1642,11 +1646,11 @@ internal sealed class DatabaseDataCreator
{
Id = 44,
UniqueId = new Guid("1BEE433F-A21A-4031-8E03-AF01BB8D2DE9"),
- DataTypeId = -92,
+ DataTypeId = Constants.DataTypes.LabelString,
ContentTypeId = 1035,
PropertyTypeGroupId = 53,
Alias = Constants.Conventions.Media.Extension,
- Name = "Type",
+ Name = "File extension",
SortOrder = 0,
Mandatory = false,
ValidationRegExp = null,
@@ -1658,15 +1662,15 @@ internal sealed class DatabaseDataCreator
{
Id = 45,
UniqueId = new Guid("3CBF538A-29AB-4317-A9EB-BBCDF1A54260"),
- DataTypeId = Constants.DataTypes.LabelBigint,
+ DataTypeId = Constants.DataTypes.LabelBytes,
ContentTypeId = 1035,
PropertyTypeGroupId = 53,
Alias = Constants.Conventions.Media.Bytes,
- Name = "Size",
+ Name = "File size",
SortOrder = 0,
Mandatory = false,
ValidationRegExp = null,
- Description = "in bytes",
+ Description = null,
Variations = (byte)ContentVariation.Nothing,
});
}
@@ -1694,11 +1698,11 @@ internal sealed class DatabaseDataCreator
{
Id = 47,
UniqueId = new Guid("EF1B4AF7-36DE-45EB-8C18-A2DE07319227"),
- DataTypeId = -92,
+ DataTypeId = Constants.DataTypes.LabelString,
ContentTypeId = 1036,
PropertyTypeGroupId = 54,
Alias = Constants.Conventions.Media.Extension,
- Name = "Type",
+ Name = "File extension",
SortOrder = 0,
Mandatory = false,
ValidationRegExp = null,
@@ -1710,15 +1714,15 @@ internal sealed class DatabaseDataCreator
{
Id = 48,
UniqueId = new Guid("AAB7D00C-7209-4337-BE3F-A4421C8D79A0"),
- DataTypeId = Constants.DataTypes.LabelBigint,
+ DataTypeId = Constants.DataTypes.LabelBytes,
ContentTypeId = 1036,
PropertyTypeGroupId = 54,
Alias = Constants.Conventions.Media.Bytes,
- Name = "Size",
+ Name = "File size",
SortOrder = 0,
Mandatory = false,
ValidationRegExp = null,
- Description = "in bytes",
+ Description = null,
Variations = (byte)ContentVariation.Nothing,
});
}
@@ -1746,11 +1750,11 @@ internal sealed class DatabaseDataCreator
{
Id = 50,
UniqueId = new Guid("0F25A89E-2EB7-49BC-A7B4-759A7E4C69F2"),
- DataTypeId = -92,
+ DataTypeId = Constants.DataTypes.LabelString,
ContentTypeId = 1037,
PropertyTypeGroupId = 55,
Alias = Constants.Conventions.Media.Extension,
- Name = "Type",
+ Name = "File extension",
SortOrder = 0,
Mandatory = false,
ValidationRegExp = null,
@@ -1762,15 +1766,15 @@ internal sealed class DatabaseDataCreator
{
Id = 51,
UniqueId = new Guid("09A07AFF-861D-4769-A2B0-C165EBD43D39"),
- DataTypeId = Constants.DataTypes.LabelBigint,
+ DataTypeId = Constants.DataTypes.LabelBytes,
ContentTypeId = 1037,
PropertyTypeGroupId = 55,
Alias = Constants.Conventions.Media.Bytes,
- Name = "Size",
+ Name = "File size",
SortOrder = 0,
Mandatory = false,
ValidationRegExp = null,
- Description = "in bytes",
+ Description = null,
Variations = (byte)ContentVariation.Nothing,
});
}
@@ -1995,6 +1999,10 @@ internal sealed class DatabaseDataCreator
"Umb.PropertyEditorUi.Label", "Decimal", "{\"umbracoDataValueType\":\"DECIMAL\"}");
InsertDataTypeDto(Constants.DataTypes.LabelTime, Constants.PropertyEditors.Aliases.Label,
"Umb.PropertyEditorUi.Label", "Date", "{\"umbracoDataValueType\":\"TIME\"}");
+ InsertDataTypeDto(Constants.DataTypes.LabelBytes, Constants.PropertyEditors.Aliases.Label,
+ "Umb.PropertyEditorUi.Label", "Nvarchar", "{\"umbracoDataValueType\":\"BIGINT\", \"labelTemplate\":\"{=value | bytes}\"}");
+ InsertDataTypeDto(Constants.DataTypes.LabelPixels, Constants.PropertyEditors.Aliases.Label,
+ "Umb.PropertyEditorUi.Label", "Integer", "{\"umbracoDataValueType\":\"INT\", \"labelTemplate\":\"{=value}px\"}");
if (_database.Exists(Constants.DataTypes.DateTime))
{
diff --git a/src/Umbraco.Infrastructure/Migrations/Upgrade/UmbracoPlan.cs b/src/Umbraco.Infrastructure/Migrations/Upgrade/UmbracoPlan.cs
index 0d7babbacf..21294c9e76 100644
--- a/src/Umbraco.Infrastructure/Migrations/Upgrade/UmbracoPlan.cs
+++ b/src/Umbraco.Infrastructure/Migrations/Upgrade/UmbracoPlan.cs
@@ -126,5 +126,6 @@ public class UmbracoPlan : MigrationPlan
// To 16.3.0
To("{A917FCBC-C378-4A08-A36C-220C581A6581}");
+ To("{FB7073AF-DFAF-4AC1-800D-91F9BD5B5238}");
}
}
diff --git a/src/Umbraco.Infrastructure/Migrations/Upgrade/V_16_3_0/MigrateMediaTypeLabelProperties.cs b/src/Umbraco.Infrastructure/Migrations/Upgrade/V_16_3_0/MigrateMediaTypeLabelProperties.cs
new file mode 100644
index 0000000000..3ced4a2a6a
--- /dev/null
+++ b/src/Umbraco.Infrastructure/Migrations/Upgrade/V_16_3_0/MigrateMediaTypeLabelProperties.cs
@@ -0,0 +1,193 @@
+using Microsoft.Extensions.Logging;
+using Microsoft.Extensions.Options;
+using Umbraco.Cms.Core;
+using Umbraco.Cms.Core.Configuration.Models;
+using Umbraco.Cms.Core.Models;
+using Umbraco.Cms.Core.Services;
+using Umbraco.Cms.Core.Services.OperationStatus;
+using Umbraco.Cms.Infrastructure.Persistence.Dtos;
+
+namespace Umbraco.Cms.Infrastructure.Migrations.Upgrade.V_16_3_0;
+
+[Obsolete("Remove in Umbraco 18.")]
+public class MigrateMediaTypeLabelProperties : AsyncMigrationBase
+{
+ private readonly IMediaTypeService _mediaTypeService;
+
+ private readonly InstallDefaultDataSettings? _dataTypeSettings;
+ private readonly InstallDefaultDataSettings? _mediaTypeSettings;
+
+ private readonly Guid _labelBytesDataTypeKey = new(Constants.DataTypes.Guids.LabelBytes);
+ private readonly Guid _labelPixelsDataTypeKey = new(Constants.DataTypes.Guids.LabelPixels);
+
+ public MigrateMediaTypeLabelProperties(
+ IMigrationContext context,
+ IMediaTypeService mediaTypeService,
+ IOptionsMonitor installDefaultDataSettings)
+ : base(context)
+ {
+ _mediaTypeService = mediaTypeService;
+
+ _dataTypeSettings = installDefaultDataSettings.Get(Constants.Configuration.NamedOptions.InstallDefaultData.DataTypes);
+ _mediaTypeSettings = installDefaultDataSettings.Get(Constants.Configuration.NamedOptions.InstallDefaultData.MediaTypes);
+ }
+
+ protected override async Task MigrateAsync()
+ {
+ if (_dataTypeSettings?.InstallData == InstallDefaultDataOption.None)
+ {
+ return;
+ }
+
+ if (_mediaTypeSettings?.InstallData == InstallDefaultDataOption.None)
+ {
+ return;
+ }
+
+ IfNotExistsCreateBytesLabel();
+ IfNotExistsCreatePixelsLabel();
+ await MigrateMediaTypeLabels();
+ }
+
+ private void IfNotExistsCreateBytesLabel()
+ {
+ if (Database.Exists(Constants.DataTypes.LabelBytes))
+ {
+ return;
+ }
+
+ var nodeDto = new NodeDto
+ {
+ NodeId = Constants.DataTypes.LabelBytes,
+ Trashed = false,
+ ParentId = -1,
+ UserId = -1,
+ Level = 1,
+ Path = "-1," + Constants.DataTypes.LabelBytes,
+ SortOrder = 40,
+ UniqueId = _labelBytesDataTypeKey,
+ Text = "Label (bytes)",
+ NodeObjectType = Constants.ObjectTypes.DataType,
+ CreateDate = DateTime.Now,
+ };
+
+ _ = Database.Insert(Constants.DatabaseSchema.Tables.Node, "id", false, nodeDto);
+
+ var dataTypeDto = new DataTypeDto
+ {
+ NodeId = Constants.DataTypes.LabelBytes,
+ EditorAlias = Constants.PropertyEditors.Aliases.Label,
+ EditorUiAlias = "Umb.PropertyEditorUi.Label",
+ DbType = nameof(ValueStorageType.Nvarchar),
+ Configuration = "{\"umbracoDataValueType\":\"BIGINT\", \"labelTemplate\":\"{=value | bytes}\"}",
+ };
+
+ _ = Database.Insert(Constants.DatabaseSchema.Tables.DataType, "pk", false, dataTypeDto);
+ }
+
+ private void IfNotExistsCreatePixelsLabel()
+ {
+ if (Database.Exists(Constants.DataTypes.LabelPixels))
+ {
+ return;
+ }
+
+ var nodeDto = new NodeDto
+ {
+ NodeId = Constants.DataTypes.LabelPixels,
+ Trashed = false,
+ ParentId = -1,
+ UserId = -1,
+ Level = 1,
+ Path = "-1," + Constants.DataTypes.LabelPixels,
+ SortOrder = 41,
+ UniqueId = _labelPixelsDataTypeKey,
+ Text = "Label (pixels)",
+ NodeObjectType = Constants.ObjectTypes.DataType,
+ CreateDate = DateTime.Now,
+ };
+
+ _ = Database.Insert(Constants.DatabaseSchema.Tables.Node, "id", false, nodeDto);
+
+ var dataTypeDto = new DataTypeDto
+ {
+ NodeId = Constants.DataTypes.LabelPixels,
+ EditorAlias = Constants.PropertyEditors.Aliases.Label,
+ EditorUiAlias = "Umb.PropertyEditorUi.Label",
+ DbType = nameof(ValueStorageType.Integer),
+ Configuration = "{\"umbracoDataValueType\":\"INT\", \"labelTemplate\":\"{=value}px\"}",
+ };
+
+ _ = Database.Insert(Constants.DatabaseSchema.Tables.DataType, "pk", false, dataTypeDto);
+ }
+
+ private async Task MigrateMediaTypeLabels()
+ {
+ // update all media types with the new data-type references
+ IMediaType[] allMediaTypes = _mediaTypeService.GetAll().ToArray();
+ foreach (IMediaType mediaType in allMediaTypes)
+ {
+ bool updated = false;
+
+ foreach (IPropertyType propertyType in mediaType.PropertyTypes)
+ {
+ switch (propertyType.Alias)
+ {
+ case Constants.Conventions.Media.Bytes when propertyType.DataTypeId == Constants.DataTypes.LabelBigint:
+ propertyType.DataTypeId = Constants.DataTypes.LabelBytes;
+ propertyType.DataTypeKey = _labelBytesDataTypeKey;
+
+ if (propertyType.Name == "Size")
+ {
+ propertyType.Name = "File size";
+ }
+
+ if (propertyType.Description == "in bytes")
+ {
+ propertyType.Description = null;
+ }
+
+ updated = true;
+
+ break;
+
+ case Constants.Conventions.Media.Height when propertyType.DataTypeId == Constants.DataTypes.LabelInt:
+ case Constants.Conventions.Media.Width when propertyType.DataTypeId == Constants.DataTypes.LabelInt:
+ propertyType.DataTypeId = Constants.DataTypes.LabelPixels;
+ propertyType.DataTypeKey = _labelPixelsDataTypeKey;
+
+ if (propertyType.Description == "in pixels")
+ {
+ propertyType.Description = null;
+ }
+
+ updated = true;
+
+ break;
+
+ case Constants.Conventions.Media.Extension when propertyType.DataTypeId == Constants.DataTypes.LabelString:
+ if (propertyType.Name == "Type")
+ {
+ propertyType.Name = "File extension";
+ }
+
+ updated = true;
+
+ break;
+
+ default:
+ break;
+ }
+ }
+
+ if (updated)
+ {
+ Attempt attempt = await _mediaTypeService.UpdateAsync(mediaType, Constants.Security.SuperUserKey);
+ if (!attempt.Success)
+ {
+ Logger.LogError(attempt.Exception, $"Failed to update media type '{mediaType.Alias}' during migration.");
+ }
+ }
+ }
+ }
+}
diff --git a/tests/Umbraco.Tests.Integration/Umbraco.Infrastructure/Persistence/Repositories/DataTypeDefinitionRepositoryTest.cs b/tests/Umbraco.Tests.Integration/Umbraco.Infrastructure/Persistence/Repositories/DataTypeDefinitionRepositoryTest.cs
index 66ac4278a3..4ff77c86fa 100644
--- a/tests/Umbraco.Tests.Integration/Umbraco.Infrastructure/Persistence/Repositories/DataTypeDefinitionRepositoryTest.cs
+++ b/tests/Umbraco.Tests.Integration/Umbraco.Infrastructure/Persistence/Repositories/DataTypeDefinitionRepositoryTest.cs
@@ -250,7 +250,7 @@ internal sealed class DataTypeDefinitionRepositoryTest : UmbracoIntegrationTest
Assert.That(dataTypeDefinitions, Is.Not.Null);
Assert.That(dataTypeDefinitions.Any(), Is.True);
Assert.That(dataTypeDefinitions.Any(x => x == null), Is.False);
- Assert.That(dataTypeDefinitions.Length, Is.EqualTo(34));
+ Assert.That(dataTypeDefinitions.Length, Is.EqualTo(36));
}
}