Refactor PartialView.IsValid with logic found in SaveFileController

Refactor FileService.CreatePartialView to use Attempt so that it gets rid of PartialView.SaveSucceeded
Refactor SaveFileController to move all saving logic into the FileService
Added SavingPartialView and SavedPartialView events to the FileService
This commit is contained in:
Sebastiaan Janssen
2014-08-19 12:51:07 +02:00
parent 32057bd7ee
commit 1805857eea
4 changed files with 90 additions and 72 deletions

View File

@@ -28,10 +28,18 @@ namespace Umbraco.Core.Models
/// <returns>True if file is valid, otherwise false</returns>
public override bool IsValid()
{
//Validate extension
return IOHelper.VerifyFileExtension(Path, new List<string> { "cshtml" });
//TODO: Validate using the macro engine
//var engine = MacroEngineFactory.GetEngine(PartialViewMacroEngine.EngineName);
//engine.Validate(...)
var validatePath = IOHelper.ValidateEditPath(IOHelper.MapPath(Path), BasePath);
var verifyFileExtension = IOHelper.VerifyFileExtension(Path, new List<string> { "cshtml" });
return validatePath && verifyFileExtension;
}
public string OldFileName { get; set; }
public string FileName { get; set; }
public string SnippetName { get; set; }
@@ -48,8 +56,6 @@ namespace Umbraco.Core.Models
public string ReturnUrl { get; set; }
public bool SaveSucceeded { get; set; }
internal Regex HeaderMatch
{
get { return _headerMatch; }

View File

@@ -1,6 +1,7 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Runtime.Remoting.Messaging;
using System.Text;
using System.Web;
using Umbraco.Core.Auditing;
@@ -367,24 +368,25 @@ namespace Umbraco.Core.Services
return template.IsValid();
}
internal PartialView CreatePartialView(PartialView partialView)
internal Attempt<PartialView> CreatePartialView(PartialView partialView)
{
var partialViewsFileSystem = new PhysicalFileSystem(partialView.BasePath);
var relativeFilePath = partialView.ParentFolderName.EnsureEndsWith('/') + partialViewsFileSystem.GetRelativePath(partialView.FileName);
partialView.ReturnUrl = string.Format(partialView.EditViewFile + "?file={0}", HttpUtility.UrlEncode(relativeFilePath));
//return the link to edit the file if it already exists
if (partialViewsFileSystem.FileExists(partialView.Path))
{
partialView.ReturnUrl = string.Format(partialView.EditViewFile + "?file={0}", HttpUtility.UrlEncode(relativeFilePath));
partialView.SaveSucceeded = true;
return partialView;
}
return Attempt<PartialView>.Succeed(partialView);
if (CreatingPartialView.IsRaisedEventCancelled(new NewEventArgs<PartialView>(partialView, true, partialView.Alias, -1), this))
{
LogHelper.Info<FileService>(string.Format("Creating Partial View {0} was cancelled by an event handler.", partialViewsFileSystem.GetFullPath(partialView.FileName)));
partialView.SaveSucceeded = false;
return partialView;
// We have nowhere to return to, clear ReturnUrl
partialView.ReturnUrl = string.Empty;
var failureMessage = string.Format("Creating Partial View {0} was cancelled by an event handler.", partialViewsFileSystem.GetFullPath(partialView.FileName));
LogHelper.Info<FileService>(failureMessage);
return Attempt<PartialView>.Fail(partialView, new ArgumentException(failureMessage));
}
//create the file
@@ -411,12 +413,10 @@ namespace Umbraco.Core.Services
if (partialView.CreateMacro)
CreatePartialViewMacro(partialView);
partialView.ReturnUrl = string.Format(partialView.EditViewFile + "?file={0}", HttpUtility.UrlEncode(relativeFilePath));
CreatedPartialView.RaiseEvent(new NewEventArgs<PartialView>(partialView, false, partialView.Alias, -1), this);
return partialView;
return Attempt<PartialView>.Succeed(partialView);
}
internal static void CreatePartialViewMacro(PartialView partialView)
@@ -459,6 +459,46 @@ namespace Umbraco.Core.Services
return true;
}
internal Attempt<PartialView> SavePartialView(PartialView partialView, int userId = 0)
{
if (SavingPartialView.IsRaisedEventCancelled(new SaveEventArgs<PartialView>(partialView, true), this))
{
return Attempt<PartialView>.Fail(new ArgumentException("Save was cancelled by an event handler " + partialView.FileName));
}
//Directory check.. only allow files in script dir and below to be edited
if (partialView.IsValid() == false)
{
return Attempt<PartialView>.Fail(
new ArgumentException(string.Format("Illegal path: {0} or illegal file extension {1}",
partialView.Path,
partialView.FileName.Substring(partialView.FileName.LastIndexOf(".", StringComparison.Ordinal)))));
}
//NOTE: I've left the below here just for informational purposes. If we save a file this way, then the UTF8
// BOM mucks everything up, strangely, if we use WriteAllText everything is ok!
// http://issues.umbraco.org/issue/U4-2118
//using (var sw = System.IO.File.CreateText(savePath))
//{
// sw.Write(val);
//}
System.IO.File.WriteAllText(partialView.Path, partialView.Content, Encoding.UTF8);
//deletes the old file
if (partialView.FileName != partialView.OldFileName)
{
// Create a new PartialView class so that we can set the FileName of the file that needs deleting
var deletePartial = partialView;
deletePartial.FileName = partialView.OldFileName;
DeletePartialView(deletePartial, userId);
}
SavedPartialView.RaiseEvent(new SaveEventArgs<PartialView>(partialView), this);
return Attempt.Succeed(partialView);
}
//TODO Method to change name and/or alias of view/masterpage template
#region Event Handlers
@@ -522,6 +562,16 @@ namespace Umbraco.Core.Services
/// </summary>
public static event TypedEventHandler<IFileService, SaveEventArgs<Stylesheet>> SavedStylesheet;
/// <summary>
/// Occurs before Save
/// </summary>
internal static event TypedEventHandler<IFileService, SaveEventArgs<PartialView>> SavingPartialView;
/// <summary>
/// Occurs after Save
/// </summary>
internal static event TypedEventHandler<IFileService, SaveEventArgs<PartialView>> SavedPartialView;
/// <summary>
/// Occurs before Create
/// </summary>
@@ -543,5 +593,6 @@ namespace Umbraco.Core.Services
internal static event TypedEventHandler<IFileService, DeleteEventArgs<PartialView>> DeletedPartialView;
#endregion
}
}

View File

@@ -5,6 +5,7 @@ using System.Web.Mvc;
using Umbraco.Core.Events;
using Umbraco.Core.IO;
using Umbraco.Core.Logging;
using Umbraco.Core.Models;
using Umbraco.Core.Services;
using Umbraco.Web.Macros;
using Umbraco.Web.Mvc;
@@ -38,57 +39,27 @@ namespace Umbraco.Web.WebServices
public JsonResult SavePartialView(string filename, string oldName, string contents)
{
var folderPath = SystemDirectories.MvcViews.EnsureEndsWith('/');// +"/Partials/";
// validate file
IOHelper.ValidateEditPath(IOHelper.MapPath(folderPath + filename), folderPath);
// validate extension
IOHelper.ValidateFileExtension(IOHelper.MapPath(folderPath + filename), new[] { "cshtml" }.ToList());
//TODO: Validate using the macro engine
var engine = MacroEngineFactory.GetEngine(PartialViewMacroEngine.EngineName);
//engine.Validate(...)
var val = contents;
var saveOldPath = oldName.StartsWith("~/") ? IOHelper.MapPath(oldName) : IOHelper.MapPath(folderPath + oldName);
var savePath = filename.StartsWith("~/") ? IOHelper.MapPath(filename) : IOHelper.MapPath(folderPath + filename);
//Directory check.. only allow files in script dir and below to be edited
if (!savePath.StartsWith(IOHelper.MapPath(folderPath)))
var partialView = new PartialView(savePath)
{
BasePath = folderPath,
OldFileName = oldName,
FileName = filename,
Content = contents,
};
var fileService = new FileService();
var attempt = fileService.SavePartialView(partialView);
if (attempt.Success == false)
{
return Failed(
ui.Text("speechBubbles", "partialViewErrorText"), ui.Text("speechBubbles", "partialViewErrorHeader"),
//pass in a new exception ... this will also append the the message
new ArgumentException("Illegal path: " + savePath));
attempt.Exception);
}
if (Saving.IsRaisedEventCancelled(new SaveEventArgs<string>(savePath), this))
{
return Failed(
ui.Text("speechBubbles", "partialViewErrorText"), ui.Text("speechBubbles", "partialViewErrorHeader"),
//pass in a new exception ... this will also append the the message
new ArgumentException("Save was cancelled by an event handler " + savePath));
}
//deletes the old file
if (savePath != saveOldPath)
{
if (System.IO.File.Exists(saveOldPath))
System.IO.File.Delete(saveOldPath);
}
//NOTE: I've left the below here just for informational purposes. If we save a file this way, then the UTF8
// BOM mucks everything up, strangely, if we use WriteAllText everything is ok!
// http://issues.umbraco.org/issue/U4-2118
//using (var sw = System.IO.File.CreateText(savePath))
//{
// sw.Write(val);
//}
System.IO.File.WriteAllText(savePath, val, Encoding.UTF8);
Saved.RaiseEvent(new SaveEventArgs<string>(savePath, false), this);
return Success(ui.Text("speechBubbles", "partialViewSavedText"), ui.Text("speechBubbles", "partialViewSavedHeader"));
}
@@ -185,15 +156,5 @@ namespace Umbraco.Web.WebServices
message = message + (exception == null ? "" : (exception.Message + ". Check log for details."))
});
}
/// <summary>
/// Occurs before Create
/// </summary>
internal static event TypedEventHandler<SaveFileController, SaveEventArgs<string>> Saving;
/// <summary>
/// Occurs after Create
/// </summary>
internal static event TypedEventHandler<SaveFileController, SaveEventArgs<string>> Saved;
}
}

View File

@@ -65,11 +65,11 @@ namespace umbraco
};
var fileService = new FileService();
var partialView = fileService.CreatePartialView(model);
var attempt = fileService.CreatePartialView(model);
_returnUrl = partialView.ReturnUrl;
_returnUrl = attempt.Result.ReturnUrl;
return partialView.SaveSucceeded;
return attempt.Success;
}
public override bool PerformDelete()