using System.ComponentModel.DataAnnotations; using Umbraco.Cms.Core.IO; using Umbraco.Cms.Core.Models; using Umbraco.Cms.Core.Models.Validation; using Umbraco.Cms.Core.PropertyEditors.Validation; using Umbraco.Cms.Core.Serialization; using Umbraco.Cms.Core.Services; using Umbraco.Cms.Core.Strings; using Umbraco.Extensions; namespace Umbraco.Cms.Core.PropertyEditors; /// /// Represents an entity data picker property editor. /// [DataEditor( Constants.PropertyEditors.Aliases.EntityDataPicker, ValueType = ValueTypes.Json, ValueEditorIsReusable = true)] internal sealed class EntityDataPickerPropertyEditor : DataEditor { private readonly IIOHelper _ioHelper; /// /// Initializes a new instance of the class. /// public EntityDataPickerPropertyEditor(IDataValueEditorFactory dataValueEditorFactory, IIOHelper ioHelper) : base(dataValueEditorFactory) { _ioHelper = ioHelper; SupportsReadOnly = true; } /// public override IPropertyIndexValueFactory PropertyIndexValueFactory { get; } = new NoopPropertyIndexValueFactory(); /// protected override IDataValueEditor CreateValueEditor() => DataValueEditorFactory.Create(Attribute!); /// protected override IConfigurationEditor CreateConfigurationEditor() => new EntityDataPickerConfigurationEditor(_ioHelper); /// /// Defines the value editor for the entity data picker property editor. /// internal sealed class EntityDataPickerPropertyValueEditor : DataValueEditor { /// /// Initializes a new instance of the class. /// public EntityDataPickerPropertyValueEditor( IShortStringHelper shortStringHelper, IJsonSerializer jsonSerializer, IIOHelper ioHelper, DataEditorAttribute attribute, ILocalizedTextService localizedTextService) : base(shortStringHelper, jsonSerializer, ioHelper, attribute) { var validators = new TypedJsonValidatorRunner( jsonSerializer, new MinMaxValidator(localizedTextService)); Validators.Add(validators); } /// /// Validates the min/max configuration for the entity data picker property editor. /// internal sealed class MinMaxValidator : ITypedJsonValidator { private readonly ILocalizedTextService _localizedTextService; /// /// Initializes a new instance of the class. /// public MinMaxValidator(ILocalizedTextService localizedTextService) => _localizedTextService = localizedTextService; /// public IEnumerable Validate( EntityDataPickerDto? data, EntityDataPickerConfiguration? configuration, string? valueType, PropertyValidationContext validationContext) { var validationResults = new List(); if (data is null || configuration is null) { return validationResults; } if (configuration.ValidationLimit.Min is not null && data.Ids.Length < configuration.ValidationLimit.Min) { validationResults.Add(new ValidationResult( _localizedTextService.Localize( "validation", "entriesShort", [configuration.ValidationLimit.Min.ToString(), (configuration.ValidationLimit.Min - data.Ids.Length).ToString()]), ["value"])); } if (configuration.ValidationLimit.Max is not null && data.Ids.Length > configuration.ValidationLimit.Max) { validationResults.Add(new ValidationResult( _localizedTextService.Localize( "validation", "entriesExceed", [configuration.ValidationLimit.Max.ToString(), (data.Ids.Length - configuration.ValidationLimit.Max).ToString() ]), ["value"])); } return validationResults; } } } internal sealed class EntityDataPickerDto { public string[] Ids { get; set; } = []; } }