Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Ability to register your own content provider for default template content #11317

Merged
merged 9 commits into from
Oct 27, 2021
Merged
Show file tree
Hide file tree
Changes from 8 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
20 changes: 17 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,27 @@ public class TemplateController : BackOfficeNotificationsController
private readonly IFileService _fileService;
private readonly IUmbracoMapper _umbracoMapper;
private readonly IShortStringHelper _shortStringHelper;
private readonly IDefaultViewContentProvider _defaultViewContentProvider;

public TemplateController(
IFileService fileService,
IUmbracoMapper umbracoMapper,
IShortStringHelper shortStringHelper)
IShortStringHelper shortStringHelper,
IDefaultViewContentProvider defaultViewContentProvider)
bergmania marked this conversation as resolved.
Show resolved Hide resolved
{
_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 +150,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