2021-02-12 17:23:14 +11:00
|
|
|
using System;
|
2017-12-28 09:18:09 +01:00
|
|
|
using System.Collections.Generic;
|
|
|
|
|
using System.IO;
|
|
|
|
|
using System.Linq;
|
|
|
|
|
using System.Text.RegularExpressions;
|
2020-09-18 15:27:38 +02:00
|
|
|
using Microsoft.Extensions.Logging;
|
2021-02-09 11:26:22 +01:00
|
|
|
using Microsoft.Extensions.Options;
|
2021-02-09 10:22:42 +01:00
|
|
|
using Umbraco.Cms.Core.Configuration.Models;
|
|
|
|
|
using Umbraco.Cms.Core.Events;
|
|
|
|
|
using Umbraco.Cms.Core.Hosting;
|
|
|
|
|
using Umbraco.Cms.Core.Models;
|
|
|
|
|
using Umbraco.Cms.Core.Persistence.Repositories;
|
2021-02-15 11:41:12 +01:00
|
|
|
using Umbraco.Cms.Core.Scoping;
|
2021-04-09 13:43:39 +02:00
|
|
|
using Umbraco.Cms.Core.Services.Notifications;
|
2021-02-09 10:22:42 +01:00
|
|
|
using Umbraco.Cms.Core.Strings;
|
2021-02-09 11:26:22 +01:00
|
|
|
using Umbraco.Extensions;
|
2017-12-28 09:18:09 +01:00
|
|
|
|
2021-02-23 12:24:51 +01:00
|
|
|
namespace Umbraco.Cms.Core.Services.Implement
|
2017-12-28 09:18:09 +01:00
|
|
|
{
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// Represents the File Service, which is an easy access to operations involving <see cref="IFile"/> objects like Scripts, Stylesheets and Templates
|
|
|
|
|
/// </summary>
|
2021-03-07 09:53:25 +01:00
|
|
|
public class FileService : RepositoryService, IFileService
|
2017-12-28 09:18:09 +01:00
|
|
|
{
|
|
|
|
|
private readonly IStylesheetRepository _stylesheetRepository;
|
|
|
|
|
private readonly IScriptRepository _scriptRepository;
|
|
|
|
|
private readonly ITemplateRepository _templateRepository;
|
|
|
|
|
private readonly IPartialViewRepository _partialViewRepository;
|
|
|
|
|
private readonly IPartialViewMacroRepository _partialViewMacroRepository;
|
|
|
|
|
private readonly IAuditRepository _auditRepository;
|
2019-12-09 14:12:06 +01:00
|
|
|
private readonly IShortStringHelper _shortStringHelper;
|
2020-08-21 14:52:47 +01:00
|
|
|
private readonly GlobalSettings _globalSettings;
|
2020-06-22 10:08:08 +02:00
|
|
|
private readonly IHostingEnvironment _hostingEnvironment;
|
2017-12-28 09:18:09 +01:00
|
|
|
|
2021-02-22 10:09:20 +01:00
|
|
|
private const string PartialViewHeader = "@inherits Umbraco.Cms.Web.Common.Views.UmbracoViewPage";
|
2021-02-26 15:14:42 +11:00
|
|
|
private const string PartialViewMacroHeader = "@inherits Umbraco.Cms.Web.Common.Macros.PartialViewMacroPage";
|
2017-12-28 09:18:09 +01:00
|
|
|
|
2020-09-18 15:27:38 +02:00
|
|
|
public FileService(IScopeProvider uowProvider, ILoggerFactory loggerFactory, IEventMessagesFactory eventMessagesFactory,
|
2017-12-28 09:18:09 +01:00
|
|
|
IStylesheetRepository stylesheetRepository, IScriptRepository scriptRepository, ITemplateRepository templateRepository,
|
|
|
|
|
IPartialViewRepository partialViewRepository, IPartialViewMacroRepository partialViewMacroRepository,
|
2020-08-23 23:36:48 +02:00
|
|
|
IAuditRepository auditRepository, IShortStringHelper shortStringHelper, IOptions<GlobalSettings> globalSettings, IHostingEnvironment hostingEnvironment)
|
2020-09-18 15:27:38 +02:00
|
|
|
: base(uowProvider, loggerFactory, eventMessagesFactory)
|
2017-12-28 09:18:09 +01:00
|
|
|
{
|
|
|
|
|
_stylesheetRepository = stylesheetRepository;
|
|
|
|
|
_scriptRepository = scriptRepository;
|
|
|
|
|
_templateRepository = templateRepository;
|
|
|
|
|
_partialViewRepository = partialViewRepository;
|
|
|
|
|
_partialViewMacroRepository = partialViewMacroRepository;
|
|
|
|
|
_auditRepository = auditRepository;
|
2019-12-09 14:12:06 +01:00
|
|
|
_shortStringHelper = shortStringHelper;
|
2020-08-21 14:52:47 +01:00
|
|
|
_globalSettings = globalSettings.Value;
|
2020-06-22 10:08:08 +02:00
|
|
|
_hostingEnvironment = hostingEnvironment;
|
2017-12-28 09:18:09 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#region Stylesheets
|
|
|
|
|
|
2019-11-12 13:49:56 +11:00
|
|
|
/// <inheritdoc />
|
2019-11-12 13:33:02 +11:00
|
|
|
public IEnumerable<IStylesheet> GetStylesheets(params string[] names)
|
2017-12-28 09:18:09 +01:00
|
|
|
{
|
|
|
|
|
using (var scope = ScopeProvider.CreateScope(autoComplete: true))
|
|
|
|
|
{
|
|
|
|
|
return _stylesheetRepository.GetMany(names);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2019-11-12 13:49:56 +11:00
|
|
|
/// <inheritdoc />
|
2019-11-12 13:33:02 +11:00
|
|
|
public IStylesheet GetStylesheetByName(string name)
|
2017-12-28 09:18:09 +01:00
|
|
|
{
|
|
|
|
|
using (var scope = ScopeProvider.CreateScope(autoComplete: true))
|
|
|
|
|
{
|
|
|
|
|
return _stylesheetRepository.Get(name);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2019-11-12 13:49:56 +11:00
|
|
|
/// <inheritdoc />
|
2021-02-09 10:22:42 +01:00
|
|
|
public void SaveStylesheet(IStylesheet stylesheet, int userId = Cms.Core.Constants.Security.SuperUserId)
|
2017-12-28 09:18:09 +01:00
|
|
|
{
|
2021-03-30 14:05:09 +02:00
|
|
|
using (IScope scope = ScopeProvider.CreateScope())
|
2017-12-28 09:18:09 +01:00
|
|
|
{
|
2021-03-30 14:05:09 +02:00
|
|
|
EventMessages eventMessages = EventMessagesFactory.Get();
|
|
|
|
|
var savingNotification = new StylesheetSavingNotification(stylesheet, eventMessages);
|
|
|
|
|
if (scope.Notifications.PublishCancelable(savingNotification))
|
2017-12-28 09:18:09 +01:00
|
|
|
{
|
|
|
|
|
scope.Complete();
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
_stylesheetRepository.Save(stylesheet);
|
2021-03-30 14:05:09 +02:00
|
|
|
scope.Notifications.Publish(new StylesheetSavedNotification(stylesheet, eventMessages).WithStateFrom(savingNotification));
|
2020-02-05 01:52:10 -08:00
|
|
|
Audit(AuditType.Save, userId, -1, "Stylesheet");
|
2017-12-28 09:18:09 +01:00
|
|
|
|
|
|
|
|
scope.Complete();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2019-11-12 13:49:56 +11:00
|
|
|
/// <inheritdoc />
|
2021-02-09 10:22:42 +01:00
|
|
|
public void DeleteStylesheet(string path, int userId = Cms.Core.Constants.Security.SuperUserId)
|
2017-12-28 09:18:09 +01:00
|
|
|
{
|
2021-03-30 12:14:32 +02:00
|
|
|
using (IScope scope = ScopeProvider.CreateScope())
|
2017-12-28 09:18:09 +01:00
|
|
|
{
|
2021-03-30 12:14:32 +02:00
|
|
|
IStylesheet stylesheet = _stylesheetRepository.Get(path);
|
2017-12-28 09:18:09 +01:00
|
|
|
if (stylesheet == null)
|
|
|
|
|
{
|
|
|
|
|
scope.Complete();
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
2021-03-30 12:14:32 +02:00
|
|
|
EventMessages eventMessages = EventMessagesFactory.Get();
|
|
|
|
|
var deletingNotification = new StylesheetDeletingNotification(stylesheet, eventMessages);
|
|
|
|
|
if (scope.Notifications.PublishCancelable(deletingNotification))
|
2017-12-28 09:18:09 +01:00
|
|
|
{
|
|
|
|
|
scope.Complete();
|
2021-03-30 12:14:32 +02:00
|
|
|
return; // causes rollback
|
2017-12-28 09:18:09 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
_stylesheetRepository.Delete(stylesheet);
|
2021-03-30 12:14:32 +02:00
|
|
|
|
|
|
|
|
scope.Notifications.Publish(new StylesheetDeletedNotification(stylesheet, eventMessages).WithStateFrom(deletingNotification));
|
2020-02-05 01:52:10 -08:00
|
|
|
Audit(AuditType.Delete, userId, -1, "Stylesheet");
|
2017-12-28 09:18:09 +01:00
|
|
|
|
|
|
|
|
scope.Complete();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2019-01-21 19:02:52 +01:00
|
|
|
public void CreateStyleSheetFolder(string folderPath)
|
|
|
|
|
{
|
|
|
|
|
using (var scope = ScopeProvider.CreateScope())
|
|
|
|
|
{
|
2019-11-12 13:49:56 +11:00
|
|
|
_stylesheetRepository.AddFolder(folderPath);
|
2019-01-21 19:02:52 +01:00
|
|
|
scope.Complete();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public void DeleteStyleSheetFolder(string folderPath)
|
|
|
|
|
{
|
|
|
|
|
using (var scope = ScopeProvider.CreateScope())
|
|
|
|
|
{
|
2019-11-12 13:49:56 +11:00
|
|
|
_stylesheetRepository.DeleteFolder(folderPath);
|
2019-01-21 19:02:52 +01:00
|
|
|
scope.Complete();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2017-12-28 09:18:09 +01:00
|
|
|
#endregion
|
|
|
|
|
|
|
|
|
|
#region Scripts
|
|
|
|
|
|
2019-11-12 13:49:56 +11:00
|
|
|
/// <inheritdoc />
|
|
|
|
|
public IScript GetScriptByName(string name)
|
2017-12-28 09:18:09 +01:00
|
|
|
{
|
|
|
|
|
using (var scope = ScopeProvider.CreateScope(autoComplete: true))
|
|
|
|
|
{
|
|
|
|
|
return _scriptRepository.Get(name);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2019-11-12 13:49:56 +11:00
|
|
|
/// <inheritdoc />
|
2021-02-09 10:22:42 +01:00
|
|
|
public void SaveScript(IScript script, int userId = Cms.Core.Constants.Security.SuperUserId)
|
2017-12-28 09:18:09 +01:00
|
|
|
{
|
2021-03-30 14:05:09 +02:00
|
|
|
using (IScope scope = ScopeProvider.CreateScope())
|
2017-12-28 09:18:09 +01:00
|
|
|
{
|
2021-03-30 14:05:09 +02:00
|
|
|
EventMessages eventMessages = EventMessagesFactory.Get();
|
|
|
|
|
var savingNotification = new ScriptSavingNotification(script, eventMessages);
|
|
|
|
|
if (scope.Notifications.PublishCancelable(savingNotification))
|
2017-12-28 09:18:09 +01:00
|
|
|
{
|
|
|
|
|
scope.Complete();
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
_scriptRepository.Save(script);
|
2021-03-30 14:05:09 +02:00
|
|
|
scope.Notifications.Publish(new ScriptSavedNotification(script, eventMessages).WithStateFrom(savingNotification));
|
2017-12-28 09:18:09 +01:00
|
|
|
|
2018-10-18 22:47:12 +11:00
|
|
|
Audit(AuditType.Save, userId, -1, "Script");
|
2017-12-28 09:18:09 +01:00
|
|
|
scope.Complete();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2019-11-12 13:49:56 +11:00
|
|
|
/// <inheritdoc />
|
2021-02-09 10:22:42 +01:00
|
|
|
public void DeleteScript(string path, int userId = Cms.Core.Constants.Security.SuperUserId)
|
2017-12-28 09:18:09 +01:00
|
|
|
{
|
2021-03-30 12:14:32 +02:00
|
|
|
using (IScope scope = ScopeProvider.CreateScope())
|
2017-12-28 09:18:09 +01:00
|
|
|
{
|
2021-03-30 12:14:32 +02:00
|
|
|
IScript script = _scriptRepository.Get(path);
|
2017-12-28 09:18:09 +01:00
|
|
|
if (script == null)
|
|
|
|
|
{
|
|
|
|
|
scope.Complete();
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
2021-03-30 12:14:32 +02:00
|
|
|
EventMessages eventMessages = EventMessagesFactory.Get();
|
|
|
|
|
var deletingNotification = new ScriptDeletingNotification(script, eventMessages);
|
|
|
|
|
if (scope.Notifications.PublishCancelable(deletingNotification))
|
2017-12-28 09:18:09 +01:00
|
|
|
{
|
|
|
|
|
scope.Complete();
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
_scriptRepository.Delete(script);
|
2021-03-30 12:14:32 +02:00
|
|
|
scope.Notifications.Publish(new ScriptDeletedNotification(script, eventMessages).WithStateFrom(deletingNotification));
|
2017-12-28 09:18:09 +01:00
|
|
|
|
2018-10-18 22:47:12 +11:00
|
|
|
Audit(AuditType.Delete, userId, -1, "Script");
|
2017-12-28 09:18:09 +01:00
|
|
|
scope.Complete();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public void CreateScriptFolder(string folderPath)
|
|
|
|
|
{
|
|
|
|
|
using (var scope = ScopeProvider.CreateScope())
|
|
|
|
|
{
|
2019-11-12 13:49:56 +11:00
|
|
|
_scriptRepository.AddFolder(folderPath);
|
2017-12-28 09:18:09 +01:00
|
|
|
scope.Complete();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public void DeleteScriptFolder(string folderPath)
|
|
|
|
|
{
|
|
|
|
|
using (var scope = ScopeProvider.CreateScope())
|
|
|
|
|
{
|
2019-11-12 13:49:56 +11:00
|
|
|
_scriptRepository.DeleteFolder(folderPath);
|
2017-12-28 09:18:09 +01:00
|
|
|
scope.Complete();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#endregion
|
|
|
|
|
|
|
|
|
|
#region Templates
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// Creates a template for a content type
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <param name="contentTypeAlias"></param>
|
|
|
|
|
/// <param name="contentTypeName"></param>
|
|
|
|
|
/// <param name="userId"></param>
|
|
|
|
|
/// <returns>
|
|
|
|
|
/// The template created
|
|
|
|
|
/// </returns>
|
2021-02-09 10:22:42 +01:00
|
|
|
public Attempt<OperationResult<OperationResultType, ITemplate>> CreateTemplateForContentType(string contentTypeAlias, string contentTypeName, int userId = Cms.Core.Constants.Security.SuperUserId)
|
2017-12-28 09:18:09 +01:00
|
|
|
{
|
2019-12-09 14:12:06 +01:00
|
|
|
var template = new Template(_shortStringHelper, contentTypeName,
|
2017-12-28 09:18:09 +01:00
|
|
|
//NOTE: We are NOT passing in the content type alias here, we want to use it's name since we don't
|
|
|
|
|
// want to save template file names as camelCase, the Template ctor will clean the alias as
|
|
|
|
|
// `alias.ToCleanString(CleanStringType.UnderscoreAlias)` which has been the default.
|
|
|
|
|
// This fixes: http://issues.umbraco.org/issue/U4-7953
|
|
|
|
|
contentTypeName);
|
|
|
|
|
|
2021-03-30 14:01:37 +02:00
|
|
|
EventMessages eventMessages = EventMessagesFactory.Get();
|
2017-12-28 09:18:09 +01:00
|
|
|
|
2019-08-29 17:41:55 +01:00
|
|
|
if (contentTypeAlias != null && contentTypeAlias.Length > 255)
|
|
|
|
|
{
|
|
|
|
|
throw new InvalidOperationException("Name cannot be more than 255 characters in length.");
|
|
|
|
|
}
|
|
|
|
|
|
2018-07-18 13:19:48 +10:00
|
|
|
// check that the template hasn't been created on disk before creating the content type
|
|
|
|
|
// if it exists, set the new template content to the existing file content
|
|
|
|
|
string content = GetViewContent(contentTypeAlias);
|
2018-07-30 23:23:01 +10:00
|
|
|
if (content != null)
|
2018-07-18 13:19:48 +10:00
|
|
|
{
|
|
|
|
|
template.Content = content;
|
|
|
|
|
}
|
2019-08-29 17:41:55 +01:00
|
|
|
|
2021-03-30 14:01:37 +02:00
|
|
|
using (IScope scope = ScopeProvider.CreateScope())
|
2017-12-28 09:18:09 +01:00
|
|
|
{
|
2021-04-09 09:10:59 +02:00
|
|
|
var savingEvent = new TemplateSavingNotification(template, eventMessages, true, contentTypeAlias);
|
2021-03-30 14:01:37 +02:00
|
|
|
if (scope.Notifications.PublishCancelable(savingEvent))
|
2017-12-28 09:18:09 +01:00
|
|
|
{
|
|
|
|
|
scope.Complete();
|
2021-03-30 14:01:37 +02:00
|
|
|
return OperationResult.Attempt.Fail<OperationResultType, ITemplate>(OperationResultType.FailedCancelledByEvent, eventMessages, template);
|
2017-12-28 09:18:09 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
_templateRepository.Save(template);
|
2021-04-09 09:10:59 +02:00
|
|
|
scope.Notifications.Publish(new TemplateSavedNotification(template, eventMessages).WithStateFrom(savingEvent));
|
2017-12-28 09:18:09 +01:00
|
|
|
|
2018-10-18 22:47:12 +11:00
|
|
|
Audit(AuditType.Save, userId, template.Id, ObjectTypes.GetName(UmbracoObjectTypes.Template));
|
2017-12-28 09:18:09 +01:00
|
|
|
scope.Complete();
|
|
|
|
|
}
|
|
|
|
|
|
2021-03-30 14:01:37 +02:00
|
|
|
return OperationResult.Attempt.Succeed<OperationResultType, ITemplate>(OperationResultType.Success, eventMessages, template);
|
2017-12-28 09:18:09 +01:00
|
|
|
}
|
|
|
|
|
|
2018-07-30 23:23:01 +10:00
|
|
|
/// <summary>
|
|
|
|
|
/// Create a new template, setting the content if a view exists in the filesystem
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <param name="name"></param>
|
2019-01-29 12:25:23 +01:00
|
|
|
/// <param name="alias"></param>
|
2018-07-30 23:23:01 +10:00
|
|
|
/// <param name="content"></param>
|
|
|
|
|
/// <param name="masterTemplate"></param>
|
|
|
|
|
/// <param name="userId"></param>
|
|
|
|
|
/// <returns></returns>
|
2021-02-09 10:22:42 +01:00
|
|
|
public ITemplate CreateTemplateWithIdentity(string name, string alias, string content, ITemplate masterTemplate = null, int userId = Cms.Core.Constants.Security.SuperUserId)
|
2017-12-28 09:18:09 +01:00
|
|
|
{
|
2019-10-31 14:54:14 +00:00
|
|
|
if (name == null)
|
|
|
|
|
{
|
|
|
|
|
throw new ArgumentNullException(nameof(name));
|
|
|
|
|
}
|
|
|
|
|
|
2019-11-08 07:51:14 +01:00
|
|
|
if (string.IsNullOrWhiteSpace(name))
|
2019-10-31 14:54:14 +00:00
|
|
|
{
|
|
|
|
|
throw new ArgumentException("Name cannot be empty or contain only white-space characters", nameof(name));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (name.Length > 255)
|
|
|
|
|
{
|
|
|
|
|
throw new ArgumentOutOfRangeException(nameof(name), "Name cannot be more than 255 characters in length.");
|
|
|
|
|
}
|
|
|
|
|
|
2018-07-30 23:23:01 +10:00
|
|
|
// file might already be on disk, if so grab the content to avoid overwriting
|
2019-12-09 14:12:06 +01:00
|
|
|
var template = new Template(_shortStringHelper, name, alias)
|
2017-12-28 09:18:09 +01:00
|
|
|
{
|
2019-01-29 12:25:23 +01:00
|
|
|
Content = GetViewContent(alias) ?? content
|
2017-12-28 09:18:09 +01:00
|
|
|
};
|
2019-11-05 12:54:22 +01:00
|
|
|
|
2017-12-28 09:18:09 +01:00
|
|
|
if (masterTemplate != null)
|
|
|
|
|
{
|
|
|
|
|
template.SetMasterTemplate(masterTemplate);
|
|
|
|
|
}
|
2018-07-30 23:23:01 +10:00
|
|
|
|
2017-12-28 09:18:09 +01:00
|
|
|
SaveTemplate(template, userId);
|
2018-07-30 23:23:01 +10:00
|
|
|
|
2017-12-28 09:18:09 +01:00
|
|
|
return template;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// Gets a list of all <see cref="ITemplate"/> objects
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <returns>An enumerable list of <see cref="ITemplate"/> objects</returns>
|
|
|
|
|
public IEnumerable<ITemplate> GetTemplates(params string[] aliases)
|
|
|
|
|
{
|
|
|
|
|
using (var scope = ScopeProvider.CreateScope(autoComplete: true))
|
|
|
|
|
{
|
|
|
|
|
return _templateRepository.GetAll(aliases).OrderBy(x => x.Name);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// Gets a list of all <see cref="ITemplate"/> objects
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <returns>An enumerable list of <see cref="ITemplate"/> objects</returns>
|
|
|
|
|
public IEnumerable<ITemplate> GetTemplates(int masterTemplateId)
|
|
|
|
|
{
|
|
|
|
|
using (var scope = ScopeProvider.CreateScope(autoComplete: true))
|
|
|
|
|
{
|
|
|
|
|
return _templateRepository.GetChildren(masterTemplateId).OrderBy(x => x.Name);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// Gets a <see cref="ITemplate"/> object by its alias.
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <param name="alias">The alias of the template.</param>
|
|
|
|
|
/// <returns>The <see cref="ITemplate"/> object matching the alias, or null.</returns>
|
|
|
|
|
public ITemplate GetTemplate(string alias)
|
|
|
|
|
{
|
|
|
|
|
using (var scope = ScopeProvider.CreateScope(autoComplete: true))
|
|
|
|
|
{
|
|
|
|
|
return _templateRepository.Get(alias);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// Gets a <see cref="ITemplate"/> object by its identifier.
|
|
|
|
|
/// </summary>
|
2019-01-22 18:03:39 -05:00
|
|
|
/// <param name="id">The identifier of the template.</param>
|
2017-12-28 09:18:09 +01:00
|
|
|
/// <returns>The <see cref="ITemplate"/> object matching the identifier, or null.</returns>
|
|
|
|
|
public ITemplate GetTemplate(int id)
|
|
|
|
|
{
|
|
|
|
|
using (var scope = ScopeProvider.CreateScope(autoComplete: true))
|
|
|
|
|
{
|
|
|
|
|
return _templateRepository.Get(id);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// Gets a <see cref="ITemplate"/> object by its guid identifier.
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <param name="id">The guid identifier of the template.</param>
|
|
|
|
|
/// <returns>The <see cref="ITemplate"/> object matching the identifier, or null.</returns>
|
|
|
|
|
public ITemplate GetTemplate(Guid id)
|
|
|
|
|
{
|
|
|
|
|
using (var scope = ScopeProvider.CreateScope(autoComplete: true))
|
|
|
|
|
{
|
|
|
|
|
var query = Query<ITemplate>().Where(x => x.Key == id);
|
|
|
|
|
return _templateRepository.Get(query).SingleOrDefault();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// Gets the template descendants
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <param name="masterTemplateId"></param>
|
|
|
|
|
/// <returns></returns>
|
|
|
|
|
public IEnumerable<ITemplate> GetTemplateDescendants(int masterTemplateId)
|
|
|
|
|
{
|
|
|
|
|
using (var scope = ScopeProvider.CreateScope(autoComplete: true))
|
|
|
|
|
{
|
|
|
|
|
return _templateRepository.GetDescendants(masterTemplateId);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// Saves a <see cref="Template"/>
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <param name="template"><see cref="Template"/> to save</param>
|
|
|
|
|
/// <param name="userId"></param>
|
2021-02-09 10:22:42 +01:00
|
|
|
public void SaveTemplate(ITemplate template, int userId = Cms.Core.Constants.Security.SuperUserId)
|
2017-12-28 09:18:09 +01:00
|
|
|
{
|
2019-10-31 14:54:14 +00:00
|
|
|
if (template == null)
|
|
|
|
|
{
|
|
|
|
|
throw new ArgumentNullException(nameof(template));
|
|
|
|
|
}
|
2019-11-08 07:51:14 +01:00
|
|
|
|
2019-10-31 14:54:14 +00:00
|
|
|
if (string.IsNullOrWhiteSpace(template.Name) || template.Name.Length > 255)
|
|
|
|
|
{
|
|
|
|
|
throw new InvalidOperationException("Name cannot be null, empty, contain only white-space characters or be more than 255 characters in length.");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2021-03-30 14:01:37 +02:00
|
|
|
using (IScope scope = ScopeProvider.CreateScope())
|
2017-12-28 09:18:09 +01:00
|
|
|
{
|
2021-03-30 14:01:37 +02:00
|
|
|
EventMessages eventMessages = EventMessagesFactory.Get();
|
|
|
|
|
var savingNotification = new TemplateSavingNotification(template, eventMessages);
|
|
|
|
|
if (scope.Notifications.PublishCancelable(savingNotification))
|
2017-12-28 09:18:09 +01:00
|
|
|
{
|
|
|
|
|
scope.Complete();
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
_templateRepository.Save(template);
|
|
|
|
|
|
2021-03-30 14:01:37 +02:00
|
|
|
scope.Notifications.Publish(new TemplateSavedNotification(template, eventMessages).WithStateFrom(savingNotification));
|
2017-12-28 09:18:09 +01:00
|
|
|
|
2019-11-12 17:56:47 +11:00
|
|
|
Audit(AuditType.Save, userId, template.Id, UmbracoObjectTypes.Template.GetName());
|
2017-12-28 09:18:09 +01:00
|
|
|
scope.Complete();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// Saves a collection of <see cref="Template"/> objects
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <param name="templates">List of <see cref="Template"/> to save</param>
|
|
|
|
|
/// <param name="userId">Optional id of the user</param>
|
2021-02-09 10:22:42 +01:00
|
|
|
public void SaveTemplate(IEnumerable<ITemplate> templates, int userId = Cms.Core.Constants.Security.SuperUserId)
|
2017-12-28 09:18:09 +01:00
|
|
|
{
|
2021-03-30 14:01:37 +02:00
|
|
|
ITemplate[] templatesA = templates.ToArray();
|
|
|
|
|
using (IScope scope = ScopeProvider.CreateScope())
|
2017-12-28 09:18:09 +01:00
|
|
|
{
|
2021-03-30 14:01:37 +02:00
|
|
|
EventMessages eventMessages = EventMessagesFactory.Get();
|
|
|
|
|
var savingNotification = new TemplateSavingNotification(templatesA, eventMessages);
|
|
|
|
|
if (scope.Notifications.PublishCancelable(savingNotification))
|
2017-12-28 09:18:09 +01:00
|
|
|
{
|
|
|
|
|
scope.Complete();
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
2021-03-30 14:01:37 +02:00
|
|
|
foreach (ITemplate template in templatesA)
|
|
|
|
|
{
|
2017-12-28 09:18:09 +01:00
|
|
|
_templateRepository.Save(template);
|
2021-03-30 14:01:37 +02:00
|
|
|
}
|
2017-12-28 09:18:09 +01:00
|
|
|
|
2021-03-30 14:59:10 +02:00
|
|
|
scope.Notifications.Publish(new TemplateSavedNotification(templatesA, eventMessages).WithStateFrom(savingNotification));
|
2017-12-28 09:18:09 +01:00
|
|
|
|
2019-11-12 17:56:47 +11:00
|
|
|
Audit(AuditType.Save, userId, -1, UmbracoObjectTypes.Template.GetName());
|
2017-12-28 09:18:09 +01:00
|
|
|
scope.Complete();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// Deletes a template by its alias
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <param name="alias">Alias of the <see cref="ITemplate"/> to delete</param>
|
|
|
|
|
/// <param name="userId"></param>
|
2021-02-09 10:22:42 +01:00
|
|
|
public void DeleteTemplate(string alias, int userId = Cms.Core.Constants.Security.SuperUserId)
|
2017-12-28 09:18:09 +01:00
|
|
|
{
|
2021-03-30 12:14:32 +02:00
|
|
|
using (IScope scope = ScopeProvider.CreateScope())
|
2017-12-28 09:18:09 +01:00
|
|
|
{
|
2021-03-30 12:14:32 +02:00
|
|
|
ITemplate template = _templateRepository.Get(alias);
|
2017-12-28 09:18:09 +01:00
|
|
|
if (template == null)
|
|
|
|
|
{
|
|
|
|
|
scope.Complete();
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
2021-03-30 12:14:32 +02:00
|
|
|
EventMessages eventMessages = EventMessagesFactory.Get();
|
|
|
|
|
var deletingNotification = new TemplateDeletingNotification(template, eventMessages);
|
|
|
|
|
if (scope.Notifications.PublishCancelable(deletingNotification))
|
2017-12-28 09:18:09 +01:00
|
|
|
{
|
|
|
|
|
scope.Complete();
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
_templateRepository.Delete(template);
|
|
|
|
|
|
2021-03-30 12:14:32 +02:00
|
|
|
scope.Notifications.Publish(new TemplateDeletedNotification(template, eventMessages).WithStateFrom(deletingNotification));
|
2017-12-28 09:18:09 +01:00
|
|
|
|
2018-10-18 22:47:12 +11:00
|
|
|
Audit(AuditType.Delete, userId, template.Id, ObjectTypes.GetName(UmbracoObjectTypes.Template));
|
2017-12-28 09:18:09 +01:00
|
|
|
scope.Complete();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2018-07-18 13:19:48 +10:00
|
|
|
private string GetViewContent(string fileName)
|
|
|
|
|
{
|
|
|
|
|
if (fileName.IsNullOrWhiteSpace())
|
|
|
|
|
throw new ArgumentNullException(nameof(fileName));
|
2017-12-28 09:18:09 +01:00
|
|
|
|
2018-07-30 23:23:01 +10:00
|
|
|
if (!fileName.EndsWith(".cshtml"))
|
|
|
|
|
fileName = $"{fileName}.cshtml";
|
2018-07-18 13:19:48 +10:00
|
|
|
|
|
|
|
|
var fs = _templateRepository.GetFileContentStream(fileName);
|
2018-07-30 23:23:01 +10:00
|
|
|
if (fs == null) return null;
|
2018-07-18 13:19:48 +10:00
|
|
|
using (var view = new StreamReader(fs))
|
|
|
|
|
{
|
|
|
|
|
return view.ReadToEnd().Trim();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#endregion
|
2017-12-28 09:18:09 +01:00
|
|
|
|
2018-07-18 13:19:48 +10:00
|
|
|
#region Partial Views
|
2017-12-28 09:18:09 +01:00
|
|
|
|
|
|
|
|
public IEnumerable<string> GetPartialViewSnippetNames(params string[] filterNames)
|
|
|
|
|
{
|
2020-09-01 18:10:12 +02:00
|
|
|
var snippetPath = _hostingEnvironment.MapPathContentRoot($"{_globalSettings.UmbracoPath}/PartialViewMacros/Templates/");
|
2017-12-28 09:18:09 +01:00
|
|
|
var files = Directory.GetFiles(snippetPath, "*.cshtml")
|
|
|
|
|
.Select(Path.GetFileNameWithoutExtension)
|
|
|
|
|
.Except(filterNames, StringComparer.InvariantCultureIgnoreCase)
|
|
|
|
|
.ToArray();
|
|
|
|
|
|
|
|
|
|
//Ensure the ones that are called 'Empty' are at the top
|
|
|
|
|
var empty = files.Where(x => Path.GetFileName(x).InvariantStartsWith("Empty"))
|
|
|
|
|
.OrderBy(x => x.Length)
|
|
|
|
|
.ToArray();
|
|
|
|
|
|
|
|
|
|
return empty.Union(files.Except(empty));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public void DeletePartialViewFolder(string folderPath)
|
|
|
|
|
{
|
|
|
|
|
using (var scope = ScopeProvider.CreateScope())
|
|
|
|
|
{
|
|
|
|
|
_partialViewRepository.DeleteFolder(folderPath);
|
|
|
|
|
scope.Complete();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public void DeletePartialViewMacroFolder(string folderPath)
|
|
|
|
|
{
|
|
|
|
|
using (var scope = ScopeProvider.CreateScope())
|
|
|
|
|
{
|
|
|
|
|
_partialViewMacroRepository.DeleteFolder(folderPath);
|
|
|
|
|
scope.Complete();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public IPartialView GetPartialView(string path)
|
|
|
|
|
{
|
|
|
|
|
using (var scope = ScopeProvider.CreateScope(autoComplete: true))
|
|
|
|
|
{
|
|
|
|
|
return _partialViewRepository.Get(path);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public IPartialView GetPartialViewMacro(string path)
|
|
|
|
|
{
|
|
|
|
|
using (var scope = ScopeProvider.CreateScope(autoComplete: true))
|
|
|
|
|
{
|
|
|
|
|
return _partialViewMacroRepository.Get(path);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2021-02-09 10:22:42 +01:00
|
|
|
public Attempt<IPartialView> CreatePartialView(IPartialView partialView, string snippetName = null, int userId = Cms.Core.Constants.Security.SuperUserId)
|
2017-12-28 09:18:09 +01:00
|
|
|
{
|
|
|
|
|
return CreatePartialViewMacro(partialView, PartialViewType.PartialView, snippetName, userId);
|
|
|
|
|
}
|
|
|
|
|
|
2021-02-09 10:22:42 +01:00
|
|
|
public Attempt<IPartialView> CreatePartialViewMacro(IPartialView partialView, string snippetName = null, int userId = Cms.Core.Constants.Security.SuperUserId)
|
2017-12-28 09:18:09 +01:00
|
|
|
{
|
|
|
|
|
return CreatePartialViewMacro(partialView, PartialViewType.PartialViewMacro, snippetName, userId);
|
|
|
|
|
}
|
|
|
|
|
|
2021-02-09 10:22:42 +01:00
|
|
|
private Attempt<IPartialView> CreatePartialViewMacro(IPartialView partialView, PartialViewType partialViewType, string snippetName = null, int userId = Cms.Core.Constants.Security.SuperUserId)
|
2017-12-28 09:18:09 +01:00
|
|
|
{
|
|
|
|
|
string partialViewHeader;
|
|
|
|
|
switch (partialViewType)
|
|
|
|
|
{
|
|
|
|
|
case PartialViewType.PartialView:
|
|
|
|
|
partialViewHeader = PartialViewHeader;
|
|
|
|
|
break;
|
|
|
|
|
case PartialViewType.PartialViewMacro:
|
|
|
|
|
partialViewHeader = PartialViewMacroHeader;
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
throw new ArgumentOutOfRangeException(nameof(partialViewType));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
string partialViewContent = null;
|
|
|
|
|
if (snippetName.IsNullOrWhiteSpace() == false)
|
|
|
|
|
{
|
|
|
|
|
//create the file
|
2021-03-30 14:05:09 +02:00
|
|
|
Attempt<string> snippetPathAttempt = TryGetSnippetPath(snippetName);
|
2017-12-28 09:18:09 +01:00
|
|
|
if (snippetPathAttempt.Success == false)
|
|
|
|
|
{
|
|
|
|
|
throw new InvalidOperationException("Could not load snippet with name " + snippetName);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
using (var snippetFile = new StreamReader(System.IO.File.OpenRead(snippetPathAttempt.Result)))
|
|
|
|
|
{
|
|
|
|
|
var snippetContent = snippetFile.ReadToEnd().Trim();
|
|
|
|
|
|
|
|
|
|
//strip the @inherits if it's there
|
|
|
|
|
snippetContent = StripPartialViewHeader(snippetContent);
|
|
|
|
|
|
2019-01-29 10:46:10 +00:00
|
|
|
//Update Model.Content. to be Model. when used as PartialView
|
|
|
|
|
if(partialViewType == PartialViewType.PartialView)
|
|
|
|
|
{
|
|
|
|
|
snippetContent = snippetContent.Replace("Model.Content.", "Model.");
|
|
|
|
|
}
|
|
|
|
|
|
2017-12-28 09:18:09 +01:00
|
|
|
partialViewContent = $"{partialViewHeader}{Environment.NewLine}{snippetContent}";
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2021-03-30 14:05:09 +02:00
|
|
|
using (IScope scope = ScopeProvider.CreateScope())
|
2017-12-28 09:18:09 +01:00
|
|
|
{
|
2021-03-30 14:05:09 +02:00
|
|
|
EventMessages eventMessages = EventMessagesFactory.Get();
|
|
|
|
|
var creatingNotification = new PartialViewCreatingNotification(partialView, eventMessages);
|
|
|
|
|
if (scope.Notifications.PublishCancelable(creatingNotification))
|
2017-12-28 09:18:09 +01:00
|
|
|
{
|
|
|
|
|
scope.Complete();
|
|
|
|
|
return Attempt<IPartialView>.Fail();
|
|
|
|
|
}
|
|
|
|
|
|
2021-03-30 14:05:09 +02:00
|
|
|
IPartialViewRepository repository = GetPartialViewRepository(partialViewType);
|
|
|
|
|
if (partialViewContent != null)
|
|
|
|
|
{
|
|
|
|
|
partialView.Content = partialViewContent;
|
|
|
|
|
}
|
|
|
|
|
|
2017-12-28 09:18:09 +01:00
|
|
|
repository.Save(partialView);
|
|
|
|
|
|
2021-03-30 14:05:09 +02:00
|
|
|
scope.Notifications.Publish(new PartialViewCreatedNotification(partialView, eventMessages).WithStateFrom(creatingNotification));
|
2017-12-28 09:18:09 +01:00
|
|
|
|
2018-10-18 22:47:12 +11:00
|
|
|
Audit(AuditType.Save, userId, -1, partialViewType.ToString());
|
2017-12-28 09:18:09 +01:00
|
|
|
|
|
|
|
|
scope.Complete();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return Attempt<IPartialView>.Succeed(partialView);
|
2019-11-05 12:54:22 +01:00
|
|
|
}
|
2017-12-28 09:18:09 +01:00
|
|
|
|
2021-02-09 10:22:42 +01:00
|
|
|
public bool DeletePartialView(string path, int userId = Cms.Core.Constants.Security.SuperUserId)
|
2017-12-28 09:18:09 +01:00
|
|
|
{
|
|
|
|
|
return DeletePartialViewMacro(path, PartialViewType.PartialView, userId);
|
|
|
|
|
}
|
|
|
|
|
|
2021-02-09 10:22:42 +01:00
|
|
|
public bool DeletePartialViewMacro(string path, int userId = Cms.Core.Constants.Security.SuperUserId)
|
2017-12-28 09:18:09 +01:00
|
|
|
{
|
|
|
|
|
return DeletePartialViewMacro(path, PartialViewType.PartialViewMacro, userId);
|
|
|
|
|
}
|
|
|
|
|
|
2021-02-09 10:22:42 +01:00
|
|
|
private bool DeletePartialViewMacro(string path, PartialViewType partialViewType, int userId = Cms.Core.Constants.Security.SuperUserId)
|
2017-12-28 09:18:09 +01:00
|
|
|
{
|
2021-03-30 14:05:09 +02:00
|
|
|
using (IScope scope = ScopeProvider.CreateScope())
|
2017-12-28 09:18:09 +01:00
|
|
|
{
|
2021-03-30 14:05:09 +02:00
|
|
|
IPartialViewRepository repository = GetPartialViewRepository(partialViewType);
|
|
|
|
|
IPartialView partialView = repository.Get(path);
|
2017-12-28 09:18:09 +01:00
|
|
|
if (partialView == null)
|
|
|
|
|
{
|
|
|
|
|
scope.Complete();
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
2021-03-30 14:05:09 +02:00
|
|
|
EventMessages eventMessages = EventMessagesFactory.Get();
|
|
|
|
|
var deletingNotification = new PartialViewDeletingNotification(partialView, eventMessages);
|
|
|
|
|
if (scope.Notifications.PublishCancelable(deletingNotification))
|
2017-12-28 09:18:09 +01:00
|
|
|
{
|
|
|
|
|
scope.Complete();
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
repository.Delete(partialView);
|
2021-03-30 14:05:09 +02:00
|
|
|
scope.Notifications.Publish(new PartialViewDeletedNotification(partialView, eventMessages).WithStateFrom(deletingNotification));
|
2018-10-18 22:47:12 +11:00
|
|
|
Audit(AuditType.Delete, userId, -1, partialViewType.ToString());
|
2017-12-28 09:18:09 +01:00
|
|
|
|
|
|
|
|
scope.Complete();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
2021-02-09 10:22:42 +01:00
|
|
|
public Attempt<IPartialView> SavePartialView(IPartialView partialView, int userId = Cms.Core.Constants.Security.SuperUserId)
|
2017-12-28 09:18:09 +01:00
|
|
|
{
|
|
|
|
|
return SavePartialView(partialView, PartialViewType.PartialView, userId);
|
|
|
|
|
}
|
|
|
|
|
|
2021-02-09 10:22:42 +01:00
|
|
|
public Attempt<IPartialView> SavePartialViewMacro(IPartialView partialView, int userId = Cms.Core.Constants.Security.SuperUserId)
|
2017-12-28 09:18:09 +01:00
|
|
|
{
|
|
|
|
|
return SavePartialView(partialView, PartialViewType.PartialViewMacro, userId);
|
|
|
|
|
}
|
|
|
|
|
|
2021-02-09 10:22:42 +01:00
|
|
|
private Attempt<IPartialView> SavePartialView(IPartialView partialView, PartialViewType partialViewType, int userId = Cms.Core.Constants.Security.SuperUserId)
|
2017-12-28 09:18:09 +01:00
|
|
|
{
|
2021-03-30 14:05:09 +02:00
|
|
|
using (IScope scope = ScopeProvider.CreateScope())
|
2017-12-28 09:18:09 +01:00
|
|
|
{
|
2021-03-30 14:05:09 +02:00
|
|
|
EventMessages eventMessages = EventMessagesFactory.Get();
|
|
|
|
|
var savingNotification = new PartialViewSavingNotification(partialView, eventMessages);
|
|
|
|
|
if (scope.Notifications.PublishCancelable(savingNotification))
|
2017-12-28 09:18:09 +01:00
|
|
|
{
|
|
|
|
|
scope.Complete();
|
|
|
|
|
return Attempt<IPartialView>.Fail();
|
|
|
|
|
}
|
|
|
|
|
|
2021-03-30 14:05:09 +02:00
|
|
|
IPartialViewRepository repository = GetPartialViewRepository(partialViewType);
|
2017-12-28 09:18:09 +01:00
|
|
|
repository.Save(partialView);
|
2021-03-30 14:05:09 +02:00
|
|
|
|
2018-10-18 22:47:12 +11:00
|
|
|
Audit(AuditType.Save, userId, -1, partialViewType.ToString());
|
2021-03-30 14:05:09 +02:00
|
|
|
scope.Notifications.Publish(new PartialViewSavedNotification(partialView, eventMessages).WithStateFrom(savingNotification));
|
2017-12-28 09:18:09 +01:00
|
|
|
|
|
|
|
|
scope.Complete();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return Attempt.Succeed(partialView);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
internal string StripPartialViewHeader(string contents)
|
|
|
|
|
{
|
|
|
|
|
var headerMatch = new Regex("^@inherits\\s+?.*$", RegexOptions.Multiline);
|
|
|
|
|
return headerMatch.Replace(contents, string.Empty);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
internal Attempt<string> TryGetSnippetPath(string fileName)
|
|
|
|
|
{
|
|
|
|
|
if (fileName.EndsWith(".cshtml") == false)
|
|
|
|
|
{
|
|
|
|
|
fileName += ".cshtml";
|
|
|
|
|
}
|
|
|
|
|
|
2020-09-01 18:10:12 +02:00
|
|
|
var snippetPath = _hostingEnvironment.MapPathContentRoot($"{_globalSettings.UmbracoPath}/PartialViewMacros/Templates/{fileName}");
|
2017-12-28 09:18:09 +01:00
|
|
|
return System.IO.File.Exists(snippetPath)
|
|
|
|
|
? Attempt<string>.Succeed(snippetPath)
|
|
|
|
|
: Attempt<string>.Fail();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public void CreatePartialViewFolder(string folderPath)
|
|
|
|
|
{
|
|
|
|
|
using (var scope = ScopeProvider.CreateScope())
|
|
|
|
|
{
|
|
|
|
|
_partialViewRepository.AddFolder(folderPath);
|
|
|
|
|
scope.Complete();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public void CreatePartialViewMacroFolder(string folderPath)
|
|
|
|
|
{
|
|
|
|
|
using (var scope = ScopeProvider.CreateScope())
|
|
|
|
|
{
|
|
|
|
|
_partialViewMacroRepository.AddFolder(folderPath);
|
|
|
|
|
scope.Complete();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private IPartialViewRepository GetPartialViewRepository(PartialViewType partialViewType)
|
|
|
|
|
{
|
|
|
|
|
switch (partialViewType)
|
|
|
|
|
{
|
|
|
|
|
case PartialViewType.PartialView:
|
|
|
|
|
return _partialViewRepository;
|
|
|
|
|
case PartialViewType.PartialViewMacro:
|
|
|
|
|
return _partialViewMacroRepository;
|
|
|
|
|
default:
|
|
|
|
|
throw new ArgumentOutOfRangeException(nameof(partialViewType));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#endregion
|
|
|
|
|
|
|
|
|
|
#region Snippets
|
|
|
|
|
|
|
|
|
|
public string GetPartialViewSnippetContent(string snippetName)
|
|
|
|
|
{
|
|
|
|
|
return GetPartialViewMacroSnippetContent(snippetName, PartialViewType.PartialView);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public string GetPartialViewMacroSnippetContent(string snippetName)
|
|
|
|
|
{
|
|
|
|
|
return GetPartialViewMacroSnippetContent(snippetName, PartialViewType.PartialViewMacro);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private string GetPartialViewMacroSnippetContent(string snippetName, PartialViewType partialViewType)
|
|
|
|
|
{
|
|
|
|
|
if (snippetName.IsNullOrWhiteSpace())
|
|
|
|
|
throw new ArgumentNullException(nameof(snippetName));
|
|
|
|
|
|
|
|
|
|
string partialViewHeader;
|
|
|
|
|
switch (partialViewType)
|
|
|
|
|
{
|
|
|
|
|
case PartialViewType.PartialView:
|
|
|
|
|
partialViewHeader = PartialViewHeader;
|
|
|
|
|
break;
|
|
|
|
|
case PartialViewType.PartialViewMacro:
|
|
|
|
|
partialViewHeader = PartialViewMacroHeader;
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
throw new ArgumentOutOfRangeException(nameof(partialViewType));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Try and get the snippet path
|
|
|
|
|
var snippetPathAttempt = TryGetSnippetPath(snippetName);
|
|
|
|
|
if (snippetPathAttempt.Success == false)
|
|
|
|
|
{
|
|
|
|
|
throw new InvalidOperationException("Could not load snippet with name " + snippetName);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
using (var snippetFile = new StreamReader(System.IO.File.OpenRead(snippetPathAttempt.Result)))
|
|
|
|
|
{
|
|
|
|
|
var snippetContent = snippetFile.ReadToEnd().Trim();
|
|
|
|
|
|
|
|
|
|
//strip the @inherits if it's there
|
|
|
|
|
snippetContent = StripPartialViewHeader(snippetContent);
|
|
|
|
|
|
2019-04-04 19:41:39 +02:00
|
|
|
//Update Model.Content to be Model when used as PartialView
|
2019-01-29 10:46:10 +00:00
|
|
|
if (partialViewType == PartialViewType.PartialView)
|
|
|
|
|
{
|
2019-04-04 19:41:39 +02:00
|
|
|
snippetContent = snippetContent
|
|
|
|
|
.Replace("Model.Content.", "Model.")
|
|
|
|
|
.Replace("(Model.Content)", "(Model)");
|
2019-01-29 10:46:10 +00:00
|
|
|
}
|
|
|
|
|
|
2017-12-28 09:18:09 +01:00
|
|
|
var content = $"{partialViewHeader}{Environment.NewLine}{snippetContent}";
|
|
|
|
|
return content;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#endregion
|
2019-11-05 12:54:22 +01:00
|
|
|
|
2018-10-18 22:47:12 +11:00
|
|
|
private void Audit(AuditType type, int userId, int objectId, string entityType)
|
2017-12-28 09:18:09 +01:00
|
|
|
{
|
2018-10-18 22:47:12 +11:00
|
|
|
_auditRepository.Save(new AuditItem(objectId, type, userId, entityType));
|
2017-12-28 09:18:09 +01:00
|
|
|
}
|
|
|
|
|
|
2019-01-27 01:17:32 -05:00
|
|
|
// TODO: Method to change name and/or alias of view template
|
2017-12-28 09:18:09 +01:00
|
|
|
}
|
2018-04-20 17:40:01 +10:00
|
|
|
}
|