Merge pull request #449 from nul800sebastiaan/uaas-events
Adding events for use by Courier/UaaS
This commit is contained in:
74
src/Umbraco.Core/Models/PartialView.cs
Normal file
74
src/Umbraco.Core/Models/PartialView.cs
Normal file
@@ -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
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents a Partial View file
|
||||
/// </summary>
|
||||
[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;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Boolean indicating whether the file could be validated
|
||||
/// </summary>
|
||||
/// <returns>True if file is valid, otherwise false</returns>
|
||||
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<string> { "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<string> 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<string>.Succeed(snippetPath)
|
||||
: Attempt<string>.Fail();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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<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))
|
||||
return Attempt<PartialView>.Succeed(partialView);
|
||||
|
||||
if (CreatingPartialView.IsRaisedEventCancelled(new NewEventArgs<PartialView>(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<FileService>(failureMessage);
|
||||
|
||||
return Attempt<PartialView>.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>(partialView, false, partialView.Alias, -1), this);
|
||||
|
||||
return Attempt<PartialView>.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>(partialView), this))
|
||||
{
|
||||
LogHelper.Info<FileService>(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<FileService>(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<FileService>(string.Format("Partial View directory {0} deleted by user {1}", partialViewsFileSystem.GetFullPath(partialView.FileName), userId));
|
||||
}
|
||||
|
||||
DeletedPartialView.RaiseEvent(new DeleteEventArgs<PartialView>(partialView, false), this);
|
||||
|
||||
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
|
||||
@@ -425,6 +565,37 @@ 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>
|
||||
internal static event TypedEventHandler<IFileService, NewEventArgs<PartialView>> CreatingPartialView;
|
||||
|
||||
/// <summary>
|
||||
/// Occurs after Create
|
||||
/// </summary>
|
||||
internal static event TypedEventHandler<IFileService, NewEventArgs<PartialView>> CreatedPartialView;
|
||||
|
||||
/// <summary>
|
||||
/// Occurs before Delete
|
||||
/// </summary>
|
||||
internal static event TypedEventHandler<IFileService, DeleteEventArgs<PartialView>> DeletingPartialView;
|
||||
|
||||
/// <summary>
|
||||
/// Occurs after Delete
|
||||
/// </summary>
|
||||
internal static event TypedEventHandler<IFileService, DeleteEventArgs<PartialView>> DeletedPartialView;
|
||||
|
||||
#endregion
|
||||
|
||||
}
|
||||
}
|
||||
@@ -144,7 +144,7 @@ namespace Umbraco.Core.Services
|
||||
_dataTypeService = new Lazy<IDataTypeService>(() => new DataTypeService(provider, repositoryFactory.Value));
|
||||
|
||||
if (_fileService == null)
|
||||
_fileService = new Lazy<IFileService>(() => new FileService(fileProvider, provider, repositoryFactory.Value));
|
||||
_fileService = new Lazy<IFileService>(() => new FileService(fileProvider, provider, repositoryFactory.Value, _macroService.Value));
|
||||
|
||||
if (_localizationService == null)
|
||||
_localizationService = new Lazy<ILocalizationService>(() => new LocalizationService(provider, repositoryFactory.Value));
|
||||
|
||||
@@ -364,6 +364,7 @@
|
||||
<Compile Include="Models\PublishedContent\IPublishedContentModelFactory.cs" />
|
||||
<Compile Include="Models\PublishedContent\PublishedContentModel.cs" />
|
||||
<Compile Include="Models\PublishedContent\PublishedContentModelFactoryResolver.cs" />
|
||||
<Compile Include="Models\PartialView.cs" />
|
||||
<Compile Include="Models\TagCacheStorageType.cs" />
|
||||
<Compile Include="Models\TaggableObjectTypes.cs" />
|
||||
<Compile Include="Models\TaggedEntity.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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -488,6 +488,7 @@
|
||||
<Compile Include="umbraco.presentation\umbraco\create\DLRScripting.ascx.cs">
|
||||
<SubType>ASPXCodeBehind</SubType>
|
||||
</Compile>
|
||||
<Compile Include="umbraco.presentation\umbraco\create\PartialViewTasksBase.cs" />
|
||||
<Compile Include="umbraco.presentation\umbraco\create\xslt.ascx.cs">
|
||||
<SubType>ASPXCodeBehind</SubType>
|
||||
</Compile>
|
||||
|
||||
@@ -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
|
||||
{
|
||||
/// <summary>
|
||||
/// A REST controller used to save files such as templates, partial views, macro files, etc...
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This isn't fully implemented yet but we should migrate all of the logic in the umbraco.presentation.webservices.codeEditorSave
|
||||
/// over to this controller.
|
||||
/// </remarks>
|
||||
public class SaveFileController : UmbracoAuthorizedController
|
||||
{
|
||||
/// A REST controller used to save files such as templates, partial views, macro files, etc...
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This isn't fully implemented yet but we should migrate all of the logic in the umbraco.presentation.webservices.codeEditorSave
|
||||
/// over to this controller.
|
||||
/// </remarks>
|
||||
public class SaveFileController : UmbracoAuthorizedController
|
||||
{
|
||||
|
||||
/// <summary>
|
||||
/// Saves a partial view for a partial view macr
|
||||
/// </summary>
|
||||
/// <param name="filename"></param>
|
||||
/// <param name="oldName"></param>
|
||||
/// <param name="contents"></param>
|
||||
/// <returns></returns>
|
||||
[HttpPost]
|
||||
public JsonResult SavePartialView(string filename, string oldName, string contents)
|
||||
{
|
||||
var folderPath = SystemDirectories.MvcViews.EnsureEndsWith('/');// +"/Partials/";
|
||||
/// <summary>
|
||||
/// Saves a partial view for a partial view macro
|
||||
/// </summary>
|
||||
/// <param name="filename"></param>
|
||||
/// <param name="oldName"></param>
|
||||
/// <param name="contents"></param>
|
||||
/// <returns></returns>
|
||||
[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"));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Saves a template
|
||||
/// </summary>
|
||||
/// <param name="templateName"></param>
|
||||
/// <param name="templateAlias"></param>
|
||||
/// <param name="templateContents"></param>
|
||||
/// <param name="templateId"></param>
|
||||
/// <param name="masterTemplateId"></param>
|
||||
/// <returns></returns>
|
||||
[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
|
||||
};
|
||||
/// <summary>
|
||||
/// Saves a template
|
||||
/// </summary>
|
||||
/// <param name="templateName"></param>
|
||||
/// <param name="templateAlias"></param>
|
||||
/// <param name="templateContents"></param>
|
||||
/// <param name="templateId"></param>
|
||||
/// <param name="masterTemplateId"></param>
|
||||
/// <returns></returns>
|
||||
[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);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns a successful message
|
||||
@@ -151,27 +135,26 @@ namespace Umbraco.Web.WebServices
|
||||
d["message"] = message;
|
||||
d["header"] = header;
|
||||
|
||||
return Json(d);
|
||||
}
|
||||
return Json(d);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns a failed message
|
||||
/// </summary>
|
||||
/// <param name="message">The message to display in the speach bubble</param>
|
||||
/// <param name="header">The header to display in the speach bubble</param>
|
||||
/// <param name="exception">The exception if there was one</param>
|
||||
/// <returns></returns>
|
||||
private JsonResult Failed(string message, string header, Exception exception = null)
|
||||
{
|
||||
if (exception != null)
|
||||
LogHelper.Error<SaveFileController>("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."))
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
/// <summary>
|
||||
/// Returns a failed message
|
||||
/// </summary>
|
||||
/// <param name="message">The message to display in the speach bubble</param>
|
||||
/// <param name="header">The header to display in the speach bubble</param>
|
||||
/// <param name="exception">The exception if there was one</param>
|
||||
/// <returns></returns>
|
||||
private JsonResult Failed(string message, string header, Exception exception = null)
|
||||
{
|
||||
if (exception != null)
|
||||
LogHelper.Error<SaveFileController>("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."))
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
/// </summary>
|
||||
[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<PartialViewTasks>(string.Format("{0} Deleted by user {1}", Alias, User.Id));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
{
|
||||
/// <summary>
|
||||
/// The UI 'tasks' for the create dialog and delete processes
|
||||
/// </summary>
|
||||
[UmbracoWillObsolete("http://issues.umbraco.org/issue/U4-1373", "This will one day be removed when we overhaul the create process")]
|
||||
public class PartialViewTasks : LegacyDialogTask
|
||||
/// <summary>
|
||||
/// The UI 'tasks' for the create dialog and delete processes
|
||||
/// </summary>
|
||||
[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<PartialViewTasks>(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(); }
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Looks first in the Partial View template folder and then in the macro partials template folder if not found
|
||||
/// </summary>
|
||||
/// <param name="fileName"></param>
|
||||
/// <returns></returns>
|
||||
private Attempt<string> TryGetTemplatePath(string fileName)
|
||||
{
|
||||
var templatePath = IOHelper.MapPath(SystemDirectories.Umbraco + "/PartialViews/Templates/" + fileName);
|
||||
|
||||
if (File.Exists(templatePath))
|
||||
{
|
||||
return Attempt<string>.Succeed(templatePath);
|
||||
}
|
||||
|
||||
templatePath = IOHelper.MapPath(SystemDirectories.Umbraco + "/PartialViewMacros/Templates/" + fileName);
|
||||
|
||||
return File.Exists(templatePath)
|
||||
? Attempt<string>.Succeed(templatePath)
|
||||
: Attempt<string>.Fail();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
{
|
||||
/// <summary>
|
||||
/// The base UI 'tasks' for the create dialog and delete processes
|
||||
/// </summary>
|
||||
[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);
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user