2018-06-29 19:52:40 +02:00
|
|
|
|
using System;
|
|
|
|
|
|
using System.Collections.Generic;
|
|
|
|
|
|
using System.Linq;
|
|
|
|
|
|
using Umbraco.Core;
|
2018-08-29 01:15:46 +10:00
|
|
|
|
using Umbraco.Core.Configuration.UmbracoSettings;
|
2018-06-29 19:52:40 +02:00
|
|
|
|
using Umbraco.Core.IO;
|
|
|
|
|
|
using Umbraco.Core.Logging;
|
|
|
|
|
|
using Umbraco.Core.Models;
|
|
|
|
|
|
using Umbraco.Core.PropertyEditors;
|
|
|
|
|
|
using Umbraco.Core.Services;
|
2019-12-20 17:36:44 +01:00
|
|
|
|
using Umbraco.Core.Strings;
|
2018-08-29 01:15:46 +10:00
|
|
|
|
using Umbraco.Web.Media;
|
2018-04-04 13:11:12 +10:00
|
|
|
|
|
2018-06-29 19:52:40 +02:00
|
|
|
|
namespace Umbraco.Web.PropertyEditors
|
|
|
|
|
|
{
|
2019-06-07 17:59:38 +01:00
|
|
|
|
[DataEditor(
|
|
|
|
|
|
Constants.PropertyEditors.Aliases.UploadField,
|
|
|
|
|
|
"File upload",
|
|
|
|
|
|
"fileupload",
|
|
|
|
|
|
Group = Constants.PropertyEditors.Groups.Media,
|
|
|
|
|
|
Icon = "icon-download-alt")]
|
2020-02-19 16:37:00 +11:00
|
|
|
|
public class FileUploadPropertyEditor : DataEditor, IMediaUrlGenerator
|
2018-06-29 19:52:40 +02:00
|
|
|
|
{
|
2018-10-26 15:06:53 +02:00
|
|
|
|
private readonly IMediaFileSystem _mediaFileSystem;
|
2020-03-12 15:30:22 +01:00
|
|
|
|
private readonly IContentSettings _contentSettings;
|
2018-08-29 01:15:46 +10:00
|
|
|
|
private readonly UploadAutoFillProperties _uploadAutoFillProperties;
|
2019-11-12 13:40:07 +01:00
|
|
|
|
private readonly IDataTypeService _dataTypeService;
|
|
|
|
|
|
private readonly ILocalizationService _localizationService;
|
2020-01-07 13:08:21 +01:00
|
|
|
|
private readonly ILocalizedTextService _localizedTextService;
|
2018-06-29 19:52:40 +02:00
|
|
|
|
|
2020-03-12 15:30:22 +01:00
|
|
|
|
public FileUploadPropertyEditor(ILogger logger, IMediaFileSystem mediaFileSystem, IContentSettings contentSettings, IDataTypeService dataTypeService, ILocalizationService localizationService, ILocalizedTextService localizedTextService, IShortStringHelper shortStringHelper)
|
2020-01-07 13:08:21 +01:00
|
|
|
|
: base(logger, dataTypeService, localizationService, localizedTextService, shortStringHelper)
|
2018-06-29 19:52:40 +02:00
|
|
|
|
{
|
|
|
|
|
|
_mediaFileSystem = mediaFileSystem ?? throw new ArgumentNullException(nameof(mediaFileSystem));
|
2020-03-12 15:30:22 +01:00
|
|
|
|
_contentSettings = contentSettings;
|
2019-11-12 13:40:07 +01:00
|
|
|
|
_dataTypeService = dataTypeService;
|
|
|
|
|
|
_localizationService = localizationService;
|
2020-01-07 13:08:21 +01:00
|
|
|
|
_localizedTextService = localizedTextService;
|
2020-03-12 15:30:22 +01:00
|
|
|
|
_uploadAutoFillProperties = new UploadAutoFillProperties(_mediaFileSystem, logger, contentSettings);
|
2018-06-29 19:52:40 +02:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// Creates the corresponding property value editor.
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
/// <returns>The corresponding property value editor.</returns>
|
|
|
|
|
|
protected override IDataValueEditor CreateValueEditor()
|
|
|
|
|
|
{
|
2020-03-12 15:30:22 +01:00
|
|
|
|
var editor = new FileUploadPropertyValueEditor(Attribute, _mediaFileSystem, _dataTypeService, _localizationService, _localizedTextService, ShortStringHelper, _contentSettings);
|
|
|
|
|
|
editor.Validators.Add(new UploadFileTypeValidator(_localizedTextService, _contentSettings));
|
2018-06-29 19:52:40 +02:00
|
|
|
|
return editor;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2020-02-19 16:37:00 +11:00
|
|
|
|
public bool TryGetMediaPath(string alias, object value, out string mediaPath)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (alias == Alias)
|
|
|
|
|
|
{
|
|
|
|
|
|
mediaPath = value?.ToString();
|
|
|
|
|
|
return true;
|
|
|
|
|
|
}
|
|
|
|
|
|
mediaPath = null;
|
|
|
|
|
|
return false;
|
|
|
|
|
|
}
|
2019-10-21 22:21:23 +02:00
|
|
|
|
|
2018-06-29 19:52:40 +02:00
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// Gets a value indicating whether a property is an upload field.
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
/// <param name="property">The property.</param>
|
2019-01-26 10:52:19 -05:00
|
|
|
|
/// <returns>A value indicating whether a property is an upload field, and (optionally) has a non-empty value.</returns>
|
2019-11-08 15:10:05 +01:00
|
|
|
|
private static bool IsUploadField(IProperty property)
|
2018-06-29 19:52:40 +02:00
|
|
|
|
{
|
|
|
|
|
|
return property.PropertyType.PropertyEditorAlias == Constants.PropertyEditors.Aliases.UploadField;
|
|
|
|
|
|
}
|
2019-11-05 13:45:42 +01:00
|
|
|
|
|
2018-06-29 19:52:40 +02:00
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// Ensures any files associated are removed
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
/// <param name="deletedEntities"></param>
|
|
|
|
|
|
internal IEnumerable<string> ServiceDeleted(IEnumerable<ContentBase> deletedEntities)
|
|
|
|
|
|
{
|
|
|
|
|
|
return deletedEntities.SelectMany(x => x.Properties)
|
|
|
|
|
|
.Where(IsUploadField)
|
|
|
|
|
|
.SelectMany(GetFilePathsFromPropertyValues)
|
|
|
|
|
|
.Distinct();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
2019-01-26 10:52:19 -05:00
|
|
|
|
/// Look through all property values stored against the property and resolve any file paths stored
|
2018-06-29 19:52:40 +02:00
|
|
|
|
/// </summary>
|
|
|
|
|
|
/// <param name="prop"></param>
|
|
|
|
|
|
/// <returns></returns>
|
2019-11-08 15:10:05 +01:00
|
|
|
|
private IEnumerable<string> GetFilePathsFromPropertyValues(IProperty prop)
|
2018-06-29 19:52:40 +02:00
|
|
|
|
{
|
|
|
|
|
|
var propVals = prop.Values;
|
|
|
|
|
|
foreach (var propertyValue in propVals)
|
2018-04-04 13:11:12 +10:00
|
|
|
|
{
|
2018-06-29 19:52:40 +02:00
|
|
|
|
//check if the published value contains data and return it
|
2018-04-04 13:11:12 +10:00
|
|
|
|
var propVal = propertyValue.PublishedValue;
|
2018-06-29 19:52:40 +02:00
|
|
|
|
if (propVal != null && propVal is string str1 && !str1.IsNullOrWhiteSpace())
|
|
|
|
|
|
yield return _mediaFileSystem.GetRelativePath(str1);
|
|
|
|
|
|
|
|
|
|
|
|
//check if the edited value contains data and return it
|
|
|
|
|
|
propVal = propertyValue.EditedValue;
|
|
|
|
|
|
if (propVal != null && propVal is string str2 && !str2.IsNullOrWhiteSpace())
|
|
|
|
|
|
yield return _mediaFileSystem.GetRelativePath(str2);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// After a content has been copied, also copy uploaded files.
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
/// <param name="sender">The event sender.</param>
|
|
|
|
|
|
/// <param name="args">The event arguments.</param>
|
|
|
|
|
|
internal void ContentServiceCopied(IContentService sender, Core.Events.CopyEventArgs<IContent> args)
|
|
|
|
|
|
{
|
|
|
|
|
|
// get the upload field properties with a value
|
|
|
|
|
|
var properties = args.Original.Properties.Where(IsUploadField);
|
|
|
|
|
|
|
|
|
|
|
|
// copy files
|
|
|
|
|
|
var isUpdated = false;
|
|
|
|
|
|
foreach (var property in properties)
|
|
|
|
|
|
{
|
|
|
|
|
|
//copy each of the property values (variants, segments) to the destination
|
|
|
|
|
|
foreach (var propertyValue in property.Values)
|
|
|
|
|
|
{
|
|
|
|
|
|
var propVal = property.GetValue(propertyValue.Culture, propertyValue.Segment);
|
|
|
|
|
|
if (propVal == null || !(propVal is string str) || str.IsNullOrWhiteSpace()) continue;
|
|
|
|
|
|
var sourcePath = _mediaFileSystem.GetRelativePath(str);
|
|
|
|
|
|
var copyPath = _mediaFileSystem.CopyFile(args.Copy, property.PropertyType, sourcePath);
|
|
|
|
|
|
args.Copy.SetValue(property.Alias, _mediaFileSystem.GetUrl(copyPath), propertyValue.Culture, propertyValue.Segment);
|
|
|
|
|
|
isUpdated = true;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// if updated, re-save the copy with the updated value
|
|
|
|
|
|
if (isUpdated)
|
|
|
|
|
|
sender.Save(args.Copy);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// After a media has been created, auto-fill the properties.
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
/// <param name="sender">The event sender.</param>
|
|
|
|
|
|
/// <param name="args">The event arguments.</param>
|
|
|
|
|
|
internal void MediaServiceCreated(IMediaService sender, Core.Events.NewEventArgs<IMedia> args)
|
|
|
|
|
|
{
|
|
|
|
|
|
AutoFillProperties(args.Entity);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// After a media has been saved, auto-fill the properties.
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
/// <param name="sender">The event sender.</param>
|
|
|
|
|
|
/// <param name="args">The event arguments.</param>
|
|
|
|
|
|
internal void MediaServiceSaving(IMediaService sender, Core.Events.SaveEventArgs<IMedia> args)
|
|
|
|
|
|
{
|
|
|
|
|
|
foreach (var entity in args.SavedEntities)
|
|
|
|
|
|
AutoFillProperties(entity);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// After a content item has been saved, auto-fill the properties.
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
/// <param name="sender">The event sender.</param>
|
|
|
|
|
|
/// <param name="args">The event arguments.</param>
|
|
|
|
|
|
internal void ContentServiceSaving(IContentService sender, Core.Events.SaveEventArgs<IContent> args)
|
|
|
|
|
|
{
|
|
|
|
|
|
foreach (var entity in args.SavedEntities)
|
|
|
|
|
|
AutoFillProperties(entity);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// Auto-fill properties (or clear).
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
private void AutoFillProperties(IContentBase model)
|
|
|
|
|
|
{
|
|
|
|
|
|
var properties = model.Properties.Where(IsUploadField);
|
|
|
|
|
|
|
|
|
|
|
|
foreach (var property in properties)
|
|
|
|
|
|
{
|
2020-03-12 15:30:22 +01:00
|
|
|
|
var autoFillConfig = _contentSettings.GetConfig(property.Alias);
|
2018-06-29 19:52:40 +02:00
|
|
|
|
if (autoFillConfig == null) continue;
|
|
|
|
|
|
|
|
|
|
|
|
foreach (var pvalue in property.Values)
|
|
|
|
|
|
{
|
|
|
|
|
|
var svalue = property.GetValue(pvalue.Culture, pvalue.Segment) as string;
|
|
|
|
|
|
if (string.IsNullOrWhiteSpace(svalue))
|
2018-08-29 01:15:46 +10:00
|
|
|
|
_uploadAutoFillProperties.Reset(model, autoFillConfig, pvalue.Culture, pvalue.Segment);
|
2018-06-29 19:52:40 +02:00
|
|
|
|
else
|
2018-08-29 01:15:46 +10:00
|
|
|
|
_uploadAutoFillProperties.Populate(model, autoFillConfig, _mediaFileSystem.GetRelativePath(svalue), pvalue.Culture, pvalue.Segment);
|
2018-06-29 19:52:40 +02:00
|
|
|
|
}
|
|
|
|
|
|
}
|
2018-04-04 13:11:12 +10:00
|
|
|
|
}
|
2018-06-29 19:52:40 +02:00
|
|
|
|
}
|
|
|
|
|
|
}
|