Merge branch 'v8/dev' into v8/feature/2438AB-RTE-Image-Config-MediaFolder

# Conflicts:
#	src/Umbraco.Web/PropertyEditors/GridPropertyEditor.cs
#	src/Umbraco.Web/PropertyEditors/RichTextPropertyEditor.cs
#	src/Umbraco.Web/Templates/TemplateUtilities.cs
This commit is contained in:
Warren Buckley
2019-09-13 09:51:53 +01:00
7 changed files with 102 additions and 46 deletions

View File

@@ -10,6 +10,7 @@ using Umbraco.Core.Logging;
using Umbraco.Core.Models;
using Umbraco.Web.PropertyEditors;
using Umbraco.Core.Services;
using Umbraco.Web;
namespace Umbraco.Tests.PublishedContent
{
@@ -39,7 +40,7 @@ namespace Umbraco.Tests.PublishedContent
var converters = Factory.GetInstance<PropertyValueConverterCollection>();
var dataTypeService = new TestObjects.TestDataTypeService(
new DataType(new RichTextPropertyEditor(Mock.Of<ILogger>(), Mock.Of<IMediaService>(), Mock.Of<IContentTypeBaseServiceProvider>())) { Id = 1 });
new DataType(new RichTextPropertyEditor(Mock.Of<ILogger>(), Mock.Of<IMediaService>(), Mock.Of<IContentTypeBaseServiceProvider>(), Mock.Of<IUmbracoContextAccessor>())) { Id = 1 });
var publishedContentTypeFactory = new PublishedContentTypeFactory(Mock.Of<IPublishedModelFactory>(), converters, dataTypeService);

View File

@@ -44,11 +44,12 @@ namespace Umbraco.Tests.PublishedContent
var logger = Mock.Of<ILogger>();
var mediaService = Mock.Of<IMediaService>();
var contentTypeBaseServiceProvider = Mock.Of<IContentTypeBaseServiceProvider>();
var umbracoContextAccessor = Mock.Of<IUmbracoContextAccessor>();
var dataTypeService = new TestObjects.TestDataTypeService(
new DataType(new VoidEditor(logger)) { Id = 1 },
new DataType(new TrueFalsePropertyEditor(logger)) { Id = 1001 },
new DataType(new RichTextPropertyEditor(logger, mediaService, contentTypeBaseServiceProvider)) { Id = 1002 },
new DataType(new RichTextPropertyEditor(logger, mediaService, contentTypeBaseServiceProvider, umbracoContextAccessor)) { Id = 1002 },
new DataType(new IntegerPropertyEditor(logger)) { Id = 1003 },
new DataType(new TextboxPropertyEditor(logger)) { Id = 1004 },
new DataType(new MediaPickerPropertyEditor(logger)) { Id = 1005 });

View File

@@ -523,10 +523,10 @@ function tinyMceService($rootScope, $q, imageHelper, $locale, $http, $timeout, s
if (editor.settings.maxImageSize && editor.settings.maxImageSize !== 0) {
var newSize = imageHelper.scaleToMaxSize(editor.settings.maxImageSize, size.w, size.h);
var s = "width: " + newSize.width + "px; height:" + newSize.height + "px;";
editor.dom.setAttrib(imgElm, 'style', s);
editor.dom.setAttrib(imgElm, 'width', newSize.width);
editor.dom.setAttrib(imgElm, 'height', newSize.height);
if (img.url) {
var src = img.url + "?width=" + newSize.width + "&height=" + newSize.height;
editor.dom.setAttrib(imgElm, 'data-mce-src', src);

View File

@@ -1,26 +1,34 @@
using System.Net;
using System.Net.Http;
using System.Web.Http;
using Umbraco.Core.Services;
using Umbraco.Web.WebApi;
using Umbraco.Core;
using Umbraco.Web.Mvc;
using Umbraco.Core.IO;
using System;
using System.IO;
using System.Threading.Tasks;
using Umbraco.Web.Composing;
using Umbraco.Core.Configuration.UmbracoSettings;
using System.Linq;
using System;
using System.Net;
using System.Net.Http;
using System.Threading.Tasks;
using System.Web.Http;
using Umbraco.Core;
using Umbraco.Core.Configuration.UmbracoSettings;
using Umbraco.Core.IO;
using Umbraco.Core.Logging;
using Umbraco.Core.Services;
using Umbraco.Web.Composing;
using Umbraco.Web.Mvc;
using Umbraco.Web.WebApi;
using Umbraco.Web.WebApi.Filters;
using Constants = Umbraco.Core.Constants;
namespace Umbraco.Web.Editors
{
[PluginController("UmbracoApi")]
[UmbracoApplicationAuthorize(
Constants.Applications.Content,
Constants.Applications.Media,
Constants.Applications.Members)]
public class TinyMceController : UmbracoAuthorizedApiController
{
private IMediaService _mediaService;
private IContentTypeBaseServiceProvider _contentTypeBaseServiceProvider;
public TinyMceController(IMediaService mediaService, IContentTypeBaseServiceProvider contentTypeBaseServiceProvider)
{
_mediaService = mediaService;
@@ -91,9 +99,28 @@ namespace Umbraco.Web.Editors
}
catch (Exception ex)
{
// Could be a file permission ex
throw;
}
// IOException, PathTooLong, DirectoryNotFound, UnathorizedAccess
Logger.Error<TinyMceController>(ex, "Error when trying to move {CurrentFilePath} to {NewFilePath}", currentFile, newFilePath);
return Request.CreateErrorResponse(HttpStatusCode.InternalServerError, $"Error when trying to move {currentFile} to {newFilePath}", ex);
}
// Now remove all old files so that the temp folder(s) never grow
// Anything older than one day gets deleted
var tempFiles = Directory.GetFiles(SystemDirectories.TempFileUploads, "*", SearchOption.AllDirectories);
foreach (var tempFile in tempFiles)
{
if (DateTime.UtcNow - File.GetLastWriteTimeUtc(tempFile) > TimeSpan.FromDays(1))
{
try
{
File.Delete(tempFile);
}
catch (Exception ex)
{
Logger.Error<TinyMceController>(ex, "Could not delete temp file {FileName}", tempFile);
}
}
}
return Request.CreateResponse(HttpStatusCode.OK, new { tmpLocation = relativeNewFilePath });
}

View File

@@ -1,14 +1,13 @@
using System.Linq;
using Umbraco.Core.Logging;
using Newtonsoft.Json;
using System;
using System.Linq;
using Umbraco.Core;
using Umbraco.Core.PropertyEditors;
using Newtonsoft.Json;
using Umbraco.Core.Logging;
using Umbraco.Core.Models;
using Umbraco.Core.Models.Editors;
using Umbraco.Web.Templates;
using Umbraco.Web.Composing;
using Umbraco.Core.PropertyEditors;
using Umbraco.Core.Services;
using System;
using Umbraco.Web.Templates;
namespace Umbraco.Web.PropertyEditors
{
@@ -27,12 +26,16 @@ namespace Umbraco.Web.PropertyEditors
{
private IMediaService _mediaService;
private IContentTypeBaseServiceProvider _contentTypeBaseServiceProvider;
private IUmbracoContextAccessor _umbracoContextAccessor;
private ILogger _logger;
public GridPropertyEditor(ILogger logger, IMediaService mediaService, IContentTypeBaseServiceProvider contentTypeBaseServiceProvider)
public GridPropertyEditor(ILogger logger, IMediaService mediaService, IContentTypeBaseServiceProvider contentTypeBaseServiceProvider, IUmbracoContextAccessor umbracoContextAccessor)
: base(logger)
{
_mediaService = mediaService;
_contentTypeBaseServiceProvider = contentTypeBaseServiceProvider;
_umbracoContextAccessor = umbracoContextAccessor;
_logger = logger;
}
public override IPropertyIndexValueFactory PropertyIndexValueFactory => new GridPropertyIndexValueFactory();
@@ -41,7 +44,7 @@ namespace Umbraco.Web.PropertyEditors
/// Overridden to ensure that the value is validated
/// </summary>
/// <returns></returns>
protected override IDataValueEditor CreateValueEditor() => new GridPropertyValueEditor(Attribute, _mediaService, _contentTypeBaseServiceProvider);
protected override IDataValueEditor CreateValueEditor() => new GridPropertyValueEditor(Attribute, _mediaService, _contentTypeBaseServiceProvider, _umbracoContextAccessor, _logger);
protected override IConfigurationEditor CreateConfigurationEditor() => new GridConfigurationEditor();
@@ -49,12 +52,16 @@ namespace Umbraco.Web.PropertyEditors
{
private IMediaService _mediaService;
private IContentTypeBaseServiceProvider _contentTypeBaseServiceProvider;
private IUmbracoContextAccessor _umbracoContextAccessor;
private ILogger _logger;
public GridPropertyValueEditor(DataEditorAttribute attribute, IMediaService mediaService, IContentTypeBaseServiceProvider contentTypeBaseServiceProvider)
public GridPropertyValueEditor(DataEditorAttribute attribute, IMediaService mediaService, IContentTypeBaseServiceProvider contentTypeBaseServiceProvider, IUmbracoContextAccessor umbracoContextAccessor, ILogger logger)
: base(attribute)
{
_mediaService = mediaService;
_contentTypeBaseServiceProvider = contentTypeBaseServiceProvider;
_umbracoContextAccessor = umbracoContextAccessor;
_logger = logger;
}
/// <summary>
@@ -91,10 +98,10 @@ namespace Umbraco.Web.PropertyEditors
{
// Parse the HTML
var html = rte.Value?.ToString();
var userId = Current.UmbracoContext.Security.CurrentUser.Id;
var parsedHtml = TemplateUtilities.FindAndPersistPastedTempImages(html, mediaParentId, userId, _mediaService, _contentTypeBaseServiceProvider);
var userId = _umbracoContextAccessor.UmbracoContext?.Security.CurrentUser.Id ?? -1;
var parsedHtml = TemplateUtilities.FindAndPersistPastedTempImages(html, mediaParentId, userId, _mediaService, _contentTypeBaseServiceProvider, _logger);
rte.Value = parsedHtml;
}

View File

@@ -1,15 +1,11 @@
using HtmlAgilityPack;
using System;
using System;
using System.Collections.Generic;
using System.IO;
using Umbraco.Core;
using Umbraco.Core.IO;
using Umbraco.Core.Logging;
using Umbraco.Core.Models;
using Umbraco.Core.PropertyEditors;
using Umbraco.Core.Services;
using Umbraco.Examine;
using Umbraco.Web.Composing;
using Umbraco.Web.Macros;
using Umbraco.Web.Templates;
@@ -30,21 +26,25 @@ namespace Umbraco.Web.PropertyEditors
{
private IMediaService _mediaService;
private IContentTypeBaseServiceProvider _contentTypeBaseServiceProvider;
private IUmbracoContextAccessor _umbracoContextAccessor;
private ILogger _logger;
/// <summary>
/// The constructor will setup the property editor based on the attribute if one is found
/// </summary>
public RichTextPropertyEditor(ILogger logger, IMediaService mediaService, IContentTypeBaseServiceProvider contentTypeBaseServiceProvider) : base(logger)
public RichTextPropertyEditor(ILogger logger, IMediaService mediaService, IContentTypeBaseServiceProvider contentTypeBaseServiceProvider, IUmbracoContextAccessor umbracoContextAccessor) : base(logger)
{
_mediaService = mediaService;
_contentTypeBaseServiceProvider = contentTypeBaseServiceProvider;
_umbracoContextAccessor = umbracoContextAccessor;
_logger = logger;
}
/// <summary>
/// Create a custom value editor
/// </summary>
/// <returns></returns>
protected override IDataValueEditor CreateValueEditor() => new RichTextPropertyValueEditor(Attribute, _mediaService, _contentTypeBaseServiceProvider);
protected override IDataValueEditor CreateValueEditor() => new RichTextPropertyValueEditor(Attribute, _mediaService, _contentTypeBaseServiceProvider, _umbracoContextAccessor, _logger);
protected override IConfigurationEditor CreateConfigurationEditor() => new RichTextConfigurationEditor();
@@ -57,12 +57,16 @@ namespace Umbraco.Web.PropertyEditors
{
private IMediaService _mediaService;
private IContentTypeBaseServiceProvider _contentTypeBaseServiceProvider;
private IUmbracoContextAccessor _umbracoContextAccessor;
private ILogger _logger;
public RichTextPropertyValueEditor(DataEditorAttribute attribute, IMediaService mediaService, IContentTypeBaseServiceProvider contentTypeBaseServiceProvider)
public RichTextPropertyValueEditor(DataEditorAttribute attribute, IMediaService mediaService, IContentTypeBaseServiceProvider contentTypeBaseServiceProvider, IUmbracoContextAccessor umbracoContextAccessor, ILogger logger)
: base(attribute)
{
_mediaService = mediaService;
_contentTypeBaseServiceProvider = contentTypeBaseServiceProvider;
_umbracoContextAccessor = umbracoContextAccessor;
_logger = logger;
}
/// <inheritdoc />
@@ -113,7 +117,7 @@ namespace Umbraco.Web.PropertyEditors
var editorValueWithMediaUrlsRemoved = TemplateUtilities.RemoveMediaUrlsFromTextString(editorValue.Value.ToString());
var parsed = MacroTagParser.FormatRichTextContentForPersistence(editorValueWithMediaUrlsRemoved);
var userId = Current.UmbracoContext.Security.CurrentUser.Id;
var userId = _umbracoContextAccessor.UmbracoContext?.Security.CurrentUser.Id ?? -1;
var config = editorValue.DataTypeConfiguration as RichTextConfiguration;
var mediaParent = config?.MediaParentId;
@@ -124,7 +128,7 @@ namespace Umbraco.Web.PropertyEditors
else
mediaParentId = mediaParent.Guid;
parsed = TemplateUtilities.FindAndPersistPastedTempImages(parsed, mediaParentId, userId, _mediaService, _contentTypeBaseServiceProvider);
parsed = TemplateUtilities.FindAndPersistPastedTempImages(parsed, mediaParentId, userId, _mediaService, _contentTypeBaseServiceProvider, _logger);
return parsed;
}
}

View File

@@ -3,13 +3,14 @@ using System;
using System.IO;
using System.Text.RegularExpressions;
using Umbraco.Core;
using Umbraco.Core.Configuration;
using Umbraco.Core.IO;
using Umbraco.Core.Logging;
using Umbraco.Core.Models;
using Umbraco.Core.Services;
using Umbraco.Web.Composing;
using Umbraco.Web.PublishedCache;
using Umbraco.Web.Routing;
using File = System.IO.File;
namespace Umbraco.Web.Templates
{
@@ -190,7 +191,7 @@ namespace Umbraco.Web.Templates
// see comment in ResolveMediaFromTextString for group reference
=> ResolveImgPattern.Replace(text, "$1$3$4$5");
internal static string FindAndPersistPastedTempImages(string html, Guid mediaParentFolder, int userId, IMediaService mediaService, IContentTypeBaseServiceProvider contentTypeBaseServiceProvider)
internal static string FindAndPersistPastedTempImages(string html, Guid mediaParentFolder, int userId, IMediaService mediaService, IContentTypeBaseServiceProvider contentTypeBaseServiceProvider, ILogger logger)
{
// Find all img's that has data-tmpimg attribute
// Use HTML Agility Pack - https://html-agility-pack.net
@@ -243,6 +244,21 @@ namespace Umbraco.Web.Templates
// Remove the data attribute (so we do not re-process this)
img.Attributes.Remove(TemporaryImageDataAttribute);
// Delete folder & image now its saved in media
// The folder should contain one image - as a unique guid folder created
// for each image uploaded from TinyMceController
var folderName = Path.GetDirectoryName(absoluteTempImagePath);
try
{
File.Delete(absoluteTempImagePath);
Directory.Delete(folderName);
}
catch (Exception ex)
{
logger.Error(typeof(TemplateUtilities), ex, "Could not delete temp file or folder {FileName}", absoluteTempImagePath);
}
}
return htmlDoc.DocumentNode.OuterHtml;