diff --git a/src/Umbraco.Core/Models/PartialView.cs b/src/Umbraco.Core/Models/PartialView.cs
new file mode 100644
index 0000000000..f963ff0e1a
--- /dev/null
+++ b/src/Umbraco.Core/Models/PartialView.cs
@@ -0,0 +1,74 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Runtime.Serialization;
+using System.Text.RegularExpressions;
+using Umbraco.Core.IO;
+
+namespace Umbraco.Core.Models
+{
+ ///
+ /// Represents a Partial View file
+ ///
+ [Serializable]
+ [DataContract(IsReference = true)]
+ internal class PartialView : File
+ {
+ private readonly Regex _headerMatch = new Regex("^@inherits\\s+?.*$", RegexOptions.Multiline | RegexOptions.Compiled);
+
+ public PartialView(string path)
+ : base(path)
+ {
+ base.Path = path;
+ }
+
+ ///
+ /// Boolean indicating whether the file could be validated
+ ///
+ /// True if file is valid, otherwise false
+ public override bool IsValid()
+ {
+ //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 { "cshtml" });
+
+ return validatePath && verifyFileExtension;
+ }
+
+ public string OldFileName { get; set; }
+
+ public string FileName { get; set; }
+
+ public string SnippetName { get; set; }
+
+ public bool CreateMacro { get; set; }
+
+ public string CodeHeader { get; set; }
+
+ public string ParentFolderName { get; set; }
+
+ public string EditViewFile { get; set; }
+
+ public string BasePath { get; set; }
+
+ public string ReturnUrl { get; set; }
+
+ internal Regex HeaderMatch
+ {
+ get { return _headerMatch; }
+ }
+
+ internal Attempt TryGetSnippetPath(string fileName)
+ {
+ var partialViewsFileSystem = new PhysicalFileSystem(BasePath);
+ var snippetPath = IOHelper.MapPath(string.Format("{0}/PartialViewMacros/Templates/{1}", SystemDirectories.Umbraco, fileName));
+
+ return partialViewsFileSystem.FileExists(snippetPath)
+ ? Attempt.Succeed(snippetPath)
+ : Attempt.Fail();
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/Umbraco.Core/Services/FileService.cs b/src/Umbraco.Core/Services/FileService.cs
index 848097f6f0..c96365f7af 100644
--- a/src/Umbraco.Core/Services/FileService.cs
+++ b/src/Umbraco.Core/Services/FileService.cs
@@ -1,7 +1,13 @@
using System;
using System.Collections.Generic;
+using System.IO;
+using System.Runtime.Remoting.Messaging;
+using System.Text;
+using System.Web;
using Umbraco.Core.Auditing;
using Umbraco.Core.Events;
+using Umbraco.Core.IO;
+using Umbraco.Core.Logging;
using Umbraco.Core.Models;
using Umbraco.Core.Persistence;
using Umbraco.Core.Persistence.Repositories;
@@ -17,19 +23,21 @@ namespace Umbraco.Core.Services
private readonly RepositoryFactory _repositoryFactory;
private readonly IUnitOfWorkProvider _fileUowProvider;
private readonly IDatabaseUnitOfWorkProvider _dataUowProvider;
+ private readonly IMacroService _macroService;
public FileService()
: this(new RepositoryFactory())
{ }
public FileService(RepositoryFactory repositoryFactory)
- : this(new FileUnitOfWorkProvider(), new PetaPocoUnitOfWorkProvider(), repositoryFactory)
+ : this(new FileUnitOfWorkProvider(), new PetaPocoUnitOfWorkProvider(), repositoryFactory, new MacroService())
{
}
- public FileService(IUnitOfWorkProvider fileProvider, IDatabaseUnitOfWorkProvider dataProvider, RepositoryFactory repositoryFactory)
+ public FileService(IUnitOfWorkProvider fileProvider, IDatabaseUnitOfWorkProvider dataProvider, RepositoryFactory repositoryFactory, IMacroService macroService)
{
_repositoryFactory = repositoryFactory;
+ _macroService = macroService;
_fileUowProvider = fileProvider;
_dataUowProvider = dataProvider;
}
@@ -362,6 +370,138 @@ namespace Umbraco.Core.Services
return template.IsValid();
}
+ // TODO: Before making this public: How to get feedback in the UI when cancelled
+ internal Attempt 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))
+ return Attempt.Succeed(partialView);
+
+ if (CreatingPartialView.IsRaisedEventCancelled(new NewEventArgs(partialView, true, partialView.Alias, -1), this))
+ {
+ // 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(failureMessage);
+
+ return Attempt.Fail(partialView, new ArgumentException(failureMessage));
+ }
+
+ //create the file
+ var snippetPathAttempt = partialView.TryGetSnippetPath(partialView.SnippetName);
+ if (snippetPathAttempt.Success == false)
+ {
+ throw new InvalidOperationException("Could not load template with name " + partialView.SnippetName);
+ }
+
+ using (var snippetFile = new StreamReader(partialViewsFileSystem.OpenFile(snippetPathAttempt.Result)))
+ {
+ var snippetContent = snippetFile.ReadToEnd().Trim();
+
+ //strip the @inherits if it's there
+ snippetContent = partialView.HeaderMatch.Replace(snippetContent, string.Empty);
+
+ var content = string.Format("{0}{1}{2}", partialView.CodeHeader, Environment.NewLine, snippetContent);
+
+ using (var stream = new MemoryStream(Encoding.UTF8.GetBytes(content)))
+ {
+ partialViewsFileSystem.AddFile(partialView.Path, stream);
+ }
+ }
+
+ if (partialView.CreateMacro)
+ CreatePartialViewMacro(partialView);
+
+ CreatedPartialView.RaiseEvent(new NewEventArgs(partialView, false, partialView.Alias, -1), this);
+
+ return Attempt.Succeed(partialView);
+ }
+
+ internal void CreatePartialViewMacro(PartialView partialView)
+ {
+ var name = partialView.FileName.Substring(0, (partialView.FileName.LastIndexOf('.') + 1))
+ .Trim('.')
+ .SplitPascalCasing()
+ .ToFirstUpperInvariant();
+
+ var macro = new Macro(name, name) { ScriptPath = partialView.BasePath + partialView.FileName };
+ _macroService.Save(macro);
+ }
+
+ // TODO: Before making this public: How to get feedback in the UI when cancelled
+ internal bool DeletePartialView(PartialView partialView, int userId = 0)
+ {
+ var partialViewsFileSystem = new PhysicalFileSystem(partialView.BasePath);
+
+ if (DeletingPartialView.IsRaisedEventCancelled(new DeleteEventArgs(partialView), this))
+ {
+ LogHelper.Info(string.Format("Deleting Partial View {0} was cancelled by an event handler.", partialViewsFileSystem.GetFullPath(partialView.FileName)));
+ return false;
+ }
+
+ if (partialViewsFileSystem.FileExists(partialView.FileName))
+ {
+ partialViewsFileSystem.DeleteFile(partialView.FileName);
+ LogHelper.Info(string.Format("Partial View file {0} deleted by user {1}", partialViewsFileSystem.GetFullPath(partialView.FileName), userId));
+ }
+ // TODO: does this ever even happen? I don't think folders show up in the tree currently.
+ // Leaving this here as it was in the original PartialViewTasks code - SJ
+ else if (partialViewsFileSystem.DirectoryExists(partialView.FileName))
+ {
+ partialViewsFileSystem.DeleteDirectory(partialView.FileName, true);
+ LogHelper.Info(string.Format("Partial View directory {0} deleted by user {1}", partialViewsFileSystem.GetFullPath(partialView.FileName), userId));
+ }
+
+ DeletedPartialView.RaiseEvent(new DeleteEventArgs(partialView, false), this);
+
+ return true;
+ }
+
+ internal Attempt SavePartialView(PartialView partialView, int userId = 0)
+ {
+ if (SavingPartialView.IsRaisedEventCancelled(new SaveEventArgs(partialView, true), this))
+ {
+ return Attempt.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.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), this);
+
+ return Attempt.Succeed(partialView);
+ }
+
//TODO Method to change name and/or alias of view/masterpage template
#region Event Handlers
@@ -425,6 +565,37 @@ namespace Umbraco.Core.Services
///
public static event TypedEventHandler> SavedStylesheet;
+ ///
+ /// Occurs before Save
+ ///
+ internal static event TypedEventHandler> SavingPartialView;
+
+ ///
+ /// Occurs after Save
+ ///
+ internal static event TypedEventHandler> SavedPartialView;
+
+ ///
+ /// Occurs before Create
+ ///
+ internal static event TypedEventHandler> CreatingPartialView;
+
+ ///
+ /// Occurs after Create
+ ///
+ internal static event TypedEventHandler> CreatedPartialView;
+
+ ///
+ /// Occurs before Delete
+ ///
+ internal static event TypedEventHandler> DeletingPartialView;
+
+ ///
+ /// Occurs after Delete
+ ///
+ internal static event TypedEventHandler> DeletedPartialView;
+
#endregion
+
}
}
\ No newline at end of file
diff --git a/src/Umbraco.Core/Services/ServiceContext.cs b/src/Umbraco.Core/Services/ServiceContext.cs
index f358e41bf3..375e1ca1ba 100644
--- a/src/Umbraco.Core/Services/ServiceContext.cs
+++ b/src/Umbraco.Core/Services/ServiceContext.cs
@@ -144,7 +144,7 @@ namespace Umbraco.Core.Services
_dataTypeService = new Lazy(() => new DataTypeService(provider, repositoryFactory.Value));
if (_fileService == null)
- _fileService = new Lazy(() => new FileService(fileProvider, provider, repositoryFactory.Value));
+ _fileService = new Lazy(() => new FileService(fileProvider, provider, repositoryFactory.Value, _macroService.Value));
if (_localizationService == null)
_localizationService = new Lazy(() => new LocalizationService(provider, repositoryFactory.Value));
diff --git a/src/Umbraco.Core/Umbraco.Core.csproj b/src/Umbraco.Core/Umbraco.Core.csproj
index 83f0aadb2b..c317594937 100644
--- a/src/Umbraco.Core/Umbraco.Core.csproj
+++ b/src/Umbraco.Core/Umbraco.Core.csproj
@@ -364,6 +364,7 @@
+
diff --git a/src/Umbraco.Web.UI/umbraco/create/PartialViewMacro.ascx.cs b/src/Umbraco.Web.UI/umbraco/create/PartialViewMacro.ascx.cs
index 056f17b157..ab017f3653 100644
--- a/src/Umbraco.Web.UI/umbraco/create/PartialViewMacro.ascx.cs
+++ b/src/Umbraco.Web.UI/umbraco/create/PartialViewMacro.ascx.cs
@@ -9,17 +9,17 @@ using umbraco.presentation.create;
namespace Umbraco.Web.UI.Umbraco.Create
{
- public partial class PartialViewMacro : UserControl
- {
-
+ public partial class PartialViewMacro : UserControl
+ {
- protected override void OnLoad(EventArgs e)
- {
- base.OnLoad(e);
- DataBind();
- LoadTemplates(PartialViewTemplate);
- }
+ protected override void OnLoad(EventArgs e)
+ {
+ base.OnLoad(e);
+ DataBind();
+
+ LoadTemplates(PartialViewTemplate);
+ }
private static void LoadTemplates(ListControl list)
{
@@ -45,44 +45,47 @@ namespace Umbraco.Web.UI.Umbraco.Create
}
}
- protected void SubmitButton_Click(object sender, EventArgs e)
- {
- if (Page.IsValid)
- {
- //Seriously, need to overhaul create dialogs, this is rediculous:
- // http://issues.umbraco.org/issue/U4-1373
+ protected void SubmitButton_Click(object sender, EventArgs e)
+ {
+ if (Page.IsValid)
+ {
+ //Seriously, need to overhaul create dialogs, this is rediculous:
+ // http://issues.umbraco.org/issue/U4-1373
+
+ var createMacroVal = 0;
+ if (CreateMacroCheckBox.Checked)
+ createMacroVal = 1;
- var createMacroVal = 0;
- if (CreateMacroCheckBox.Checked)
- createMacroVal = 1;
-
string returnUrl = dialogHandler_temp.Create(Request.GetItemAsString("nodeType"),
createMacroVal, //apparently we need to pass this value to 'ParentID'... of course! :P then we'll extract it in PartialViewTasks to create it.
PartialViewTemplate.SelectedValue + "|||" + FileName.Text);
-
- BasePage.Current.ClientTools
- .ChangeContentFrameUrl(returnUrl)
- .ChildNodeCreated()
- .CloseModalWindow();
- }
- }
- protected void MacroExistsValidator_OnServerValidate(object source, ServerValidateEventArgs args)
- {
- if (CreateMacroCheckBox.Checked)
- {
+ BasePage.Current.ClientTools
+ .ChangeContentFrameUrl(returnUrl)
+ .ChildNodeCreated()
+ .CloseModalWindow();
+ }
+ }
+
+ protected void MacroExistsValidator_OnServerValidate(object source, ServerValidateEventArgs args)
+ {
+ if (CreateMacroCheckBox.Checked)
+ {
//TODO: Shouldn't this use our string functions to create the alias ?
- var fileName = FileName.Text + ".cshtml";
- var name = fileName
- .Substring(0, (fileName.LastIndexOf('.') + 1)).Trim('.')
- .SplitPascalCasing().ToFirstUpperInvariant();
+ var fileName = FileName.Text;
+
+ var name = fileName.Contains(".")
+ ? fileName.Substring(0, (fileName.LastIndexOf('.') + 1)).Trim('.')
+ : fileName;
+
+ name = name.SplitPascalCasing().ToFirstUpperInvariant();
var macro = ApplicationContext.Current.Services.MacroService.GetByAlias(name);
if (macro != null)
{
args.IsValid = false;
- }
- }
- }
- }
+ }
+ }
+ }
+ }
}
\ No newline at end of file
diff --git a/src/Umbraco.Web/Umbraco.Web.csproj b/src/Umbraco.Web/Umbraco.Web.csproj
index 39ca165358..3a8a7c3c38 100644
--- a/src/Umbraco.Web/Umbraco.Web.csproj
+++ b/src/Umbraco.Web/Umbraco.Web.csproj
@@ -488,6 +488,7 @@
ASPXCodeBehind
+
ASPXCodeBehind
diff --git a/src/Umbraco.Web/WebServices/SaveFileController.cs b/src/Umbraco.Web/WebServices/SaveFileController.cs
index 7b90da05c1..591b89e1d4 100644
--- a/src/Umbraco.Web/WebServices/SaveFileController.cs
+++ b/src/Umbraco.Web/WebServices/SaveFileController.cs
@@ -2,8 +2,11 @@
using System.Linq;
using System.Text;
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;
using umbraco;
@@ -16,91 +19,72 @@ using Template = umbraco.cms.businesslogic.template.Template;
namespace Umbraco.Web.WebServices
{
///
- /// A REST controller used to save files such as templates, partial views, macro files, etc...
- ///
- ///
- /// This isn't fully implemented yet but we should migrate all of the logic in the umbraco.presentation.webservices.codeEditorSave
- /// over to this controller.
- ///
- public class SaveFileController : UmbracoAuthorizedController
- {
+ /// A REST controller used to save files such as templates, partial views, macro files, etc...
+ ///
+ ///
+ /// This isn't fully implemented yet but we should migrate all of the logic in the umbraco.presentation.webservices.codeEditorSave
+ /// over to this controller.
+ ///
+ public class SaveFileController : UmbracoAuthorizedController
+ {
- ///
- /// Saves a partial view for a partial view macr
- ///
- ///
- ///
- ///
- ///
- [HttpPost]
- public JsonResult SavePartialView(string filename, string oldName, string contents)
- {
- var folderPath = SystemDirectories.MvcViews.EnsureEndsWith('/');// +"/Partials/";
+ ///
+ /// Saves a partial view for a partial view macro
+ ///
+ ///
+ ///
+ ///
+ ///
+ [HttpPost]
+ public JsonResult SavePartialView(string filename, string oldName, string contents)
+ {
+ var folderPath = SystemDirectories.MvcViews.EnsureEndsWith('/');// +"/Partials/";
+ var savePath = filename.StartsWith("~/") ? IOHelper.MapPath(filename) : IOHelper.MapPath(folderPath + filename);
- // 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 partialView = new PartialView(savePath)
+ {
+ BasePath = folderPath,
+ OldFileName = oldName,
+ FileName = filename,
+ Content = contents,
+ };
- 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);
+ var fileService = (FileService)ApplicationContext.Current.Services.FileService;
+ var attempt = fileService.SavePartialView(partialView);
- //Directory check.. only allow files in script dir and below to be edited
- if (!savePath.StartsWith(IOHelper.MapPath(folderPath)))
- {
- 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));
- }
+ 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
+ attempt.Exception);
+ }
- //deletes the old file
- if (savePath != saveOldPath)
- {
- if (System.IO.File.Exists(saveOldPath))
- System.IO.File.Delete(saveOldPath);
- }
+ return Success(ui.Text("speechBubbles", "partialViewSavedText"), ui.Text("speechBubbles", "partialViewSavedHeader"));
+ }
- //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);
-
- return Success(ui.Text("speechBubbles", "partialViewSavedText"), ui.Text("speechBubbles", "partialViewSavedHeader"));
- }
-
- ///
- /// Saves a template
- ///
- ///
- ///
- ///
- ///
- ///
- ///
- [HttpPost]
- public JsonResult SaveTemplate(string templateName, string templateAlias, string templateContents, int templateId, int masterTemplateId)
- {
- Template t;
- bool pathChanged = false;
- try
- {
- t = new Template(templateId)
- {
- Text = templateName,
- Alias = templateAlias,
- Design = templateContents
- };
+ ///
+ /// Saves a template
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ [HttpPost]
+ public JsonResult SaveTemplate(string templateName, string templateAlias, string templateContents, int templateId, int masterTemplateId)
+ {
+ Template t;
+ bool pathChanged = false;
+ try
+ {
+ t = new Template(templateId)
+ {
+ Text = templateName,
+ Alias = templateAlias,
+ Design = templateContents
+ };
//check if the master page has changed
if (t.MasterTemplate != masterTemplateId)
@@ -108,16 +92,16 @@ namespace Umbraco.Web.WebServices
pathChanged = true;
t.MasterTemplate = masterTemplateId;
}
- }
- catch (ArgumentException ex)
- {
- //the template does not exist
- return Failed("Template does not exist", ui.Text("speechBubbles", "templateErrorHeader"), ex);
- }
+ }
+ catch (ArgumentException ex)
+ {
+ //the template does not exist
+ return Failed("Template does not exist", ui.Text("speechBubbles", "templateErrorHeader"), ex);
+ }
- try
- {
- t.Save();
+ try
+ {
+ t.Save();
//ensure the correct path is synced as the parent might have been changed
// http://issues.umbraco.org/issue/U4-2300
@@ -128,14 +112,14 @@ namespace Umbraco.Web.WebServices
}
var syncPath = "-1,init," + t.Path.Replace("-1,", "");
- return Success(ui.Text("speechBubbles", "templateSavedText"), ui.Text("speechBubbles", "templateSavedHeader"),
- new {path = syncPath});
- }
- catch (Exception ex)
- {
- return Failed(ui.Text("speechBubbles", "templateErrorText"), ui.Text("speechBubbles", "templateErrorHeader"), ex);
- }
- }
+ return Success(ui.Text("speechBubbles", "templateSavedText"), ui.Text("speechBubbles", "templateSavedHeader"),
+ new { path = syncPath });
+ }
+ catch (Exception ex)
+ {
+ return Failed(ui.Text("speechBubbles", "templateErrorText"), ui.Text("speechBubbles", "templateErrorHeader"), ex);
+ }
+ }
///
/// Returns a successful message
@@ -151,27 +135,26 @@ namespace Umbraco.Web.WebServices
d["message"] = message;
d["header"] = header;
- return Json(d);
- }
+ return Json(d);
+ }
- ///
- /// Returns a failed message
- ///
- /// The message to display in the speach bubble
- /// The header to display in the speach bubble
- /// The exception if there was one
- ///
- private JsonResult Failed(string message, string header, Exception exception = null)
- {
- if (exception != null)
- LogHelper.Error("An error occurred saving a file. " + message, exception);
- return Json(new
- {
- success = false,
- header = header,
- message = message + (exception == null ? "" : (exception.Message + ". Check log for details."))
- });
- }
-
- }
+ ///
+ /// Returns a failed message
+ ///
+ /// The message to display in the speach bubble
+ /// The header to display in the speach bubble
+ /// The exception if there was one
+ ///
+ private JsonResult Failed(string message, string header, Exception exception = null)
+ {
+ if (exception != null)
+ LogHelper.Error("An error occurred saving a file. " + message, exception);
+ return Json(new
+ {
+ success = false,
+ header = header,
+ message = message + (exception == null ? "" : (exception.Message + ". Check log for details."))
+ });
+ }
+ }
}
diff --git a/src/Umbraco.Web/umbraco.presentation/umbraco/create/PartialViewMacrosTasks.cs b/src/Umbraco.Web/umbraco.presentation/umbraco/create/PartialViewMacrosTasks.cs
index 7bde1e2b9a..36aee27fcc 100644
--- a/src/Umbraco.Web/umbraco.presentation/umbraco/create/PartialViewMacrosTasks.cs
+++ b/src/Umbraco.Web/umbraco.presentation/umbraco/create/PartialViewMacrosTasks.cs
@@ -1,14 +1,4 @@
-using System;
-using System.IO;
-using System.Text.RegularExpressions;
-using System.Web;
-using Umbraco.Core.CodeAnnotations;
-using Umbraco.Core.IO;
-using Umbraco.Core.Logging;
-using Umbraco.Web.Mvc;
-using Umbraco.Web.UI;
-using umbraco.BasePages;
-using Umbraco.Core;
+using Umbraco.Core.CodeAnnotations;
using umbraco.BusinessLogic;
namespace umbraco
@@ -17,100 +7,21 @@ namespace umbraco
/// The UI 'tasks' for the create dialog and delete processes
///
[UmbracoWillObsolete("http://issues.umbraco.org/issue/U4-1373", "This will one day be removed when we overhaul the create process")]
- public class PartialViewMacroTasks : LegacyDialogTask
+ public class PartialViewMacroTasks : PartialViewTasksBase
{
- private const string CodeHeader = "@inherits Umbraco.Web.Macros.PartialViewMacroPage";
- private string _returnUrl = "";
- private readonly Regex _headerMatch = new Regex("^@inherits\\s+?.*$", RegexOptions.Multiline | RegexOptions.Compiled);
-
-
- protected virtual string EditViewFile
+ protected override string CodeHeader
{
- get { return "Settings/Views/EditView.aspx"; }
+ get { return "@inherits Umbraco.Web.Macros.PartialViewMacroPage"; }
}
- protected string BasePath
- {
- get { return SystemDirectories.MvcViews + "/" + ParentFolderName.EnsureEndsWith('/'); }
- }
-
- protected virtual string ParentFolderName
+ protected override string ParentFolderName
{
get { return "MacroPartials"; }
}
-
- public override bool PerformSave()
- {
- var pipesIndex = Alias.IndexOf("|||", System.StringComparison.Ordinal);
- var template = Alias.Substring(0, pipesIndex).Trim();
- var fileName = Alias.Substring(pipesIndex + 3, Alias.Length - pipesIndex - 3) + ".cshtml";
-
- var fullFilePath = IOHelper.MapPath(BasePath + fileName);
-
- //return the link to edit the file if it already exists
- if (File.Exists(fullFilePath))
- {
- _returnUrl = string.Format(EditViewFile + "?file={0}", HttpUtility.UrlEncode(ParentFolderName.EnsureEndsWith('/') + fileName));
- return true;
- }
-
- //create the file
- using (var sw = File.CreateText(fullFilePath))
- {
- using (var templateFile = File.OpenText(IOHelper.MapPath(SystemDirectories.Umbraco + "/PartialViewMacros/Templates/" + template)))
- {
- var templateContent = templateFile.ReadToEnd().Trim();
-
- //strip the @inherits if it's there
- templateContent = _headerMatch.Replace(templateContent, string.Empty);
-
- sw.Write(
- "{0}{1}{2}",
- CodeHeader,
- Environment.NewLine,
- templateContent);
- }
- }
-
- // Create macro?
- if (ParentID == 1)
- {
- //TODO: Shouldn't this use our string functions to create the alias ?
- var name = fileName
- .Substring(0, (fileName.LastIndexOf('.') + 1)).Trim('.')
- .SplitPascalCasing().ToFirstUpperInvariant();
- var m = cms.businesslogic.macro.Macro.MakeNew(name);
- m.ScriptingFile = BasePath + fileName;
- m.Save();
- }
-
- _returnUrl = string.Format(EditViewFile + "?treeType={0}&file={1}", "partialViewMacros", HttpUtility.UrlEncode(ParentFolderName.EnsureEndsWith('/') + fileName));
- return true;
- }
-
- public override string ReturnUrl
- {
- get { return _returnUrl; }
- }
-
+
public override string AssignedApp
{
get { return DefaultApps.developer.ToString(); }
}
-
- public override bool PerformDelete()
- {
- var path = IOHelper.MapPath(BasePath + Alias.TrimStart('/'));
-
- if (File.Exists(path))
- File.Delete(path);
- else if (Directory.Exists(path))
- Directory.Delete(path, true);
-
- LogHelper.Info(string.Format("{0} Deleted by user {1}", Alias, User.Id));
-
- return true;
- }
-
}
}
\ No newline at end of file
diff --git a/src/Umbraco.Web/umbraco.presentation/umbraco/create/PartialViewTasks.cs b/src/Umbraco.Web/umbraco.presentation/umbraco/create/PartialViewTasks.cs
index 5a51055e96..4fda55c201 100644
--- a/src/Umbraco.Web/umbraco.presentation/umbraco/create/PartialViewTasks.cs
+++ b/src/Umbraco.Web/umbraco.presentation/umbraco/create/PartialViewTasks.cs
@@ -1,155 +1,27 @@
-using System;
-using System.IO;
-using System.Text.RegularExpressions;
-using System.Web;
-using Umbraco.Core.CodeAnnotations;
-using Umbraco.Core.IO;
-using Umbraco.Core.Logging;
-using Umbraco.Web.Mvc;
-using Umbraco.Web.UI;
-using umbraco.BasePages;
-using Umbraco.Core;
+using Umbraco.Core.CodeAnnotations;
using umbraco.BusinessLogic;
namespace umbraco
{
- ///
- /// The UI 'tasks' for the create dialog and delete processes
- ///
- [UmbracoWillObsolete("http://issues.umbraco.org/issue/U4-1373", "This will one day be removed when we overhaul the create process")]
- public class PartialViewTasks : LegacyDialogTask
+ ///
+ /// The UI 'tasks' for the create dialog and delete processes
+ ///
+ [UmbracoWillObsolete("http://issues.umbraco.org/issue/U4-1373", "This will one day be removed when we overhaul the create process")]
+ public class PartialViewTasks : PartialViewTasksBase
{
- private const string CodeHeader = "@inherits Umbraco.Web.Mvc.UmbracoTemplatePage";
-
- private readonly Regex _headerMatch = new Regex("^@inherits\\s+?.*$", RegexOptions.Multiline | RegexOptions.Compiled);
-
-
- protected virtual string EditViewFile
+ protected override string CodeHeader
{
- get { return "Settings/Views/EditView.aspx"; }
+ get { return "@inherits Umbraco.Web.Mvc.UmbracoTemplatePage"; }
}
- protected string BasePath
- {
- get { return SystemDirectories.MvcViews + "/" + ParentFolderName.EnsureEndsWith('/'); }
- }
-
- protected virtual string ParentFolderName
+ protected override string ParentFolderName
{
get { return "Partials"; }
}
-
- public override bool PerformSave()
- {
- var pipesIndex = Alias.IndexOf("|||", System.StringComparison.Ordinal);
- var template = Alias.Substring(0, pipesIndex).Trim();
- var fileName = Alias.Substring(pipesIndex + 3, Alias.Length - pipesIndex - 3);
- if (!fileName.ToLowerInvariant().EndsWith(".cshtml"))
- {
- fileName += ".cshtml";
- }
-
- var fullFilePath = IOHelper.MapPath(BasePath + fileName);
-
- //return the link to edit the file if it already exists
- if (File.Exists(fullFilePath))
- {
- _returnUrl = string.Format(EditViewFile + "?file={0}", HttpUtility.UrlEncode(ParentFolderName.EnsureEndsWith('/') + fileName));
- return true;
- }
-
- //create the file
- using (var sw = File.CreateText(fullFilePath))
- {
- var templatePathAttempt = TryGetTemplatePath(template);
- if (templatePathAttempt.Success == false)
- {
- throw new InvalidOperationException("Could not load template with name " + template);
- }
-
- using (var templateFile = File.OpenText(templatePathAttempt.Result))
- {
- var templateContent = templateFile.ReadToEnd().Trim();
-
- //strip the @inherits if it's there
- templateContent = _headerMatch.Replace(templateContent, string.Empty);
-
- sw.Write(
- "{0}{1}{2}",
- CodeHeader,
- Environment.NewLine,
- templateContent);
- }
- }
-
- // Create macro?
- if (ParentID == 1)
- {
- var name = fileName
- .Substring(0, (fileName.LastIndexOf('.') + 1)).Trim('.')
- .SplitPascalCasing().ToFirstUpperInvariant();
- var m = cms.businesslogic.macro.Macro.MakeNew(name);
- m.ScriptingFile = BasePath + fileName;
- m.Save();
- }
-
- _returnUrl = string.Format(EditViewFile + "?file={0}", HttpUtility.UrlEncode(ParentFolderName.EnsureEndsWith('/') + fileName));
- return true;
- }
-
- protected virtual void WriteTemplateHeader(StreamWriter sw)
+
+ public override string AssignedApp
{
- //write out the template header
- sw.Write("@inherits ");
- sw.Write(typeof(UmbracoTemplatePage).FullName.TrimEnd("`1"));
- }
-
- public override bool PerformDelete()
- {
- var path = IOHelper.MapPath(BasePath + Alias.TrimStart('/'));
-
- if (File.Exists(path))
- File.Delete(path);
- else if (Directory.Exists(path))
- Directory.Delete(path, true);
-
- LogHelper.Info(string.Format("{0} Deleted by user {1}", Alias, UmbracoEnsuredPage.CurrentUser.Id));
-
- return true;
- }
-
-
- private string _returnUrl = "";
- public override string ReturnUrl
- {
- get { return _returnUrl; }
- }
-
- public override string AssignedApp
- {
get { return DefaultApps.settings.ToString(); }
- }
-
-
- ///
- /// Looks first in the Partial View template folder and then in the macro partials template folder if not found
- ///
- ///
- ///
- private Attempt TryGetTemplatePath(string fileName)
- {
- var templatePath = IOHelper.MapPath(SystemDirectories.Umbraco + "/PartialViews/Templates/" + fileName);
-
- if (File.Exists(templatePath))
- {
- return Attempt.Succeed(templatePath);
- }
-
- templatePath = IOHelper.MapPath(SystemDirectories.Umbraco + "/PartialViewMacros/Templates/" + fileName);
-
- return File.Exists(templatePath)
- ? Attempt.Succeed(templatePath)
- : Attempt.Fail();
}
}
}
diff --git a/src/Umbraco.Web/umbraco.presentation/umbraco/create/PartialViewTasksBase.cs b/src/Umbraco.Web/umbraco.presentation/umbraco/create/PartialViewTasksBase.cs
new file mode 100644
index 0000000000..313cbc3efd
--- /dev/null
+++ b/src/Umbraco.Web/umbraco.presentation/umbraco/create/PartialViewTasksBase.cs
@@ -0,0 +1,87 @@
+using System;
+using Umbraco.Core.CodeAnnotations;
+using Umbraco.Core.IO;
+using Umbraco.Core.Models;
+using Umbraco.Core.Services;
+using Umbraco.Web.UI;
+using umbraco.BasePages;
+using Umbraco.Core;
+
+namespace umbraco
+{
+ ///
+ /// The base UI 'tasks' for the create dialog and delete processes
+ ///
+ [UmbracoWillObsolete("http://issues.umbraco.org/issue/U4-1373", "This will one day be removed when we overhaul the create process")]
+ public abstract class PartialViewTasksBase : LegacyDialogTask
+ {
+ private string _returnUrl = string.Empty;
+ public override string ReturnUrl
+ {
+ get { return _returnUrl; }
+ }
+
+ protected abstract string CodeHeader { get; }
+
+ protected abstract string ParentFolderName { get; }
+
+ public override string AssignedApp
+ {
+ get { return string.Empty; }
+ }
+
+ protected virtual string EditViewFile
+ {
+ get { return "Settings/Views/EditView.aspx"; }
+ }
+
+ protected string BasePath
+ {
+ get { return SystemDirectories.MvcViews + "/" + ParentFolderName.EnsureEndsWith('/'); }
+ }
+
+ public override bool PerformSave()
+ {
+ var pipesIndex = Alias.IndexOf("|||", StringComparison.Ordinal);
+ var snippetName = Alias.Substring(0, pipesIndex).Trim();
+ var fileName = Alias.Substring(pipesIndex + 3, Alias.Length - pipesIndex - 3);
+ if (fileName.ToLowerInvariant().EndsWith(".cshtml") == false)
+ {
+ fileName += ".cshtml";
+ }
+
+ var partialViewsFileSystem = new PhysicalFileSystem(BasePath);
+ var fullFilePath = partialViewsFileSystem.GetFullPath(fileName);
+
+ var model = new PartialView(fullFilePath)
+ {
+ FileName = fileName,
+ SnippetName = snippetName,
+ CreateMacro = ParentID == 1,
+ CodeHeader = CodeHeader,
+ ParentFolderName = ParentFolderName,
+ EditViewFile = EditViewFile,
+ BasePath = BasePath
+ };
+
+ var fileService = (FileService)ApplicationContext.Current.Services.FileService;
+ var attempt = fileService.CreatePartialView(model);
+
+ _returnUrl = attempt.Result.ReturnUrl;
+
+ return attempt.Success;
+ }
+
+ public override bool PerformDelete()
+ {
+ var partialViewsFileSystem = new PhysicalFileSystem(BasePath);
+ var path = Alias.TrimStart('/');
+ var fullFilePath = partialViewsFileSystem.GetFullPath(path);
+
+ var model = new PartialView(fullFilePath) { BasePath = BasePath, FileName = path };
+
+ var fileService = (FileService)ApplicationContext.Current.Services.FileService;
+ return fileService.DeletePartialView(model, UmbracoEnsuredPage.CurrentUser.Id);
+ }
+ }
+}