Skip to content

Commit

Permalink
Merge pull request #11317 from matthewcare/custom-default-view-content
Browse files Browse the repository at this point in the history
Ability to register your own content provider for default template content
  • Loading branch information
bergmania authored Oct 27, 2021
2 parents 3ddb2c6 + ded1c0b commit af5be82
Show file tree
Hide file tree
Showing 13 changed files with 170 additions and 89 deletions.
62 changes: 62 additions & 0 deletions src/Umbraco.Core/IO/DefaultViewContentProvider.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
using System.Text;
using Umbraco.Extensions;

namespace Umbraco.Cms.Core.IO
{
public class DefaultViewContentProvider : IDefaultViewContentProvider
{
public string GetDefaultFileContent(string layoutPageAlias = null, string modelClassName = null, string modelNamespace = null, string modelNamespaceAlias = null)
{
var content = new StringBuilder();

if (string.IsNullOrWhiteSpace(modelNamespaceAlias))
modelNamespaceAlias = "ContentModels";

// either
// @inherits Umbraco.Web.Mvc.UmbracoViewPage
// @inherits Umbraco.Web.Mvc.UmbracoViewPage<ModelClass>
content.AppendLine("@using Umbraco.Cms.Web.Common.PublishedModels;");
content.Append("@inherits Umbraco.Cms.Web.Common.Views.UmbracoViewPage");
if (modelClassName.IsNullOrWhiteSpace() == false)
{
content.Append("<");
if (modelNamespace.IsNullOrWhiteSpace() == false)
{
content.Append(modelNamespaceAlias);
content.Append(".");
}
content.Append(modelClassName);
content.Append(">");
}
content.Append("\r\n");

// if required, add
// @using ContentModels = ModelNamespace;
if (modelClassName.IsNullOrWhiteSpace() == false && modelNamespace.IsNullOrWhiteSpace() == false)
{
content.Append("@using ");
content.Append(modelNamespaceAlias);
content.Append(" = ");
content.Append(modelNamespace);
content.Append(";\r\n");
}

// either
// Layout = null;
// Layout = "layoutPage.cshtml";
content.Append("@{\r\n\tLayout = ");
if (layoutPageAlias.IsNullOrWhiteSpace())
{
content.Append("null");
}
else
{
content.Append("\"");
content.Append(layoutPageAlias);
content.Append(".cshtml\"");
}
content.Append(";\r\n}");
return content.ToString();
}
}
}
8 changes: 8 additions & 0 deletions src/Umbraco.Core/IO/IDefaultViewContentProvider.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
namespace Umbraco.Cms.Core.IO
{
public interface IDefaultViewContentProvider
{
string GetDefaultFileContent(string layoutPageAlias = null, string modelClassName = null,
string modelNamespace = null, string modelNamespaceAlias = null);
}
}
13 changes: 13 additions & 0 deletions src/Umbraco.Core/IO/IViewHelper.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
using Umbraco.Cms.Core.Models;

namespace Umbraco.Cms.Core.IO
{
public interface IViewHelper
{
bool ViewExists(ITemplate t);
string GetFileContents(ITemplate t);
string CreateView(ITemplate t, bool overWrite = false);
string UpdateViewFile(ITemplate t, string currentAlias = null);
string ViewPath(string alias);
}
}
79 changes: 21 additions & 58 deletions src/Umbraco.Core/IO/ViewHelper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,26 +2,34 @@
using System.IO;
using System.Linq;
using System.Text;
using Microsoft.Extensions.DependencyInjection;
using Umbraco.Cms.Core.Models;
using Umbraco.Cms.Web.Common.DependencyInjection;
using Umbraco.Extensions;

namespace Umbraco.Cms.Core.IO
{
public class ViewHelper
public class ViewHelper : IViewHelper
{
private readonly IFileSystem _viewFileSystem;
private readonly IDefaultViewContentProvider _defaultViewContentProvider;

[Obsolete("Use ctor with all params")]
public ViewHelper(IFileSystem viewFileSystem)
{
if (viewFileSystem == null) throw new ArgumentNullException(nameof(viewFileSystem));
_viewFileSystem = viewFileSystem;
_viewFileSystem = viewFileSystem ?? throw new ArgumentNullException(nameof(viewFileSystem));
_defaultViewContentProvider = StaticServiceProvider.Instance.GetRequiredService<IDefaultViewContentProvider>();
}

internal bool ViewExists(ITemplate t)
public ViewHelper(FileSystems fileSystems, IDefaultViewContentProvider defaultViewContentProvider)
{
return _viewFileSystem.FileExists(ViewPath(t.Alias));
_viewFileSystem = fileSystems.MvcViewsFileSystem ?? throw new ArgumentNullException(nameof(fileSystems));
_defaultViewContentProvider = defaultViewContentProvider ?? throw new ArgumentNullException(nameof(defaultViewContentProvider));
}

public bool ViewExists(ITemplate t) => _viewFileSystem.FileExists(ViewPath(t.Alias));


public string GetFileContents(ITemplate t)
{
var viewContent = "";
Expand Down Expand Up @@ -60,58 +68,13 @@ public string CreateView(ITemplate t, bool overWrite = false)
return viewContent;
}

public static string GetDefaultFileContent(string layoutPageAlias = null, string modelClassName = null, string modelNamespace = null, string modelNamespaceAlias = null)
[Obsolete("Inject IDefaultViewContentProvider instead")]
public static string GetDefaultFileContent(string layoutPageAlias = null, string modelClassName = null,
string modelNamespace = null, string modelNamespaceAlias = null)
{
var content = new StringBuilder();

if (string.IsNullOrWhiteSpace(modelNamespaceAlias))
modelNamespaceAlias = "ContentModels";

// either
// @inherits Umbraco.Web.Mvc.UmbracoViewPage
// @inherits Umbraco.Web.Mvc.UmbracoViewPage<ModelClass>
content.AppendLine("@using Umbraco.Cms.Web.Common.PublishedModels;");
content.Append("@inherits Umbraco.Cms.Web.Common.Views.UmbracoViewPage");
if (modelClassName.IsNullOrWhiteSpace() == false)
{
content.Append("<");
if (modelNamespace.IsNullOrWhiteSpace() == false)
{
content.Append(modelNamespaceAlias);
content.Append(".");
}
content.Append(modelClassName);
content.Append(">");
}
content.Append("\r\n");

// if required, add
// @using ContentModels = ModelNamespace;
if (modelClassName.IsNullOrWhiteSpace() == false && modelNamespace.IsNullOrWhiteSpace() == false)
{
content.Append("@using ");
content.Append(modelNamespaceAlias);
content.Append(" = ");
content.Append(modelNamespace);
content.Append(";\r\n");
}

// either
// Layout = null;
// Layout = "layoutPage.cshtml";
content.Append("@{\r\n\tLayout = ");
if (layoutPageAlias.IsNullOrWhiteSpace())
{
content.Append("null");
}
else
{
content.Append("\"");
content.Append(layoutPageAlias);
content.Append(".cshtml\"");
}
content.Append(";\r\n}");
return content.ToString();
var viewContentProvider = StaticServiceProvider.Instance.GetRequiredService<IDefaultViewContentProvider>();
return viewContentProvider.GetDefaultFileContent(layoutPageAlias, modelClassName, modelNamespace,
modelNamespaceAlias);
}

private string SaveTemplateToFile(ITemplate template)
Expand Down Expand Up @@ -157,12 +120,12 @@ public string ViewPath(string alias)
return _viewFileSystem.GetRelativePath(alias.Replace(" ", "") + ".cshtml");
}

private static string EnsureInheritedLayout(ITemplate template)
private string EnsureInheritedLayout(ITemplate template)
{
var design = template.Content;

if (string.IsNullOrEmpty(design))
design = GetDefaultFileContent(template.MasterTemplateAlias);
design = _defaultViewContentProvider.GetDefaultFileContent(template.MasterTemplateAlias);

return design;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,9 @@ internal static IUmbracoBuilder AddFileSystems(this IUmbracoBuilder builder)
// register the scheme for media paths
builder.Services.AddUnique<IMediaPathScheme, UniqueMediaPathScheme>();

builder.Services.AddUnique<IViewHelper, ViewHelper>();
builder.Services.AddUnique<IDefaultViewContentProvider, DefaultViewContentProvider>();

builder.SetMediaFileSystem(factory =>
{
IIOHelper ioHelper = factory.GetRequiredService<IIOHelper>();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,19 @@ public static IUmbracoBuilder SetCultureDictionaryFactory<T>(this IUmbracoBuilde
return builder;
}

/// <summary>
/// Sets the default view content provider
/// </summary>
/// <typeparam name="T">The type of the provider.</typeparam>
/// <param name="builder">The builder.</param>
/// <returns></returns>
public static IUmbracoBuilder SetDefaultViewContentProvider<T>(this IUmbracoBuilder builder)
where T : class, IDefaultViewContentProvider
{
builder.Services.AddUnique<IDefaultViewContentProvider, T>();
return builder;
}

/// <summary>
/// Sets the culture dictionary factory.
/// </summary>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,15 +29,15 @@ internal class TemplateRepository : EntityRepositoryBase<int, ITemplate>, ITempl
private readonly IIOHelper _ioHelper;
private readonly IShortStringHelper _shortStringHelper;
private readonly IFileSystem _viewsFileSystem;
private readonly ViewHelper _viewHelper;
private readonly IViewHelper _viewHelper;

public TemplateRepository(IScopeAccessor scopeAccessor, AppCaches cache, ILogger<TemplateRepository> logger, FileSystems fileSystems, IIOHelper ioHelper, IShortStringHelper shortStringHelper)
public TemplateRepository(IScopeAccessor scopeAccessor, AppCaches cache, ILogger<TemplateRepository> logger, FileSystems fileSystems, IIOHelper ioHelper, IShortStringHelper shortStringHelper, IViewHelper viewHelper)
: base(scopeAccessor, cache, logger)
{
_ioHelper = ioHelper;
_shortStringHelper = shortStringHelper;
_viewsFileSystem = fileSystems.MvcViewsFileSystem;
_viewHelper = new ViewHelper(_viewsFileSystem);
_viewHelper = viewHelper;
}

protected override IRepositoryCachePolicy<ITemplate, int> CreateCachePolicy() =>
Expand Down
21 changes: 18 additions & 3 deletions src/Umbraco.Web.BackOffice/Controllers/TemplateController.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
using System.Linq;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.DependencyInjection;
using Umbraco.Cms.Core;
using Umbraco.Cms.Core.IO;
using Umbraco.Cms.Core.Mapping;
Expand All @@ -12,6 +13,7 @@
using Umbraco.Cms.Core.Strings;
using Umbraco.Cms.Web.Common.Attributes;
using Umbraco.Cms.Web.Common.Authorization;
using Umbraco.Cms.Web.Common.DependencyInjection;
using Constants = Umbraco.Cms.Core.Constants;

namespace Umbraco.Cms.Web.BackOffice.Controllers
Expand All @@ -24,15 +26,28 @@ public class TemplateController : BackOfficeNotificationsController
private readonly IFileService _fileService;
private readonly IUmbracoMapper _umbracoMapper;
private readonly IShortStringHelper _shortStringHelper;
private readonly IDefaultViewContentProvider _defaultViewContentProvider;

[ActivatorUtilitiesConstructor]
public TemplateController(
IFileService fileService,
IUmbracoMapper umbracoMapper,
IShortStringHelper shortStringHelper)
IShortStringHelper shortStringHelper,
IDefaultViewContentProvider defaultViewContentProvider)
{
_fileService = fileService ?? throw new ArgumentNullException(nameof(fileService));
_umbracoMapper = umbracoMapper ?? throw new ArgumentNullException(nameof(umbracoMapper));
_shortStringHelper = shortStringHelper ?? throw new ArgumentNullException(nameof(shortStringHelper));
_defaultViewContentProvider = defaultViewContentProvider ?? throw new ArgumentNullException(nameof(defaultViewContentProvider));
}

[Obsolete("Use ctor will all params")]
public TemplateController(
IFileService fileService,
IUmbracoMapper umbracoMapper,
IShortStringHelper shortStringHelper)
: this(fileService, umbracoMapper, shortStringHelper, StaticServiceProvider.Instance.GetRequiredService<IDefaultViewContentProvider>())
{
}

/// <summary>
Expand Down Expand Up @@ -136,10 +151,10 @@ public TemplateDisplay GetScaffold(int id)
}
}

var content = ViewHelper.GetDefaultFileContent( layoutPageAlias: dt.MasterTemplateAlias );
var content = _defaultViewContentProvider.GetDefaultFileContent( layoutPageAlias: dt.MasterTemplateAlias );
var scaffold = _umbracoMapper.Map<ITemplate, TemplateDisplay>(dt);

scaffold.Content = content + "\r\n\r\n@* the fun starts here *@\r\n\r\n";
scaffold.Content = content;
return scaffold;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,15 +26,17 @@ internal class ModelsBuilderNotificationHandler :
private readonly ModelsBuilderSettings _config;
private readonly IShortStringHelper _shortStringHelper;
private readonly IModelsBuilderDashboardProvider _modelsBuilderDashboardProvider;
private readonly IDefaultViewContentProvider _defaultViewContentProvider;

public ModelsBuilderNotificationHandler(
IOptions<ModelsBuilderSettings> config,
IShortStringHelper shortStringHelper,
IModelsBuilderDashboardProvider modelsBuilderDashboardProvider)
IModelsBuilderDashboardProvider modelsBuilderDashboardProvider, IDefaultViewContentProvider defaultViewContentProvider)
{
_config = config.Value;
_shortStringHelper = shortStringHelper;
_modelsBuilderDashboardProvider = modelsBuilderDashboardProvider;
_defaultViewContentProvider = defaultViewContentProvider;
}

/// <summary>
Expand Down Expand Up @@ -123,7 +125,7 @@ public void Handle(TemplateSavingNotification notification)

// we do not support configuring this at the moment, so just let Umbraco use its default value
// var modelNamespaceAlias = ...;
var markup = ViewHelper.GetDefaultFileContent(
var markup = _defaultViewContentProvider.GetDefaultFileContent(
modelClassName: className,
modelNamespace: modelNamespace/*,
modelNamespaceAlias: modelNamespaceAlias*/);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
using System.Collections.Generic;
using System.Linq;
using Microsoft.Extensions.Logging;
using Moq;
using NUnit.Framework;
using Umbraco.Cms.Core.Cache;
using Umbraco.Cms.Core.IO;
Expand Down Expand Up @@ -73,7 +74,7 @@ public void Maps_Templates_Correctly()
IScopeProvider provider = ScopeProvider;
using (IScope scope = provider.CreateScope())
{
var templateRepo = new TemplateRepository((IScopeAccessor)provider, AppCaches.Disabled, LoggerFactory.CreateLogger<TemplateRepository>(), FileSystems, IOHelper, ShortStringHelper);
var templateRepo = new TemplateRepository((IScopeAccessor)provider, AppCaches.Disabled, LoggerFactory.CreateLogger<TemplateRepository>(), FileSystems, IOHelper, ShortStringHelper, Mock.Of<IViewHelper>());
ContentTypeRepository repository = ContentTypeRepository;
Template[] templates = new[]
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,7 @@ private DocumentRepository CreateRepository(IScopeAccessor scopeAccessor, out Co

appCaches ??= AppCaches;

templateRepository = new TemplateRepository(scopeAccessor, appCaches, LoggerFactory.CreateLogger<TemplateRepository>(), FileSystems, IOHelper, ShortStringHelper);
templateRepository = new TemplateRepository(scopeAccessor, appCaches, LoggerFactory.CreateLogger<TemplateRepository>(), FileSystems, IOHelper, ShortStringHelper, Mock.Of<IViewHelper>());
var tagRepository = new TagRepository(scopeAccessor, appCaches, LoggerFactory.CreateLogger<TagRepository>());
var commonRepository = new ContentTypeCommonRepository(scopeAccessor, templateRepository, appCaches, ShortStringHelper);
var languageRepository = new LanguageRepository(scopeAccessor, appCaches, LoggerFactory.CreateLogger<LanguageRepository>(), globalSettings);
Expand Down
Loading

0 comments on commit af5be82

Please sign in to comment.