Merge pull request #4332 from umbraco/temp8-macros-dont-render-and-other-macro-bugs
v8 Macros don't render in the RTE and various
This commit is contained in:
@@ -2,6 +2,7 @@
|
||||
using System.Linq;
|
||||
using System.Web.Mvc;
|
||||
using System.Web.Routing;
|
||||
using System.Web.Security;
|
||||
using Moq;
|
||||
using NUnit.Framework;
|
||||
using Umbraco.Core;
|
||||
@@ -17,12 +18,15 @@ using Umbraco.Web.WebApi;
|
||||
using Umbraco.Core.Strings;
|
||||
using Umbraco.Core.Composing;
|
||||
using Umbraco.Core.Configuration;
|
||||
using Umbraco.Core.Dictionary;
|
||||
using Umbraco.Core.Models.PublishedContent;
|
||||
using Umbraco.Core.Persistence;
|
||||
using Umbraco.Core.Services;
|
||||
using Umbraco.Tests.PublishedContent;
|
||||
using Umbraco.Tests.Testing;
|
||||
using Umbraco.Tests.Testing.Objects.Accessors;
|
||||
using Umbraco.Web.Runtime;
|
||||
using Umbraco.Web.Security;
|
||||
using Current = Umbraco.Web.Composing.Current;
|
||||
|
||||
namespace Umbraco.Tests.Routing
|
||||
@@ -136,7 +140,16 @@ namespace Umbraco.Tests.Routing
|
||||
var type = new AutoPublishedContentType(22, "CustomDocument", new PublishedPropertyType[] { });
|
||||
ContentTypesCache.GetPublishedContentTypeByAlias = alias => type;
|
||||
|
||||
var handler = new RenderRouteHandler(umbracoContext, new TestControllerFactory(umbracoContext, Mock.Of<ILogger>()));
|
||||
var handler = new RenderRouteHandler(umbracoContext, new TestControllerFactory(umbracoContext, Mock.Of<ILogger>(), context =>
|
||||
{
|
||||
var membershipHelper = new MembershipHelper(new TestUmbracoContextAccessor(umbracoContext), Mock.Of<MembershipProvider>(), Mock.Of<RoleProvider>(), Mock.Of<IMemberService>(), Mock.Of<IMemberTypeService>(), Mock.Of<IUserService>(), Mock.Of<IPublicAccessService>(), Mock.Of<AppCaches>(), Mock.Of<ILogger>());
|
||||
return new CustomDocumentController(Factory.GetInstance<IGlobalSettings>(),
|
||||
umbracoContext,
|
||||
Factory.GetInstance<ServiceContext>(),
|
||||
Factory.GetInstance<AppCaches>(),
|
||||
Factory.GetInstance<IProfilingLogger>(),
|
||||
new UmbracoHelper(umbracoContext, Mock.Of<ITagQuery>(), Mock.Of<ICultureDictionaryFactory>(), Mock.Of<IUmbracoComponentRenderer>(), Mock.Of<IPublishedContentQuery>(), membershipHelper));
|
||||
}));
|
||||
|
||||
handler.GetHandlerForRoute(umbracoContext.HttpContext.Request.RequestContext, frequest);
|
||||
Assert.AreEqual("CustomDocument", routeData.Values["controller"].ToString());
|
||||
@@ -172,8 +185,8 @@ namespace Umbraco.Tests.Routing
|
||||
/// </summary>
|
||||
public class CustomDocumentController : RenderMvcController
|
||||
{
|
||||
public CustomDocumentController(IGlobalSettings globalSettings, UmbracoContext umbracoContext, ServiceContext services, AppCaches appCaches, ILogger logger, IProfilingLogger profilingLogger)
|
||||
: base(globalSettings, umbracoContext, services, appCaches, logger, profilingLogger)
|
||||
public CustomDocumentController(IGlobalSettings globalSettings, UmbracoContext umbracoContext, ServiceContext services, AppCaches appCaches, IProfilingLogger profilingLogger, UmbracoHelper umbracoHelper)
|
||||
: base(globalSettings, umbracoContext, services, appCaches, profilingLogger, umbracoHelper)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
@@ -7,16 +7,16 @@ namespace Umbraco.Tests.TestHelpers.ControllerTesting
|
||||
{
|
||||
public class TestControllerActivator : TestControllerActivatorBase
|
||||
{
|
||||
private readonly Func<HttpRequestMessage, UmbracoHelper, ApiController> _factory;
|
||||
private readonly Func<HttpRequestMessage, UmbracoContext, UmbracoHelper, ApiController> _factory;
|
||||
|
||||
public TestControllerActivator(Func<HttpRequestMessage, UmbracoHelper, ApiController> factory)
|
||||
public TestControllerActivator(Func<HttpRequestMessage, UmbracoContext, UmbracoHelper, ApiController> factory)
|
||||
{
|
||||
_factory = factory;
|
||||
}
|
||||
|
||||
protected override ApiController CreateController(Type controllerType, HttpRequestMessage msg, UmbracoHelper helper)
|
||||
protected override ApiController CreateController(Type controllerType, HttpRequestMessage msg, UmbracoContext umbracoContext, UmbracoHelper helper)
|
||||
{
|
||||
return _factory(msg, helper);
|
||||
return _factory(msg, umbracoContext, helper);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -152,17 +152,16 @@ namespace Umbraco.Tests.TestHelpers.ControllerTesting
|
||||
|
||||
var membershipHelper = new MembershipHelper(new TestUmbracoContextAccessor(umbCtx), Mock.Of<MembershipProvider>(), Mock.Of<RoleProvider>(), Mock.Of<IMemberService>(), Mock.Of<IMemberTypeService>(), Mock.Of<IUserService>(), Mock.Of<IPublicAccessService>(), Mock.Of<AppCaches>(), Mock.Of<ILogger>());
|
||||
|
||||
var umbHelper = new UmbracoHelper(umbCtx,
|
||||
Mock.Of<IPublishedContent>(),
|
||||
var umbHelper = new UmbracoHelper(umbCtx,
|
||||
Mock.Of<ITagQuery>(),
|
||||
Mock.Of<ICultureDictionary>(),
|
||||
Mock.Of<ICultureDictionaryFactory>(),
|
||||
Mock.Of<IUmbracoComponentRenderer>(),
|
||||
membershipHelper,
|
||||
serviceContext);
|
||||
Mock.Of<IPublishedContentQuery>(),
|
||||
membershipHelper);
|
||||
|
||||
return CreateController(controllerType, request, umbHelper);
|
||||
return CreateController(controllerType, request, umbCtx, umbHelper);
|
||||
}
|
||||
|
||||
protected abstract ApiController CreateController(Type controllerType, HttpRequestMessage msg, UmbracoHelper helper);
|
||||
protected abstract ApiController CreateController(Type controllerType, HttpRequestMessage msg, UmbracoContext umbracoContext, UmbracoHelper helper);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,9 +15,9 @@ namespace Umbraco.Tests.TestHelpers.ControllerTesting
|
||||
{
|
||||
public class TestRunner
|
||||
{
|
||||
private readonly Func<HttpRequestMessage, UmbracoHelper, ApiController> _controllerFactory;
|
||||
private readonly Func<HttpRequestMessage, UmbracoContext, UmbracoHelper, ApiController> _controllerFactory;
|
||||
|
||||
public TestRunner(Func<HttpRequestMessage, UmbracoHelper, ApiController> controllerFactory)
|
||||
public TestRunner(Func<HttpRequestMessage, UmbracoContext, UmbracoHelper, ApiController> controllerFactory)
|
||||
{
|
||||
_controllerFactory = controllerFactory;
|
||||
}
|
||||
|
||||
@@ -16,10 +16,10 @@ namespace Umbraco.Tests.TestHelpers.ControllerTesting
|
||||
/// </summary>
|
||||
public class TestStartup
|
||||
{
|
||||
private readonly Func<HttpRequestMessage, UmbracoHelper, ApiController> _controllerFactory;
|
||||
private readonly Func<HttpRequestMessage, UmbracoContext, UmbracoHelper, ApiController> _controllerFactory;
|
||||
private readonly Action<HttpConfiguration> _initialize;
|
||||
|
||||
public TestStartup(Action<HttpConfiguration> initialize, Func<HttpRequestMessage, UmbracoHelper, ApiController> controllerFactory)
|
||||
public TestStartup(Action<HttpConfiguration> initialize, Func<HttpRequestMessage, UmbracoContext, UmbracoHelper, ApiController> controllerFactory)
|
||||
{
|
||||
_controllerFactory = controllerFactory;
|
||||
_initialize = initialize;
|
||||
|
||||
@@ -19,6 +19,7 @@ namespace Umbraco.Tests.TestHelpers.Stubs
|
||||
{
|
||||
private readonly UmbracoContext _umbracoContext;
|
||||
private readonly ILogger _logger;
|
||||
private readonly Func<RequestContext, IController> _factory;
|
||||
|
||||
public TestControllerFactory(UmbracoContext umbracoContext, ILogger logger)
|
||||
{
|
||||
@@ -26,8 +27,17 @@ namespace Umbraco.Tests.TestHelpers.Stubs
|
||||
_logger = logger;
|
||||
}
|
||||
|
||||
public TestControllerFactory(UmbracoContext umbracoContext, ILogger logger, Func<RequestContext, IController> factory)
|
||||
{
|
||||
_umbracoContext = umbracoContext;
|
||||
_logger = logger;
|
||||
_factory = factory;
|
||||
}
|
||||
|
||||
public IController CreateController(RequestContext requestContext, string controllerName)
|
||||
{
|
||||
if (_factory != null) return _factory(requestContext);
|
||||
|
||||
var types = TypeFinder.FindClassesOfType<ControllerBase>(new[] { Assembly.GetExecutingAssembly() });
|
||||
|
||||
var controllerTypes = types.Where(x => x.Name.Equals(controllerName + "Controller", StringComparison.InvariantCultureIgnoreCase));
|
||||
|
||||
@@ -61,12 +61,11 @@ namespace Umbraco.Tests.Testing.TestingTests
|
||||
|
||||
// ReSharper disable once UnusedVariable
|
||||
var helper = new UmbracoHelper(umbracoContext,
|
||||
Mock.Of<IPublishedContent>(),
|
||||
Mock.Of<ITagQuery>(),
|
||||
Mock.Of<ICultureDictionary>(),
|
||||
Mock.Of<ICultureDictionaryFactory>(),
|
||||
Mock.Of<IUmbracoComponentRenderer>(),
|
||||
new MembershipHelper(new TestUmbracoContextAccessor(umbracoContext), Mock.Of<MembershipProvider>(), Mock.Of<RoleProvider>(), Mock.Of<IMemberService>(), Mock.Of<IMemberTypeService>(), Mock.Of<IUserService>(), Mock.Of<IPublicAccessService>(), Mock.Of<AppCaches>(), Mock.Of<ILogger>()),
|
||||
ServiceContext.CreatePartial());
|
||||
Mock.Of<IPublishedContentQuery>(),
|
||||
new MembershipHelper(new TestUmbracoContextAccessor(umbracoContext), Mock.Of<MembershipProvider>(), Mock.Of<RoleProvider>(), Mock.Of<IMemberService>(), Mock.Of<IMemberTypeService>(), Mock.Of<IUserService>(), Mock.Of<IPublicAccessService>(), Mock.Of<AppCaches>(), Mock.Of<ILogger>()));
|
||||
Assert.Pass();
|
||||
}
|
||||
|
||||
|
||||
@@ -38,9 +38,11 @@ using Umbraco.Tests.Testing.Objects.Accessors;
|
||||
using Umbraco.Web.Actions;
|
||||
using Umbraco.Web.Composing.Composers;
|
||||
using Umbraco.Web.ContentApps;
|
||||
using Umbraco.Web.Macros;
|
||||
using Umbraco.Web.PublishedCache;
|
||||
using Current = Umbraco.Core.Composing.Current;
|
||||
using Umbraco.Web.Routing;
|
||||
using Umbraco.Web.Templates;
|
||||
using Umbraco.Web.Trees;
|
||||
|
||||
namespace Umbraco.Tests.Testing
|
||||
@@ -228,6 +230,7 @@ namespace Umbraco.Tests.Testing
|
||||
.Append<MembersBackOfficeSection>()
|
||||
.Append<TranslationBackOfficeSection>();
|
||||
Composition.RegisterUnique<ISectionService, SectionService>();
|
||||
|
||||
}
|
||||
|
||||
protected virtual void ComposeWtf()
|
||||
|
||||
@@ -30,6 +30,11 @@ using System;
|
||||
using Umbraco.Web.WebApi;
|
||||
using Umbraco.Web.Trees;
|
||||
using System.Globalization;
|
||||
using Umbraco.Core;
|
||||
using Umbraco.Core.Cache;
|
||||
using Umbraco.Core.Configuration;
|
||||
using Umbraco.Core.Logging;
|
||||
using Umbraco.Core.Persistence;
|
||||
using Umbraco.Web.Actions;
|
||||
|
||||
namespace Umbraco.Tests.Web.Controllers
|
||||
@@ -207,17 +212,28 @@ namespace Umbraco.Tests.Web.Controllers
|
||||
[Test]
|
||||
public async Task PostSave_Validate_Existing_Content()
|
||||
{
|
||||
ApiController Factory(HttpRequestMessage message, UmbracoHelper helper)
|
||||
ApiController CtrlFactory(HttpRequestMessage message, UmbracoContext umbracoContext, UmbracoHelper helper)
|
||||
{
|
||||
var contentServiceMock = Mock.Get(Current.Services.ContentService);
|
||||
contentServiceMock.Setup(x => x.GetById(123)).Returns(() => null); //do not find it
|
||||
|
||||
var propertyEditorCollection = new PropertyEditorCollection(new DataEditorCollection(Enumerable.Empty<DataEditor>()));
|
||||
var usersController = new ContentController(propertyEditorCollection);
|
||||
return usersController;
|
||||
|
||||
var controller = new ContentController(
|
||||
propertyEditorCollection,
|
||||
Factory.GetInstance<IGlobalSettings>(),
|
||||
umbracoContext,
|
||||
Factory.GetInstance<ISqlContext>(),
|
||||
Factory.GetInstance<ServiceContext>(),
|
||||
Factory.GetInstance<AppCaches>(),
|
||||
Factory.GetInstance<IProfilingLogger>(),
|
||||
Factory.GetInstance<IRuntimeState>(),
|
||||
helper);
|
||||
|
||||
return controller;
|
||||
}
|
||||
|
||||
var runner = new TestRunner(Factory);
|
||||
var runner = new TestRunner(CtrlFactory);
|
||||
var response = await runner.Execute("Content", "PostSave", HttpMethod.Post,
|
||||
content: GetMultiPartRequestContent(PublishJsonInvariant),
|
||||
mediaTypeHeader: new MediaTypeWithQualityHeaderValue("multipart/form-data"),
|
||||
@@ -233,21 +249,31 @@ namespace Umbraco.Tests.Web.Controllers
|
||||
[Test]
|
||||
public async Task PostSave_Validate_At_Least_One_Variant_Flagged_For_Saving()
|
||||
{
|
||||
ApiController Factory(HttpRequestMessage message, UmbracoHelper helper)
|
||||
ApiController CtrlFactory(HttpRequestMessage message, UmbracoContext umbracoContext, UmbracoHelper helper)
|
||||
{
|
||||
var contentServiceMock = Mock.Get(Current.Services.ContentService);
|
||||
contentServiceMock.Setup(x => x.GetById(123)).Returns(() => GetMockedContent());
|
||||
|
||||
var propertyEditorCollection = new PropertyEditorCollection(new DataEditorCollection(Enumerable.Empty<DataEditor>()));
|
||||
var usersController = new ContentController(propertyEditorCollection);
|
||||
return usersController;
|
||||
var controller = new ContentController(
|
||||
propertyEditorCollection,
|
||||
Factory.GetInstance<IGlobalSettings>(),
|
||||
umbracoContext,
|
||||
Factory.GetInstance<ISqlContext>(),
|
||||
Factory.GetInstance<ServiceContext>(),
|
||||
Factory.GetInstance<AppCaches>(),
|
||||
Factory.GetInstance<IProfilingLogger>(),
|
||||
Factory.GetInstance<IRuntimeState>(),
|
||||
helper);
|
||||
|
||||
return controller;
|
||||
}
|
||||
|
||||
var json = JsonConvert.DeserializeObject<JObject>(PublishJsonInvariant);
|
||||
//remove all save flaggs
|
||||
((JArray)json["variants"])[0]["save"] = false;
|
||||
|
||||
var runner = new TestRunner(Factory);
|
||||
var runner = new TestRunner(CtrlFactory);
|
||||
var response = await runner.Execute("Content", "PostSave", HttpMethod.Post,
|
||||
content: GetMultiPartRequestContent(JsonConvert.SerializeObject(json)),
|
||||
mediaTypeHeader: new MediaTypeWithQualityHeaderValue("multipart/form-data"),
|
||||
@@ -264,14 +290,24 @@ namespace Umbraco.Tests.Web.Controllers
|
||||
[Test]
|
||||
public async Task PostSave_Validate_Properties_Exist()
|
||||
{
|
||||
ApiController Factory(HttpRequestMessage message, UmbracoHelper helper)
|
||||
ApiController CtrlFactory(HttpRequestMessage message, UmbracoContext umbracoContext, UmbracoHelper helper)
|
||||
{
|
||||
var contentServiceMock = Mock.Get(Current.Services.ContentService);
|
||||
contentServiceMock.Setup(x => x.GetById(123)).Returns(() => GetMockedContent());
|
||||
|
||||
var propertyEditorCollection = new PropertyEditorCollection(new DataEditorCollection(Enumerable.Empty<DataEditor>()));
|
||||
var usersController = new ContentController(propertyEditorCollection);
|
||||
return usersController;
|
||||
var controller = new ContentController(
|
||||
propertyEditorCollection,
|
||||
Factory.GetInstance<IGlobalSettings>(),
|
||||
umbracoContext,
|
||||
Factory.GetInstance<ISqlContext>(),
|
||||
Factory.GetInstance<ServiceContext>(),
|
||||
Factory.GetInstance<AppCaches>(),
|
||||
Factory.GetInstance<IProfilingLogger>(),
|
||||
Factory.GetInstance<IRuntimeState>(),
|
||||
helper);
|
||||
|
||||
return controller;
|
||||
}
|
||||
|
||||
var json = JsonConvert.DeserializeObject<JObject>(PublishJsonInvariant);
|
||||
@@ -284,7 +320,7 @@ namespace Umbraco.Tests.Web.Controllers
|
||||
value = "hello"
|
||||
}));
|
||||
|
||||
var runner = new TestRunner(Factory);
|
||||
var runner = new TestRunner(CtrlFactory);
|
||||
var response = await runner.Execute("Content", "PostSave", HttpMethod.Post,
|
||||
content: GetMultiPartRequestContent(JsonConvert.SerializeObject(json)),
|
||||
mediaTypeHeader: new MediaTypeWithQualityHeaderValue("multipart/form-data"),
|
||||
@@ -298,7 +334,7 @@ namespace Umbraco.Tests.Web.Controllers
|
||||
{
|
||||
var content = GetMockedContent();
|
||||
|
||||
ApiController Factory(HttpRequestMessage message, UmbracoHelper helper)
|
||||
ApiController CtrlFactory(HttpRequestMessage message, UmbracoContext umbracoContext, UmbracoHelper helper)
|
||||
{
|
||||
|
||||
var contentServiceMock = Mock.Get(Current.Services.ContentService);
|
||||
@@ -310,11 +346,21 @@ namespace Umbraco.Tests.Web.Controllers
|
||||
contentTypeServiceMock.Setup(x => x.Get(content.ContentTypeId)).Returns(() => MockedContentTypes.CreateSimpleContentType());
|
||||
|
||||
var propertyEditorCollection = new PropertyEditorCollection(new DataEditorCollection(Enumerable.Empty<DataEditor>()));
|
||||
var usersController = new ContentController(propertyEditorCollection);
|
||||
return usersController;
|
||||
var controller = new ContentController(
|
||||
propertyEditorCollection,
|
||||
Factory.GetInstance<IGlobalSettings>(),
|
||||
umbracoContext,
|
||||
Factory.GetInstance<ISqlContext>(),
|
||||
Factory.GetInstance<ServiceContext>(),
|
||||
Factory.GetInstance<AppCaches>(),
|
||||
Factory.GetInstance<IProfilingLogger>(),
|
||||
Factory.GetInstance<IRuntimeState>(),
|
||||
helper);
|
||||
|
||||
return controller;
|
||||
}
|
||||
|
||||
var runner = new TestRunner(Factory);
|
||||
var runner = new TestRunner(CtrlFactory);
|
||||
var response = await runner.Execute("Content", "PostSave", HttpMethod.Post,
|
||||
content: GetMultiPartRequestContent(PublishJsonInvariant),
|
||||
mediaTypeHeader: new MediaTypeWithQualityHeaderValue("multipart/form-data"),
|
||||
@@ -332,7 +378,7 @@ namespace Umbraco.Tests.Web.Controllers
|
||||
{
|
||||
var content = GetMockedContent();
|
||||
|
||||
ApiController Factory(HttpRequestMessage message, UmbracoHelper helper)
|
||||
ApiController CtrlFactory(HttpRequestMessage message, UmbracoContext umbracoContext, UmbracoHelper helper)
|
||||
{
|
||||
|
||||
var contentServiceMock = Mock.Get(Current.Services.ContentService);
|
||||
@@ -344,15 +390,25 @@ namespace Umbraco.Tests.Web.Controllers
|
||||
contentTypeServiceMock.Setup(x => x.Get(content.ContentTypeId)).Returns(() => MockedContentTypes.CreateSimpleContentType());
|
||||
|
||||
var propertyEditorCollection = new PropertyEditorCollection(new DataEditorCollection(Enumerable.Empty<DataEditor>()));
|
||||
var usersController = new ContentController(propertyEditorCollection);
|
||||
return usersController;
|
||||
var controller = new ContentController(
|
||||
propertyEditorCollection,
|
||||
Factory.GetInstance<IGlobalSettings>(),
|
||||
umbracoContext,
|
||||
Factory.GetInstance<ISqlContext>(),
|
||||
Factory.GetInstance<ServiceContext>(),
|
||||
Factory.GetInstance<AppCaches>(),
|
||||
Factory.GetInstance<IProfilingLogger>(),
|
||||
Factory.GetInstance<IRuntimeState>(),
|
||||
helper);
|
||||
|
||||
return controller;
|
||||
}
|
||||
|
||||
//clear out the name
|
||||
var json = JsonConvert.DeserializeObject<JObject>(PublishJsonInvariant);
|
||||
json["variants"].ElementAt(0)["name"] = null;
|
||||
|
||||
var runner = new TestRunner(Factory);
|
||||
var runner = new TestRunner(CtrlFactory);
|
||||
var response = await runner.Execute("Content", "PostSave", HttpMethod.Post,
|
||||
content: GetMultiPartRequestContent(JsonConvert.SerializeObject(json)),
|
||||
mediaTypeHeader: new MediaTypeWithQualityHeaderValue("multipart/form-data"),
|
||||
@@ -370,7 +426,7 @@ namespace Umbraco.Tests.Web.Controllers
|
||||
{
|
||||
var content = GetMockedContent();
|
||||
|
||||
ApiController Factory(HttpRequestMessage message, UmbracoHelper helper)
|
||||
ApiController CtrlFactory(HttpRequestMessage message, UmbracoContext umbracoContext, UmbracoHelper helper)
|
||||
{
|
||||
|
||||
var contentServiceMock = Mock.Get(Current.Services.ContentService);
|
||||
@@ -382,15 +438,25 @@ namespace Umbraco.Tests.Web.Controllers
|
||||
contentTypeServiceMock.Setup(x => x.Get(content.ContentTypeId)).Returns(() => MockedContentTypes.CreateSimpleContentType());
|
||||
|
||||
var propertyEditorCollection = new PropertyEditorCollection(new DataEditorCollection(Enumerable.Empty<DataEditor>()));
|
||||
var usersController = new ContentController(propertyEditorCollection);
|
||||
return usersController;
|
||||
var controller = new ContentController(
|
||||
propertyEditorCollection,
|
||||
Factory.GetInstance<IGlobalSettings>(),
|
||||
umbracoContext,
|
||||
Factory.GetInstance<ISqlContext>(),
|
||||
Factory.GetInstance<ServiceContext>(),
|
||||
Factory.GetInstance<AppCaches>(),
|
||||
Factory.GetInstance<IProfilingLogger>(),
|
||||
Factory.GetInstance<IRuntimeState>(),
|
||||
helper);
|
||||
|
||||
return controller;
|
||||
}
|
||||
|
||||
//clear out one of the names
|
||||
var json = JsonConvert.DeserializeObject<JObject>(PublishJsonVariant);
|
||||
json["variants"].ElementAt(0)["name"] = null;
|
||||
|
||||
var runner = new TestRunner(Factory);
|
||||
var runner = new TestRunner(CtrlFactory);
|
||||
var response = await runner.Execute("Content", "PostSave", HttpMethod.Post,
|
||||
content: GetMultiPartRequestContent(JsonConvert.SerializeObject(json)),
|
||||
mediaTypeHeader: new MediaTypeWithQualityHeaderValue("multipart/form-data"),
|
||||
|
||||
@@ -54,7 +54,7 @@ namespace Umbraco.Tests.Web.Controllers
|
||||
public class Plugin1Controller : PluginController
|
||||
{
|
||||
public Plugin1Controller(UmbracoContext umbracoContext)
|
||||
: base(umbracoContext, null, null, null, null, null)
|
||||
: base(umbracoContext, null, null, null, null, null, null)
|
||||
{
|
||||
}
|
||||
}
|
||||
@@ -63,7 +63,7 @@ namespace Umbraco.Tests.Web.Controllers
|
||||
public class Plugin2Controller : PluginController
|
||||
{
|
||||
public Plugin2Controller(UmbracoContext umbracoContext)
|
||||
: base(umbracoContext, null, null, null, null, null)
|
||||
: base(umbracoContext, null, null, null, null, null, null)
|
||||
{
|
||||
}
|
||||
}
|
||||
@@ -72,7 +72,7 @@ namespace Umbraco.Tests.Web.Controllers
|
||||
public class Plugin3Controller : PluginController
|
||||
{
|
||||
public Plugin3Controller(UmbracoContext umbracoContext)
|
||||
: base(umbracoContext, null, null, null, null, null)
|
||||
: base(umbracoContext, null, null, null, null, null, null)
|
||||
{
|
||||
}
|
||||
}
|
||||
@@ -80,7 +80,7 @@ namespace Umbraco.Tests.Web.Controllers
|
||||
public class Plugin4Controller : PluginController
|
||||
{
|
||||
public Plugin4Controller(UmbracoContext umbracoContext)
|
||||
: base(umbracoContext, null, null, null, null, null)
|
||||
: base(umbracoContext, null, null, null, null, null, null)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,9 +7,13 @@ using Moq;
|
||||
using Newtonsoft.Json;
|
||||
using NUnit.Framework;
|
||||
using Umbraco.Core;
|
||||
using Umbraco.Core.Cache;
|
||||
using Umbraco.Core.Composing;
|
||||
using Umbraco.Core.Configuration;
|
||||
using Umbraco.Core.Logging;
|
||||
using Umbraco.Core.Models;
|
||||
using Umbraco.Core.Models.Membership;
|
||||
using Umbraco.Core.Persistence;
|
||||
using Umbraco.Core.Persistence.DatabaseModelDefinitions;
|
||||
using Umbraco.Core.Persistence.Mappers;
|
||||
using Umbraco.Core.Persistence.Querying;
|
||||
@@ -49,7 +53,7 @@ namespace Umbraco.Tests.Web.Controllers
|
||||
[Test]
|
||||
public async System.Threading.Tasks.Task Save_User()
|
||||
{
|
||||
ApiController Factory(HttpRequestMessage message, UmbracoHelper helper)
|
||||
ApiController CtrlFactory(HttpRequestMessage message, UmbracoContext umbracoContext, UmbracoHelper helper)
|
||||
{
|
||||
//setup some mocks
|
||||
Umbraco.Core.Configuration.GlobalSettings.HasSmtpServer = true;
|
||||
@@ -68,7 +72,15 @@ namespace Umbraco.Tests.Web.Controllers
|
||||
userServiceMock.Setup(service => service.GetUserById(It.IsAny<int>()))
|
||||
.Returns((int id) => id == 1234 ? new User(1234, "Test", "test@test.com", "test@test.com", "", new List<IReadOnlyUserGroup>(), new int[0], new int[0]) : null);
|
||||
|
||||
var usersController = new UsersController();
|
||||
var usersController = new UsersController(
|
||||
Factory.GetInstance<IGlobalSettings>(),
|
||||
umbracoContext,
|
||||
Factory.GetInstance<ISqlContext>(),
|
||||
Factory.GetInstance<ServiceContext>(),
|
||||
Factory.GetInstance<AppCaches>(),
|
||||
Factory.GetInstance<IProfilingLogger>(),
|
||||
Factory.GetInstance<IRuntimeState>(),
|
||||
helper);
|
||||
return usersController;
|
||||
}
|
||||
|
||||
@@ -82,7 +94,7 @@ namespace Umbraco.Tests.Web.Controllers
|
||||
UserGroups = new[] { "writers" }
|
||||
};
|
||||
|
||||
var runner = new TestRunner(Factory);
|
||||
var runner = new TestRunner(CtrlFactory);
|
||||
var response = await runner.Execute("Users", "PostSaveUser", HttpMethod.Post,
|
||||
new ObjectContent<UserSave>(userSave, new JsonMediaTypeFormatter()));
|
||||
var obj = JsonConvert.DeserializeObject<UserDisplay>(response.Item2);
|
||||
@@ -122,15 +134,23 @@ namespace Umbraco.Tests.Web.Controllers
|
||||
[Test]
|
||||
public async System.Threading.Tasks.Task GetPagedUsers_Empty()
|
||||
{
|
||||
ApiController Factory(HttpRequestMessage message, UmbracoHelper helper)
|
||||
ApiController CtrlFactory(HttpRequestMessage message, UmbracoContext umbracoContext, UmbracoHelper helper)
|
||||
{
|
||||
var usersController = new UsersController();
|
||||
var usersController = new UsersController(
|
||||
Factory.GetInstance<IGlobalSettings>(),
|
||||
umbracoContext,
|
||||
Factory.GetInstance<ISqlContext>(),
|
||||
Factory.GetInstance<ServiceContext>(),
|
||||
Factory.GetInstance<AppCaches>(),
|
||||
Factory.GetInstance<IProfilingLogger>(),
|
||||
Factory.GetInstance<IRuntimeState>(),
|
||||
helper);
|
||||
return usersController;
|
||||
}
|
||||
|
||||
MockForGetPagedUsers();
|
||||
|
||||
var runner = new TestRunner(Factory);
|
||||
var runner = new TestRunner(CtrlFactory);
|
||||
var response = await runner.Execute("Users", "GetPagedUsers", HttpMethod.Get);
|
||||
|
||||
var obj = JsonConvert.DeserializeObject<PagedResult<UserDisplay>>(response.Item2);
|
||||
@@ -140,7 +160,7 @@ namespace Umbraco.Tests.Web.Controllers
|
||||
[Test]
|
||||
public async System.Threading.Tasks.Task GetPagedUsers_10()
|
||||
{
|
||||
ApiController Factory(HttpRequestMessage message, UmbracoHelper helper)
|
||||
ApiController CtrlFactory(HttpRequestMessage message, UmbracoContext umbracoContext, UmbracoHelper helper)
|
||||
{
|
||||
//setup some mocks
|
||||
var userServiceMock = Mock.Get(Current.Services.UserService);
|
||||
@@ -151,13 +171,21 @@ namespace Umbraco.Tests.Web.Controllers
|
||||
It.IsAny<UserState[]>(), It.IsAny<string[]>(), It.IsAny<string[]>(), It.IsAny<IQuery<IUser>>()))
|
||||
.Returns(() => users);
|
||||
|
||||
var usersController = new UsersController();
|
||||
var usersController = new UsersController(
|
||||
Factory.GetInstance<IGlobalSettings>(),
|
||||
umbracoContext,
|
||||
Factory.GetInstance<ISqlContext>(),
|
||||
Factory.GetInstance<ServiceContext>(),
|
||||
Factory.GetInstance<AppCaches>(),
|
||||
Factory.GetInstance<IProfilingLogger>(),
|
||||
Factory.GetInstance<IRuntimeState>(),
|
||||
helper);
|
||||
return usersController;
|
||||
}
|
||||
|
||||
MockForGetPagedUsers();
|
||||
|
||||
var runner = new TestRunner(Factory);
|
||||
var runner = new TestRunner(CtrlFactory);
|
||||
var response = await runner.Execute("Users", "GetPagedUsers", HttpMethod.Get);
|
||||
|
||||
var obj = JsonConvert.DeserializeObject<PagedResult<UserDisplay>>(response.Item2);
|
||||
|
||||
@@ -77,42 +77,15 @@ namespace Umbraco.Tests.Web.Mvc
|
||||
|
||||
Assert.IsNotNull(ctrl.UmbracoContext);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Umbraco_Helper_Not_Null()
|
||||
{
|
||||
var globalSettings = TestObjects.GetGlobalSettings();
|
||||
var umbracoContext = UmbracoContext.EnsureContext(
|
||||
Current.UmbracoContextAccessor,
|
||||
new Mock<HttpContextBase>().Object,
|
||||
Mock.Of<IPublishedSnapshotService>(),
|
||||
new Mock<WebSecurity>(null, null, globalSettings).Object,
|
||||
TestObjects.GetUmbracoSettings(),
|
||||
Enumerable.Empty<IUrlProvider>(),
|
||||
globalSettings,
|
||||
new TestVariationContextAccessor(),
|
||||
true);
|
||||
|
||||
var controller = new TestSurfaceController(umbracoContext);
|
||||
Composition.Register(_ => umbracoContext);
|
||||
|
||||
Assert.IsNotNull(controller.Umbraco);
|
||||
}
|
||||
|
||||
|
||||
[Test]
|
||||
public void Can_Lookup_Content()
|
||||
{
|
||||
var publishedSnapshot = new Mock<IPublishedSnapshot>();
|
||||
publishedSnapshot.Setup(x => x.Members).Returns(Mock.Of<IPublishedMemberCache>());
|
||||
var contentCache = new Mock<IPublishedContentCache>();
|
||||
var content = new Mock<IPublishedContent>();
|
||||
content.Setup(x => x.Id).Returns(2);
|
||||
contentCache.Setup(x => x.GetById(It.IsAny<int>())).Returns(content.Object);
|
||||
var mediaCache = new Mock<IPublishedMediaCache>();
|
||||
publishedSnapshot.Setup(x => x.Content).Returns(contentCache.Object);
|
||||
publishedSnapshot.Setup(x => x.Media).Returns(mediaCache.Object);
|
||||
var publishedSnapshotService = new Mock<IPublishedSnapshotService>();
|
||||
publishedSnapshotService.Setup(x => x.CreatePublishedSnapshot(It.IsAny<string>())).Returns(publishedSnapshot.Object);
|
||||
var globalSettings = TestObjects.GetGlobalSettings();
|
||||
|
||||
var umbracoContext = UmbracoContext.EnsureContext(
|
||||
@@ -128,17 +101,17 @@ namespace Umbraco.Tests.Web.Mvc
|
||||
|
||||
var helper = new UmbracoHelper(
|
||||
umbracoContext,
|
||||
Mock.Of<IPublishedContent>(),
|
||||
Mock.Of<ITagQuery>(),
|
||||
Mock.Of<ICultureDictionary>(),
|
||||
Mock.Of<ICultureDictionaryFactory>(),
|
||||
Mock.Of<IUmbracoComponentRenderer>(),
|
||||
new MembershipHelper(new TestUmbracoContextAccessor(umbracoContext), Mock.Of<MembershipProvider>(), Mock.Of<RoleProvider>(), Mock.Of<IMemberService>(), Mock.Of<IMemberTypeService>(), Mock.Of<IUserService>(), Mock.Of<IPublicAccessService>(), Mock.Of<AppCaches>(), Mock.Of<ILogger>()),
|
||||
ServiceContext.CreatePartial());
|
||||
Mock.Of<IPublishedContentQuery>(query => query.Content(2) == content.Object),
|
||||
new MembershipHelper(new TestUmbracoContextAccessor(umbracoContext), Mock.Of<MembershipProvider>(), Mock.Of<RoleProvider>(), Mock.Of<IMemberService>(), Mock.Of<IMemberTypeService>(), Mock.Of<IUserService>(), Mock.Of<IPublicAccessService>(), Mock.Of<AppCaches>(), Mock.Of<ILogger>()));
|
||||
|
||||
var ctrl = new TestSurfaceController(umbracoContext, helper);
|
||||
var result = ctrl.GetContent(2) as PublishedContentResult;
|
||||
|
||||
Assert.IsNotNull(result);
|
||||
Assert.IsNotNull(result.Content);
|
||||
Assert.AreEqual(2, result.Content.Id);
|
||||
}
|
||||
|
||||
@@ -185,12 +158,8 @@ namespace Umbraco.Tests.Web.Mvc
|
||||
public class TestSurfaceController : SurfaceController
|
||||
{
|
||||
public TestSurfaceController(UmbracoContext ctx, UmbracoHelper helper = null)
|
||||
: base(ctx, null, ServiceContext.CreatePartial(), Mock.Of<AppCaches>(), null, null)
|
||||
: base(ctx, null, ServiceContext.CreatePartial(), Mock.Of<AppCaches>(), null, null, helper)
|
||||
{
|
||||
if (helper != null)
|
||||
{
|
||||
Umbraco = helper;
|
||||
}
|
||||
}
|
||||
|
||||
public ActionResult Index()
|
||||
|
||||
6
src/Umbraco.Web.UI.Client/package-lock.json
generated
6
src/Umbraco.Web.UI.Client/package-lock.json
generated
@@ -15598,9 +15598,9 @@
|
||||
}
|
||||
},
|
||||
"tinymce": {
|
||||
"version": "4.9.0",
|
||||
"resolved": "https://registry.npmjs.org/tinymce/-/tinymce-4.9.0.tgz",
|
||||
"integrity": "sha512-hrPeCLXY/sVCo3i64CTW8P5xbDiEI8Uii/vWpcmQWAMhex6GWWd2U+L8WIMj5tKKGdfcIQAJfpfQthc/92bcKw=="
|
||||
"version": "4.9.2",
|
||||
"resolved": "https://registry.npmjs.org/tinymce/-/tinymce-4.9.2.tgz",
|
||||
"integrity": "sha512-ZRoTGG4GAsOI73QPSNkabO7nkoYw9H6cglRB44W2mMkxSiqxYi8WJlgkUphk0fDqo6ZD6r3E+NSP4UHxF2lySg=="
|
||||
},
|
||||
"tmp": {
|
||||
"version": "0.0.33",
|
||||
|
||||
@@ -39,7 +39,7 @@
|
||||
"npm": "^6.4.1",
|
||||
"signalr": "2.4.0",
|
||||
"spectrum-colorpicker": "1.8.0",
|
||||
"tinymce": "4.9.0",
|
||||
"tinymce": "4.9.2",
|
||||
"typeahead.js": "0.11.1",
|
||||
"underscore": "1.9.1"
|
||||
},
|
||||
|
||||
@@ -30,7 +30,8 @@ angular.module("umbraco.directives")
|
||||
promises.push(tinyMceService.getTinyMceEditorConfig({
|
||||
htmlId: scope.uniqueId,
|
||||
stylesheets: scope.configuration ? scope.configuration.stylesheets : null,
|
||||
toolbar: toolbar
|
||||
toolbar: toolbar,
|
||||
mode: scope.configuration.mode
|
||||
}));
|
||||
|
||||
// pin toolbar to top of screen if we have focus and it scrolls off the screen
|
||||
|
||||
@@ -232,7 +232,11 @@ function tinyMceService($rootScope, $q, imageHelper, $locale, $http, $timeout, s
|
||||
|
||||
body_class: 'umb-rte',
|
||||
//see http://archive.tinymce.com/wiki.php/Configuration:cache_suffix
|
||||
cache_suffix: "?umb__rnd=" + Umbraco.Sys.ServerVariables.application.cacheBuster
|
||||
cache_suffix: "?umb__rnd=" + Umbraco.Sys.ServerVariables.application.cacheBuster,
|
||||
|
||||
//this is used to style the inline macro bits, sorry hard coding this form now since we don't have a standalone
|
||||
//stylesheet to load in for this with only these styles (the color is @pinkLight)
|
||||
content_style: ".mce-content-body .umb-macro-holder { border: 3px dotted #f5c1bc; padding: 7px; display: block; margin: 3px; } .umb-rte .mce-content-body .umb-macro-holder.loading {background: url(assets/img/loader.gif) right no-repeat; background-size: 18px; background-position-x: 99%;}"
|
||||
};
|
||||
|
||||
if (tinyMceConfig.customConfig) {
|
||||
@@ -458,7 +462,8 @@ function tinyMceService($rootScope, $q, imageHelper, $locale, $http, $timeout, s
|
||||
*/
|
||||
createInsertMacro: function (editor, callback) {
|
||||
|
||||
var createInsertMacroScope = this;
|
||||
let self = this;
|
||||
let activeMacroElement = null; //track an active macro element
|
||||
|
||||
/** Adds custom rules for the macro plugin and custom serialization */
|
||||
editor.on('preInit', function (args) {
|
||||
@@ -474,6 +479,16 @@ function tinyMceService($rootScope, $q, imageHelper, $locale, $http, $timeout, s
|
||||
}
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
/** when the contents load we need to find any macros declared and load in their content */
|
||||
editor.on("SetContent", function (o) {
|
||||
|
||||
//get all macro divs and load their content
|
||||
$(editor.dom.select(".umb-macro-holder.mceNonEditable")).each(function () {
|
||||
self.loadMacroContent($(this), null);
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
/**
|
||||
@@ -501,203 +516,26 @@ function tinyMceService($rootScope, $q, imageHelper, $locale, $http, $timeout, s
|
||||
tooltip: 'Insert macro',
|
||||
onPostRender: function () {
|
||||
|
||||
var ctrl = this;
|
||||
var isOnMacroElement = false;
|
||||
|
||||
let ctrl = this;
|
||||
|
||||
/**
|
||||
if the selection comes from a different element that is not the macro's
|
||||
we need to check if the selection includes part of the macro, if so we'll force the selection
|
||||
to clear to the next element since if people can select part of the macro markup they can then modify it.
|
||||
*/
|
||||
function handleSelectionChange() {
|
||||
|
||||
if (!editor.selection.isCollapsed()) {
|
||||
var endSelection = tinymce.activeEditor.selection.getEnd();
|
||||
var startSelection = tinymce.activeEditor.selection.getStart();
|
||||
//don't proceed if it's an entire element selected
|
||||
if (endSelection !== startSelection) {
|
||||
|
||||
//if the end selection is a macro then move the cursor
|
||||
//NOTE: we don't have to handle when the selection comes from a previous parent because
|
||||
// that is automatically taken care of with the normal onNodeChanged logic since the
|
||||
// evt.element will be the macro once it becomes part of the selection.
|
||||
var $testForMacro = $(endSelection).closest(".umb-macro-holder");
|
||||
if ($testForMacro.length > 0) {
|
||||
|
||||
//it came from before so move after, if there is no after then select ourselves
|
||||
var next = $testForMacro.next();
|
||||
if (next.length > 0) {
|
||||
editor.selection.setCursorLocation($testForMacro.next().get(0));
|
||||
} else {
|
||||
selectMacroElement($testForMacro.get(0));
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** helper method to select the macro element */
|
||||
function selectMacroElement(macroElement) {
|
||||
|
||||
// move selection to top element to ensure we can't edit this
|
||||
editor.selection.select(macroElement);
|
||||
|
||||
// check if the current selection *is* the element (ie bug)
|
||||
var currentSelection = editor.selection.getStart();
|
||||
if (tinymce.isIE) {
|
||||
if (!editor.dom.hasClass(currentSelection, 'umb-macro-holder')) {
|
||||
while (!editor.dom.hasClass(currentSelection, 'umb-macro-holder') && currentSelection.parentNode) {
|
||||
currentSelection = currentSelection.parentNode;
|
||||
}
|
||||
editor.selection.select(currentSelection);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a node change handler, test if we're editing a macro and select the whole thing, then set our isOnMacroElement flag.
|
||||
* If we change the selection inside this method, then we end up in an infinite loop, so we have to remove ourselves
|
||||
* from the event listener before changing selection, however, it seems that putting a break point in this method
|
||||
* will always cause an 'infinite' loop as the caret keeps changing.
|
||||
*
|
||||
* TODO: I don't think we need this anymore with recent tinymce fixes: https://www.tiny.cloud/docs/plugins/noneditable/
|
||||
* Check if the macro is currently selected and toggle the menu button
|
||||
*/
|
||||
function onNodeChanged(evt) {
|
||||
|
||||
//set our macro button active when on a node of class umb-macro-holder
|
||||
var $macroElement = $(evt.element).closest(".umb-macro-holder");
|
||||
|
||||
handleSelectionChange();
|
||||
|
||||
//set the button active
|
||||
ctrl.active($macroElement.length !== 0);
|
||||
|
||||
if ($macroElement.length > 0) {
|
||||
var macroElement = $macroElement.get(0);
|
||||
|
||||
//remove the event listener before re-selecting
|
||||
editor.off('NodeChange', onNodeChanged);
|
||||
|
||||
selectMacroElement(macroElement);
|
||||
|
||||
//set the flag
|
||||
isOnMacroElement = true;
|
||||
|
||||
//re-add the event listener
|
||||
editor.on('NodeChange', onNodeChanged);
|
||||
} else {
|
||||
isOnMacroElement = false;
|
||||
}
|
||||
activeMacroElement = getRealMacroElem(evt.element);
|
||||
|
||||
//set the button active/inactive
|
||||
ctrl.active(activeMacroElement !== null);
|
||||
}
|
||||
|
||||
/** when the contents load we need to find any macros declared and load in their content */
|
||||
editor.on("LoadContent", function (o) {
|
||||
|
||||
//get all macro divs and load their content
|
||||
$(editor.dom.select(".umb-macro-holder.mceNonEditable")).each(function () {
|
||||
createInsertMacroScope.loadMacroContent($(this), null);
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
/**
|
||||
* This prevents any other commands from executing when the current element is the macro so the content cannot be edited
|
||||
*
|
||||
* TODO: I don't think we need this anymore with recent tinymce fixes: https://www.tiny.cloud/docs/plugins/noneditable/
|
||||
*/
|
||||
editor.on('BeforeExecCommand', function (o) {
|
||||
if (isOnMacroElement) {
|
||||
if (o.preventDefault) {
|
||||
o.preventDefault();
|
||||
}
|
||||
if (o.stopImmediatePropagation) {
|
||||
o.stopImmediatePropagation();
|
||||
}
|
||||
return;
|
||||
}
|
||||
});
|
||||
|
||||
/**
|
||||
* This double checks and ensures you can't paste content into the rendered macro
|
||||
*
|
||||
* TODO: I don't think we need this anymore with recent tinymce fixes: https://www.tiny.cloud/docs/plugins/noneditable/
|
||||
*/
|
||||
editor.on("Paste", function (o) {
|
||||
if (isOnMacroElement) {
|
||||
if (o.preventDefault) {
|
||||
o.preventDefault();
|
||||
}
|
||||
if (o.stopImmediatePropagation) {
|
||||
o.stopImmediatePropagation();
|
||||
}
|
||||
return;
|
||||
}
|
||||
});
|
||||
//NOTE: This could be another way to deal with the active/inactive state
|
||||
//editor.on('ObjectSelected', function (e) {});
|
||||
|
||||
//set onNodeChanged event listener
|
||||
editor.on('NodeChange', onNodeChanged);
|
||||
|
||||
/**
|
||||
* Listen for the keydown in the editor, we'll check if we are currently on a macro element, if so
|
||||
* we'll check if the key down is a supported key which requires an action, otherwise we ignore the request
|
||||
* so the macro cannot be edited.
|
||||
*
|
||||
* TODO: I don't think we need this anymore with recent tinymce fixes: https://www.tiny.cloud/docs/plugins/noneditable/
|
||||
*/
|
||||
editor.on('KeyDown', function (e) {
|
||||
if (isOnMacroElement) {
|
||||
var macroElement = editor.selection.getNode();
|
||||
|
||||
//get the 'real' element (either p or the real one)
|
||||
macroElement = getRealMacroElem(macroElement);
|
||||
|
||||
//prevent editing
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
|
||||
var moveSibling = function (element, isNext) {
|
||||
var $e = $(element);
|
||||
var $sibling = isNext ? $e.next() : $e.prev();
|
||||
if ($sibling.length > 0) {
|
||||
editor.selection.select($sibling.get(0));
|
||||
editor.selection.collapse(true);
|
||||
} else {
|
||||
//if we're moving previous and there is no sibling, then lets recurse and just select the next one
|
||||
if (!isNext) {
|
||||
moveSibling(element, true);
|
||||
return;
|
||||
}
|
||||
|
||||
//if there is no sibling we'll generate a new p at the end and select it
|
||||
editor.setContent(editor.getContent() + "<p> </p>");
|
||||
editor.selection.select($(editor.dom.getRoot()).children().last().get(0));
|
||||
editor.selection.collapse(true);
|
||||
|
||||
}
|
||||
};
|
||||
|
||||
//supported keys to move to the next or prev element (13-enter, 27-esc, 38-up, 40-down, 39-right, 37-left)
|
||||
//supported keys to remove the macro (8-backspace, 46-delete)
|
||||
// TODO: Should we make the enter key insert a line break before or leave it as moving to the next element?
|
||||
if ($.inArray(e.keyCode, [13, 40, 39]) !== -1) {
|
||||
//move to next element
|
||||
moveSibling(macroElement, true);
|
||||
} else if ($.inArray(e.keyCode, [27, 38, 37]) !== -1) {
|
||||
//move to prev element
|
||||
moveSibling(macroElement, false);
|
||||
} else if ($.inArray(e.keyCode, [8, 46]) !== -1) {
|
||||
//delete macro element
|
||||
|
||||
//move first, then delete
|
||||
moveSibling(macroElement, false);
|
||||
editor.dom.remove(macroElement);
|
||||
}
|
||||
return;
|
||||
}
|
||||
});
|
||||
|
||||
},
|
||||
|
||||
/** The insert macro button click event handler */
|
||||
@@ -710,11 +548,9 @@ function tinyMceService($rootScope, $q, imageHelper, $locale, $http, $timeout, s
|
||||
|
||||
//when we click we could have a macro already selected and in that case we'll want to edit the current parameters
|
||||
//so we'll need to extract them and submit them to the dialog.
|
||||
var macroElement = editor.selection.getNode();
|
||||
macroElement = getRealMacroElem(macroElement);
|
||||
if (macroElement) {
|
||||
if (activeMacroElement) {
|
||||
//we have a macro selected so we'll need to parse it's alias and parameters
|
||||
var contents = $(macroElement).contents();
|
||||
var contents = $(activeMacroElement).contents();
|
||||
var comment = _.find(contents, function (item) {
|
||||
return item.nodeType === 8;
|
||||
});
|
||||
@@ -724,7 +560,8 @@ function tinyMceService($rootScope, $q, imageHelper, $locale, $http, $timeout, s
|
||||
var syntax = comment.textContent.trim();
|
||||
var parsed = macroService.parseMacroSyntax(syntax);
|
||||
dialogData = {
|
||||
macroData: parsed
|
||||
macroData: parsed,
|
||||
activeMacroElement: activeMacroElement //pass the active element along so we can retrieve it later
|
||||
};
|
||||
}
|
||||
|
||||
@@ -737,7 +574,11 @@ function tinyMceService($rootScope, $q, imageHelper, $locale, $http, $timeout, s
|
||||
});
|
||||
},
|
||||
|
||||
insertMacroInEditor: function (editor, macroObject) {
|
||||
insertMacroInEditor: function (editor, macroObject, activeMacroElement) {
|
||||
|
||||
//Important note: the TinyMce plugin "noneditable" is used here so that the macro cannot be edited,
|
||||
// for this to work the mceNonEditable class needs to come last and we also need to use the attribute contenteditable = false
|
||||
// (even though all the docs and examples say that is not necessary)
|
||||
|
||||
//put the macro syntax in comments, we will parse this out on the server side to be used
|
||||
//for persisting.
|
||||
@@ -746,11 +587,18 @@ function tinyMceService($rootScope, $q, imageHelper, $locale, $http, $timeout, s
|
||||
var uniqueId = "umb-macro-" + editor.dom.uniqueId();
|
||||
var macroDiv = editor.dom.create('div',
|
||||
{
|
||||
'class': 'umb-macro-holder ' + macroObject.macroAlias + ' mceNonEditable ' + uniqueId
|
||||
'class': 'umb-macro-holder ' + macroObject.macroAlias + " " + uniqueId + ' mceNonEditable',
|
||||
'contenteditable': 'false'
|
||||
},
|
||||
macroSyntaxComment + '<ins>Macro alias: <strong>' + macroObject.macroAlias + '</strong></ins>');
|
||||
|
||||
editor.selection.setNode(macroDiv);
|
||||
//if there's an activeMacroElement then replace it, otherwise set the contents of the selected node
|
||||
if (activeMacroElement) {
|
||||
activeMacroElement.replaceWith(macroDiv); //directly replaces the html node
|
||||
}
|
||||
else {
|
||||
editor.selection.setNode(macroDiv);
|
||||
}
|
||||
|
||||
var $macroDiv = $(editor.dom.select("div.umb-macro-holder." + uniqueId));
|
||||
|
||||
@@ -1167,10 +1015,15 @@ function tinyMceService($rootScope, $q, imageHelper, $locale, $http, $timeout, s
|
||||
|
||||
pinToolbar : function (editor) {
|
||||
|
||||
//we can't pin the toolbar if this doesn't exist (i.e. when in distraction free mode)
|
||||
if (!editor.editorContainer) {
|
||||
return;
|
||||
}
|
||||
|
||||
var tinyMce = $(editor.editorContainer);
|
||||
var toolbar = tinyMce.find(".mce-toolbar");
|
||||
var toolbarHeight = toolbar.height();
|
||||
var tinyMceRect = tinyMce[0].getBoundingClientRect();
|
||||
var tinyMceRect = editor.editorContainer.getBoundingClientRect();
|
||||
var tinyMceTop = tinyMceRect.top;
|
||||
var tinyMceBottom = tinyMceRect.bottom;
|
||||
var tinyMceWidth = tinyMceRect.width;
|
||||
@@ -1288,7 +1141,7 @@ function tinyMceService($rootScope, $q, imageHelper, $locale, $http, $timeout, s
|
||||
}
|
||||
});
|
||||
|
||||
var self = this;
|
||||
let self = this;
|
||||
|
||||
//create link picker
|
||||
self.createLinkPicker(args.editor, function (currentTarget, anchorElement) {
|
||||
@@ -1346,7 +1199,7 @@ function tinyMceService($rootScope, $q, imageHelper, $locale, $http, $timeout, s
|
||||
dialogData: dialogData,
|
||||
submit: function (model) {
|
||||
var macroObject = macroService.collectValueData(model.selectedMacro, model.macroParams, dialogData.renderingEngine);
|
||||
self.insertMacroInEditor(args.editor, macroObject);
|
||||
self.insertMacroInEditor(args.editor, macroObject, dialogData.activeMacroElement);
|
||||
editorService.close();
|
||||
},
|
||||
close: function () {
|
||||
|
||||
@@ -25,13 +25,6 @@
|
||||
padding:10px;
|
||||
}
|
||||
|
||||
/* loader for macro loading in tinymce*/
|
||||
.umb-rte .mce-content-body .umb-macro-holder.loading {
|
||||
background: url(img/loader.gif) right no-repeat;
|
||||
background-size: 18px;
|
||||
background-position-x: 99%;
|
||||
}
|
||||
|
||||
.umb-rte .mce-container {
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
@@ -94,6 +94,9 @@ namespace Umbraco.Web.Composing
|
||||
public static UmbracoContext UmbracoContext
|
||||
=> UmbracoContextAccessor.UmbracoContext;
|
||||
|
||||
public static UmbracoHelper UmbracoHelper
|
||||
=> Factory.GetInstance<UmbracoHelper>();
|
||||
|
||||
public static DistributedCache DistributedCache
|
||||
=> Factory.GetInstance<DistributedCache>();
|
||||
|
||||
|
||||
@@ -20,18 +20,13 @@ namespace Umbraco.Web.Controllers
|
||||
// TODO: This controller should be moved to a more suitable place.
|
||||
public class TagsController : UmbracoApiController
|
||||
{
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="TagsController"/> with auto dependencies.
|
||||
/// </summary>
|
||||
public TagsController()
|
||||
{ }
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="TagsController"/> with all its dependencies.
|
||||
/// </summary>
|
||||
public TagsController(IGlobalSettings globalSettings, UmbracoContext umbracoContext, ISqlContext sqlContext, ServiceContext services, AppCaches appCaches, IProfilingLogger logger, IRuntimeState runtimeState)
|
||||
: base(globalSettings, umbracoContext, sqlContext, services, appCaches, logger, runtimeState)
|
||||
{ }
|
||||
public TagsController(IGlobalSettings globalSettings, UmbracoContext umbracoContext, ISqlContext sqlContext, ServiceContext services, AppCaches appCaches, IProfilingLogger logger, IRuntimeState runtimeState, UmbracoHelper umbracoHelper) : base(globalSettings, umbracoContext, sqlContext, services, appCaches, logger, runtimeState, umbracoHelper)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get every tag stored in the database (with optional group)
|
||||
|
||||
@@ -12,11 +12,12 @@ namespace Umbraco.Web.Controllers
|
||||
public class UmbLoginController : SurfaceController
|
||||
{
|
||||
public UmbLoginController()
|
||||
{ }
|
||||
{
|
||||
}
|
||||
|
||||
public UmbLoginController(UmbracoContext umbracoContext, IUmbracoDatabaseFactory databaseFactory, ServiceContext services, AppCaches appCaches, ILogger logger, IProfilingLogger profilingLogger)
|
||||
: base(umbracoContext, databaseFactory, services, appCaches, logger, profilingLogger)
|
||||
{ }
|
||||
public UmbLoginController(UmbracoContext umbracoContext, IUmbracoDatabaseFactory databaseFactory, ServiceContext services, AppCaches appCaches, ILogger logger, IProfilingLogger profilingLogger, UmbracoHelper umbracoHelper) : base(umbracoContext, databaseFactory, services, appCaches, logger, profilingLogger, umbracoHelper)
|
||||
{
|
||||
}
|
||||
|
||||
[HttpPost]
|
||||
[ValidateAntiForgeryToken]
|
||||
|
||||
@@ -14,11 +14,12 @@ namespace Umbraco.Web.Controllers
|
||||
public class UmbLoginStatusController : SurfaceController
|
||||
{
|
||||
public UmbLoginStatusController()
|
||||
{ }
|
||||
{
|
||||
}
|
||||
|
||||
public UmbLoginStatusController(UmbracoContext umbracoContext, IUmbracoDatabaseFactory databaseFactory, ServiceContext services, AppCaches appCaches, ILogger logger, IProfilingLogger profilingLogger)
|
||||
: base(umbracoContext, databaseFactory, services, appCaches, logger, profilingLogger)
|
||||
{ }
|
||||
public UmbLoginStatusController(UmbracoContext umbracoContext, IUmbracoDatabaseFactory databaseFactory, ServiceContext services, AppCaches appCaches, ILogger logger, IProfilingLogger profilingLogger, UmbracoHelper umbracoHelper) : base(umbracoContext, databaseFactory, services, appCaches, logger, profilingLogger, umbracoHelper)
|
||||
{
|
||||
}
|
||||
|
||||
[HttpPost]
|
||||
[ValidateAntiForgeryToken]
|
||||
|
||||
@@ -17,8 +17,8 @@ namespace Umbraco.Web.Controllers
|
||||
public UmbProfileController()
|
||||
{ }
|
||||
|
||||
public UmbProfileController(UmbracoContext umbracoContext, IUmbracoDatabaseFactory databaseFactory, ServiceContext services, AppCaches appCaches, ILogger logger, IProfilingLogger profilingLogger)
|
||||
: base(umbracoContext, databaseFactory, services, appCaches, logger, profilingLogger)
|
||||
public UmbProfileController(UmbracoContext umbracoContext, IUmbracoDatabaseFactory databaseFactory, ServiceContext services, AppCaches appCaches, ILogger logger, IProfilingLogger profilingLogger, UmbracoHelper umbracoHelper)
|
||||
: base(umbracoContext, databaseFactory, services, appCaches, logger, profilingLogger, umbracoHelper)
|
||||
{ }
|
||||
|
||||
[HttpPost]
|
||||
|
||||
@@ -14,11 +14,12 @@ namespace Umbraco.Web.Controllers
|
||||
public class UmbRegisterController : SurfaceController
|
||||
{
|
||||
public UmbRegisterController()
|
||||
{ }
|
||||
{
|
||||
}
|
||||
|
||||
public UmbRegisterController(UmbracoContext umbracoContext, IUmbracoDatabaseFactory databaseFactory, ServiceContext services, AppCaches appCaches, ILogger logger, IProfilingLogger profilingLogger)
|
||||
: base(umbracoContext, databaseFactory, services, appCaches, logger, profilingLogger)
|
||||
{ }
|
||||
public UmbRegisterController(UmbracoContext umbracoContext, IUmbracoDatabaseFactory databaseFactory, ServiceContext services, AppCaches appCaches, ILogger logger, IProfilingLogger profilingLogger, UmbracoHelper umbracoHelper) : base(umbracoContext, databaseFactory, services, appCaches, logger, profilingLogger, umbracoHelper)
|
||||
{
|
||||
}
|
||||
|
||||
[HttpPost]
|
||||
[ValidateAntiForgeryToken]
|
||||
|
||||
@@ -43,18 +43,9 @@ namespace Umbraco.Web.Editors
|
||||
private BackOfficeUserManager<BackOfficeIdentityUser> _userManager;
|
||||
private BackOfficeSignInManager _signInManager;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the new <see cref="AuthenticationController"/> class with auto dependencies.
|
||||
/// </summary>
|
||||
public AuthenticationController()
|
||||
{ }
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="AuthenticationController"/> class with all its dependencies.
|
||||
/// </summary>
|
||||
public AuthenticationController(IGlobalSettings globalSettings, UmbracoContext umbracoContext, ISqlContext sqlContext, ServiceContext services, AppCaches appCaches, IProfilingLogger logger, IRuntimeState runtimeState)
|
||||
: base(globalSettings, umbracoContext, sqlContext, services, appCaches, logger, runtimeState)
|
||||
{ }
|
||||
public AuthenticationController(IGlobalSettings globalSettings, UmbracoContext umbracoContext, ISqlContext sqlContext, ServiceContext services, AppCaches appCaches, IProfilingLogger logger, IRuntimeState runtimeState, UmbracoHelper umbracoHelper) : base(globalSettings, umbracoContext, sqlContext, services, appCaches, logger, runtimeState, umbracoHelper)
|
||||
{
|
||||
}
|
||||
|
||||
protected BackOfficeUserManager<BackOfficeIdentityUser> UserManager => _userManager
|
||||
?? (_userManager = TryGetOwinContext().Result.GetBackOfficeUserManager());
|
||||
|
||||
@@ -49,8 +49,8 @@ namespace Umbraco.Web.Editors
|
||||
private const string TokenPasswordResetCode = "PasswordResetCode";
|
||||
private static readonly string[] TempDataTokenNames = { TokenExternalSignInError, TokenPasswordResetCode };
|
||||
|
||||
public BackOfficeController(ManifestParser manifestParser, UmbracoFeatures features, IGlobalSettings globalSettings, UmbracoContext umbracoContext, ServiceContext services, AppCaches appCaches, ILogger logger, IProfilingLogger profilingLogger, IRuntimeState runtimeState)
|
||||
: base(globalSettings, umbracoContext, services, appCaches, logger, profilingLogger)
|
||||
public BackOfficeController(ManifestParser manifestParser, UmbracoFeatures features, IGlobalSettings globalSettings, UmbracoContext umbracoContext, ServiceContext services, AppCaches appCaches, IProfilingLogger profilingLogger, IRuntimeState runtimeState, UmbracoHelper umbracoHelper)
|
||||
: base(globalSettings, umbracoContext, services, appCaches, profilingLogger, umbracoHelper)
|
||||
{
|
||||
_manifestParser = manifestParser;
|
||||
_features = features;
|
||||
|
||||
@@ -1,4 +1,10 @@
|
||||
using Umbraco.Web.WebApi;
|
||||
using Umbraco.Core;
|
||||
using Umbraco.Core.Cache;
|
||||
using Umbraco.Core.Configuration;
|
||||
using Umbraco.Core.Logging;
|
||||
using Umbraco.Core.Persistence;
|
||||
using Umbraco.Core.Services;
|
||||
using Umbraco.Web.WebApi;
|
||||
using Umbraco.Web.WebApi.Filters;
|
||||
|
||||
namespace Umbraco.Web.Editors
|
||||
@@ -11,5 +17,9 @@ namespace Umbraco.Web.Editors
|
||||
[AppendCurrentEventMessages]
|
||||
[PrefixlessBodyModelValidator]
|
||||
public abstract class BackOfficeNotificationsController : UmbracoAuthorizedJsonController
|
||||
{ }
|
||||
{
|
||||
protected BackOfficeNotificationsController(IGlobalSettings globalSettings, UmbracoContext umbracoContext, ISqlContext sqlContext, ServiceContext services, AppCaches appCaches, IProfilingLogger logger, IRuntimeState runtimeState, UmbracoHelper umbracoHelper) : base(globalSettings, umbracoContext, sqlContext, services, appCaches, logger, runtimeState, umbracoHelper)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,8 +8,12 @@ using System.Net.Http;
|
||||
using System.Web.Http;
|
||||
using ClientDependency.Core;
|
||||
using Umbraco.Core;
|
||||
using Umbraco.Core.Cache;
|
||||
using Umbraco.Core.Configuration;
|
||||
using Umbraco.Core.IO;
|
||||
using Umbraco.Core.Logging;
|
||||
using Umbraco.Core.Models;
|
||||
using Umbraco.Core.Persistence;
|
||||
using Umbraco.Core.Services;
|
||||
using Umbraco.Core.Strings.Css;
|
||||
using Umbraco.Web.Composing;
|
||||
@@ -30,6 +34,9 @@ namespace Umbraco.Web.Editors
|
||||
[UmbracoApplicationAuthorize(Core.Constants.Applications.Settings)]
|
||||
public class CodeFileController : BackOfficeNotificationsController
|
||||
{
|
||||
public CodeFileController(IGlobalSettings globalSettings, UmbracoContext umbracoContext, ISqlContext sqlContext, ServiceContext services, AppCaches appCaches, IProfilingLogger logger, IRuntimeState runtimeState, UmbracoHelper umbracoHelper) : base(globalSettings, umbracoContext, sqlContext, services, appCaches, logger, runtimeState, umbracoHelper)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Used to create a brand new file
|
||||
|
||||
@@ -11,6 +11,8 @@ using System.Web.Http.ModelBinding;
|
||||
using System.Web.Security;
|
||||
using AutoMapper;
|
||||
using Umbraco.Core;
|
||||
using Umbraco.Core.Cache;
|
||||
using Umbraco.Core.Configuration;
|
||||
using Umbraco.Core.Logging;
|
||||
using Umbraco.Core.Models;
|
||||
using Umbraco.Core.Models.Membership;
|
||||
@@ -33,6 +35,7 @@ using Umbraco.Web.ContentApps;
|
||||
using Umbraco.Web.Editors.Binders;
|
||||
using Umbraco.Web.Editors.Filters;
|
||||
using Umbraco.Core.Models.Entities;
|
||||
using Umbraco.Core.Persistence;
|
||||
using Umbraco.Core.Security;
|
||||
|
||||
namespace Umbraco.Web.Editors
|
||||
@@ -54,7 +57,7 @@ namespace Umbraco.Web.Editors
|
||||
|
||||
public object Domains { get; private set; }
|
||||
|
||||
public ContentController(PropertyEditorCollection propertyEditors)
|
||||
public ContentController(PropertyEditorCollection propertyEditors, IGlobalSettings globalSettings, UmbracoContext umbracoContext, ISqlContext sqlContext, ServiceContext services, AppCaches appCaches, IProfilingLogger logger, IRuntimeState runtimeState, UmbracoHelper umbracoHelper) : base(globalSettings, umbracoContext, sqlContext, services, appCaches, logger, runtimeState, umbracoHelper)
|
||||
{
|
||||
_propertyEditors = propertyEditors ?? throw new ArgumentNullException(nameof(propertyEditors));
|
||||
_allLangs = new Lazy<IDictionary<string, ILanguage>>(() => Services.LocalizationService.GetAllLanguages().ToDictionary(x => x.IsoCode, x => x, StringComparer.InvariantCultureIgnoreCase));
|
||||
|
||||
@@ -4,9 +4,12 @@ using System.Net;
|
||||
using System.Net.Http;
|
||||
using System.Web.Http;
|
||||
using Umbraco.Core;
|
||||
using Umbraco.Core.Cache;
|
||||
using Umbraco.Core.Configuration;
|
||||
using Umbraco.Core.Logging;
|
||||
using Umbraco.Core.Models;
|
||||
using Umbraco.Core.Models.Editors;
|
||||
using Umbraco.Core.Persistence;
|
||||
using Umbraco.Core.PropertyEditors;
|
||||
using Umbraco.Core.Services;
|
||||
using Umbraco.Web.Composing;
|
||||
@@ -23,6 +26,10 @@ namespace Umbraco.Web.Editors
|
||||
[JsonDateTimeFormatAttribute]
|
||||
public abstract class ContentControllerBase : BackOfficeNotificationsController
|
||||
{
|
||||
protected ContentControllerBase(IGlobalSettings globalSettings, UmbracoContext umbracoContext, ISqlContext sqlContext, ServiceContext services, AppCaches appCaches, IProfilingLogger logger, IRuntimeState runtimeState, UmbracoHelper umbracoHelper) : base(globalSettings, umbracoContext, sqlContext, services, appCaches, logger, runtimeState, umbracoHelper)
|
||||
{
|
||||
}
|
||||
|
||||
protected HttpResponseMessage HandleContentNotFound(object id, bool throwException = true)
|
||||
{
|
||||
ModelState.AddModelError("id", $"content with id: {id} was not found");
|
||||
|
||||
@@ -54,8 +54,8 @@ namespace Umbraco.Web.Editors
|
||||
UmbracoContext umbracoContext,
|
||||
ISqlContext sqlContext, PropertyEditorCollection propertyEditors,
|
||||
ServiceContext services, AppCaches appCaches,
|
||||
IProfilingLogger logger, IRuntimeState runtimeState)
|
||||
: base(cultureDictionaryFactory, globalSettings, umbracoContext, sqlContext, services, appCaches, logger, runtimeState)
|
||||
IProfilingLogger logger, IRuntimeState runtimeState, UmbracoHelper umbracoHelper)
|
||||
: base(cultureDictionaryFactory, globalSettings, umbracoContext, sqlContext, services, appCaches, logger, runtimeState, umbracoHelper)
|
||||
{
|
||||
_serializer = serializer;
|
||||
_propertyEditors = propertyEditors;
|
||||
|
||||
@@ -33,8 +33,8 @@ namespace Umbraco.Web.Editors
|
||||
private readonly ICultureDictionaryFactory _cultureDictionaryFactory;
|
||||
private ICultureDictionary _cultureDictionary;
|
||||
|
||||
protected ContentTypeControllerBase(ICultureDictionaryFactory cultureDictionaryFactory, IGlobalSettings globalSettings, UmbracoContext umbracoContext, ISqlContext sqlContext, ServiceContext services, AppCaches appCaches, IProfilingLogger logger, IRuntimeState runtimeState)
|
||||
: base(globalSettings, umbracoContext, sqlContext, services, appCaches, logger, runtimeState)
|
||||
protected ContentTypeControllerBase(ICultureDictionaryFactory cultureDictionaryFactory, IGlobalSettings globalSettings, UmbracoContext umbracoContext, ISqlContext sqlContext, ServiceContext services, AppCaches appCaches, IProfilingLogger logger, IRuntimeState runtimeState, UmbracoHelper umbracoHelper)
|
||||
: base(globalSettings, umbracoContext, sqlContext, services, appCaches, logger, runtimeState, umbracoHelper)
|
||||
{
|
||||
_cultureDictionaryFactory = cultureDictionaryFactory;
|
||||
}
|
||||
|
||||
@@ -31,18 +31,12 @@ namespace Umbraco.Web.Editors
|
||||
public class DashboardController : UmbracoApiController
|
||||
{
|
||||
private readonly IDashboardService _dashboardService;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="DashboardController"/> with auto dependencies.
|
||||
/// </summary>
|
||||
public DashboardController()
|
||||
{ }
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="DashboardController"/> with all its dependencies.
|
||||
/// </summary>
|
||||
public DashboardController(IGlobalSettings globalSettings, UmbracoContext umbracoContext, ISqlContext sqlContext, ServiceContext services, AppCaches appCaches, IProfilingLogger logger, IRuntimeState runtimeState, IDashboardService dashboardService)
|
||||
: base(globalSettings, umbracoContext, sqlContext, services, appCaches, logger, runtimeState)
|
||||
public DashboardController(IGlobalSettings globalSettings, UmbracoContext umbracoContext, ISqlContext sqlContext, ServiceContext services, AppCaches appCaches, IProfilingLogger logger, IRuntimeState runtimeState, IDashboardService dashboardService, UmbracoHelper umbracoHelper)
|
||||
: base(globalSettings, umbracoContext, sqlContext, services, appCaches, logger, runtimeState, umbracoHelper)
|
||||
{
|
||||
_dashboardService = dashboardService;
|
||||
}
|
||||
|
||||
@@ -16,8 +16,11 @@ using Umbraco.Web.WebApi.Filters;
|
||||
using Constants = Umbraco.Core.Constants;
|
||||
using System.Net.Http;
|
||||
using System.Text;
|
||||
using Umbraco.Core.Cache;
|
||||
using Umbraco.Web.Composing;
|
||||
using Umbraco.Core.Configuration;
|
||||
using Umbraco.Core.Logging;
|
||||
using Umbraco.Core.Persistence;
|
||||
|
||||
namespace Umbraco.Web.Editors
|
||||
{
|
||||
@@ -36,7 +39,7 @@ namespace Umbraco.Web.Editors
|
||||
{
|
||||
private readonly PropertyEditorCollection _propertyEditors;
|
||||
|
||||
public DataTypeController(PropertyEditorCollection propertyEditors)
|
||||
public DataTypeController(PropertyEditorCollection propertyEditors, IGlobalSettings globalSettings, UmbracoContext umbracoContext, ISqlContext sqlContext, ServiceContext services, AppCaches appCaches, IProfilingLogger logger, IRuntimeState runtimeState, UmbracoHelper umbracoHelper) : base(globalSettings, umbracoContext, sqlContext, services, appCaches, logger, runtimeState, umbracoHelper)
|
||||
{
|
||||
_propertyEditors = propertyEditors;
|
||||
}
|
||||
|
||||
@@ -5,7 +5,13 @@ using System.Net;
|
||||
using System.Net.Http;
|
||||
using System.Web.Http;
|
||||
using AutoMapper;
|
||||
using Umbraco.Core;
|
||||
using Umbraco.Core.Cache;
|
||||
using Umbraco.Core.Configuration;
|
||||
using Umbraco.Core.Logging;
|
||||
using Umbraco.Core.Models;
|
||||
using Umbraco.Core.Persistence;
|
||||
using Umbraco.Core.Services;
|
||||
using Umbraco.Web.Models.ContentEditing;
|
||||
using Umbraco.Web.Mvc;
|
||||
using Umbraco.Web.WebApi;
|
||||
@@ -28,6 +34,10 @@ namespace Umbraco.Web.Editors
|
||||
[EnableOverrideAuthorization]
|
||||
public class DictionaryController : BackOfficeNotificationsController
|
||||
{
|
||||
public DictionaryController(IGlobalSettings globalSettings, UmbracoContext umbracoContext, ISqlContext sqlContext, ServiceContext services, AppCaches appCaches, IProfilingLogger logger, IRuntimeState runtimeState, UmbracoHelper umbracoHelper) : base(globalSettings, umbracoContext, sqlContext, services, appCaches, logger, runtimeState, umbracoHelper)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Deletes a data type with a given ID
|
||||
/// </summary>
|
||||
|
||||
@@ -47,8 +47,8 @@ namespace Umbraco.Web.Editors
|
||||
private readonly SearchableTreeCollection _searchableTreeCollection;
|
||||
|
||||
public EntityController(IGlobalSettings globalSettings, UmbracoContext umbracoContext, ISqlContext sqlContext, ServiceContext services, AppCaches appCaches, IProfilingLogger logger, IRuntimeState runtimeState,
|
||||
ITreeService treeService, SearchableTreeCollection searchableTreeCollection, UmbracoTreeSearcher treeSearcher)
|
||||
: base(globalSettings, umbracoContext, sqlContext, services, appCaches, logger, runtimeState)
|
||||
ITreeService treeService, UmbracoHelper umbracoHelper, SearchableTreeCollection searchableTreeCollection, UmbracoTreeSearcher treeSearcher)
|
||||
: base(globalSettings, umbracoContext, sqlContext, services, appCaches, logger, runtimeState, umbracoHelper)
|
||||
{
|
||||
_treeService = treeService;
|
||||
_searchableTreeCollection = searchableTreeCollection;
|
||||
@@ -108,6 +108,8 @@ namespace Umbraco.Web.Editors
|
||||
if (string.IsNullOrEmpty(query))
|
||||
return Enumerable.Empty<EntityBasic>();
|
||||
|
||||
//TODO: This uses the internal UmbracoTreeSearcher, this instead should delgate to the ISearchableTree implementation for the type
|
||||
|
||||
return ExamineSearch(query, type, searchFrom);
|
||||
}
|
||||
|
||||
@@ -451,6 +453,9 @@ namespace Umbraco.Web.Editors
|
||||
//the EntityService cannot search members of a certain type, this is currently not supported and would require
|
||||
//quite a bit of plumbing to do in the Services/Repository, we'll revert to a paged search
|
||||
|
||||
//TODO: We should really fix this in the EntityService but if we don't we should allow the ISearchableTree for the members controller
|
||||
// to be used for this search instead of the built in/internal searcher
|
||||
|
||||
var searchResult = _treeSearcher.ExamineSearch(filter ?? "", type, pageSize, pageNumber - 1, out long total, id);
|
||||
|
||||
return new PagedResult<EntityBasic>(total, pageNumber, pageSize)
|
||||
|
||||
@@ -32,9 +32,12 @@ namespace Umbraco.Web.Editors
|
||||
{
|
||||
private readonly IMacroService _macroService;
|
||||
private readonly IContentService _contentService;
|
||||
private readonly IUmbracoComponentRenderer _componentRenderer;
|
||||
private readonly IVariationContextAccessor _variationContextAccessor;
|
||||
public MacroRenderingController(IVariationContextAccessor variationContextAccessor, IMacroService macroService, IContentService contentService)
|
||||
|
||||
public MacroRenderingController(IUmbracoComponentRenderer componentRenderer, IVariationContextAccessor variationContextAccessor, IMacroService macroService, IContentService contentService)
|
||||
{
|
||||
_componentRenderer = componentRenderer;
|
||||
_variationContextAccessor = variationContextAccessor;
|
||||
_macroService = macroService;
|
||||
_contentService = contentService;
|
||||
@@ -99,21 +102,15 @@ namespace Umbraco.Web.Editors
|
||||
|
||||
private HttpResponseMessage GetMacroResultAsHtml(string macroAlias, int pageId, IDictionary<string, object> macroParams)
|
||||
{
|
||||
// note - here we should be using the cache, provided that the preview content is in the cache...
|
||||
|
||||
var doc = _contentService.GetById(pageId);
|
||||
if (doc == null)
|
||||
{
|
||||
throw new HttpResponseException(HttpStatusCode.NotFound);
|
||||
}
|
||||
|
||||
var m = _macroService.GetByAlias(macroAlias);
|
||||
if (m == null)
|
||||
throw new HttpResponseException(HttpStatusCode.NotFound);
|
||||
var macro = new MacroModel(m);
|
||||
|
||||
var publishedContent = UmbracoContext.ContentCache.GetById(true, pageId);
|
||||
|
||||
//if it isn't supposed to be rendered in the editor then return an empty string
|
||||
if (macro.RenderInEditor == false)
|
||||
//currently we cannot render a macro if the page doesn't yet exist
|
||||
if (pageId == -1 || publishedContent == null || !m.UseInEditor)
|
||||
{
|
||||
var response = Request.CreateResponse();
|
||||
//need to create a specific content result formatted as HTML since this controller has been configured
|
||||
@@ -123,32 +120,24 @@ namespace Umbraco.Web.Editors
|
||||
return response;
|
||||
}
|
||||
|
||||
//because macro's are filled with insane legacy bits and pieces we need all sorts of weirdness to make them render.
|
||||
//the 'easiest' way might be to create an IPublishedContent manually and populate the legacy 'page' object with that
|
||||
//and then set the legacy parameters.
|
||||
|
||||
// When rendering the macro in the backoffice the default setting would be to use the Culture of the logged in user.
|
||||
// Since a Macro might contain thing thats related to the culture of the "IPublishedContent" (ie Dictionary keys) we want
|
||||
// to set the current culture to the culture related to the content item. This is hacky but it works.
|
||||
var publishedContent = UmbracoContext.ContentCache.GetById(doc.Id);
|
||||
var culture = publishedContent?.GetCulture();
|
||||
|
||||
var culture = publishedContent.GetCulture();
|
||||
_variationContextAccessor.VariationContext = new VariationContext(); //must have an active variation context!
|
||||
if (culture != null)
|
||||
{
|
||||
Thread.CurrentThread.CurrentCulture = Thread.CurrentThread.CurrentUICulture = CultureInfo.GetCultureInfo(culture.Culture);
|
||||
_variationContextAccessor.VariationContext = new VariationContext(Thread.CurrentThread.CurrentCulture.Name);
|
||||
}
|
||||
|
||||
var legacyPage = new global::Umbraco.Web.Macros.PublishedContentHashtableConverter(doc, _variationContextAccessor);
|
||||
|
||||
UmbracoContext.HttpContext.Items["pageElements"] = legacyPage.Elements;
|
||||
UmbracoContext.HttpContext.Items[Core.Constants.Conventions.Url.AltTemplate] = null;
|
||||
|
||||
var renderer = new UmbracoComponentRenderer(UmbracoContext);
|
||||
|
||||
var result = Request.CreateResponse();
|
||||
//need to create a specific content result formatted as HTML since this controller has been configured
|
||||
//with only json formatters.
|
||||
result.Content = new StringContent(
|
||||
renderer.RenderMacro(macro, macroParams, legacyPage).ToString(),
|
||||
_componentRenderer.RenderMacro(pageId, m.Alias, macroParams).ToString(),
|
||||
Encoding.UTF8,
|
||||
"text/html");
|
||||
return result;
|
||||
|
||||
@@ -7,9 +7,12 @@ using System.Net;
|
||||
using System.Net.Http;
|
||||
using System.Web.Http;
|
||||
using Umbraco.Core;
|
||||
using Umbraco.Core.Cache;
|
||||
using Umbraco.Core.Configuration;
|
||||
using Umbraco.Core.IO;
|
||||
using Umbraco.Core.Logging;
|
||||
using Umbraco.Core.Models;
|
||||
using Umbraco.Core.Persistence;
|
||||
using Umbraco.Web.Composing;
|
||||
using Umbraco.Web.Models.ContentEditing;
|
||||
using Umbraco.Web.Mvc;
|
||||
@@ -29,9 +32,9 @@ namespace Umbraco.Web.Editors
|
||||
{
|
||||
private readonly IMacroService _macroService;
|
||||
|
||||
public MacrosController(IMacroService macroService)
|
||||
public MacrosController(IGlobalSettings globalSettings, UmbracoContext umbracoContext, ISqlContext sqlContext, ServiceContext services, AppCaches appCaches, IProfilingLogger logger, IRuntimeState runtimeState, UmbracoHelper umbracoHelper) : base(globalSettings, umbracoContext, sqlContext, services, appCaches, logger, runtimeState, umbracoHelper)
|
||||
{
|
||||
_macroService = macroService;
|
||||
_macroService = Services.MacroService;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -21,7 +21,9 @@ using Umbraco.Web.Mvc;
|
||||
using Umbraco.Web.WebApi;
|
||||
using System.Linq;
|
||||
using System.Web.Http.Controllers;
|
||||
using Umbraco.Core.Cache;
|
||||
using Umbraco.Core.Composing;
|
||||
using Umbraco.Core.Configuration;
|
||||
using Umbraco.Web.WebApi.Filters;
|
||||
using Constants = Umbraco.Core.Constants;
|
||||
using Umbraco.Core.Persistence.Querying;
|
||||
@@ -47,7 +49,7 @@ namespace Umbraco.Web.Editors
|
||||
[MediaControllerControllerConfiguration]
|
||||
public class MediaController : ContentControllerBase
|
||||
{
|
||||
public MediaController(PropertyEditorCollection propertyEditors, IContentTypeBaseServiceProvider contentTypeBaseServiceProvider)
|
||||
public MediaController(PropertyEditorCollection propertyEditors, IGlobalSettings globalSettings, UmbracoContext umbracoContext, ISqlContext sqlContext, ServiceContext services, AppCaches appCaches, IProfilingLogger logger, IRuntimeState runtimeState, UmbracoHelper umbracoHelper, IContentTypeBaseServiceProvider contentTypeBaseServiceProvider) : base(globalSettings, umbracoContext, sqlContext, services, appCaches, logger, runtimeState, umbracoHelper)
|
||||
{
|
||||
_propertyEditors = propertyEditors ?? throw new ArgumentNullException(nameof(propertyEditors));
|
||||
_contentTypeBaseServiceProvider = contentTypeBaseServiceProvider;
|
||||
|
||||
@@ -37,8 +37,7 @@ namespace Umbraco.Web.Editors
|
||||
[MediaTypeControllerControllerConfiguration]
|
||||
public class MediaTypeController : ContentTypeControllerBase<IMediaType>
|
||||
{
|
||||
public MediaTypeController(ICultureDictionaryFactory cultureDictionaryFactory, IGlobalSettings globalSettings, UmbracoContext umbracoContext, ISqlContext sqlContext, ServiceContext services, AppCaches appCaches, IProfilingLogger logger, IRuntimeState runtimeState)
|
||||
: base(cultureDictionaryFactory, globalSettings, umbracoContext, sqlContext, services, appCaches, logger, runtimeState)
|
||||
public MediaTypeController(ICultureDictionaryFactory cultureDictionaryFactory, IGlobalSettings globalSettings, UmbracoContext umbracoContext, ISqlContext sqlContext, ServiceContext services, AppCaches appCaches, IProfilingLogger logger, IRuntimeState runtimeState, UmbracoHelper umbracoHelper) : base(cultureDictionaryFactory, globalSettings, umbracoContext, sqlContext, services, appCaches, logger, runtimeState, umbracoHelper)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
@@ -26,7 +26,10 @@ using Umbraco.Web.Mvc;
|
||||
using Umbraco.Web.WebApi.Filters;
|
||||
using Constants = Umbraco.Core.Constants;
|
||||
using System.Collections.Generic;
|
||||
using Umbraco.Core.Cache;
|
||||
using Umbraco.Core.Configuration;
|
||||
using Umbraco.Core.Models.ContentEditing;
|
||||
using Umbraco.Core.Persistence;
|
||||
using Umbraco.Core.PropertyEditors;
|
||||
using Umbraco.Web.ContentApps;
|
||||
using Umbraco.Web.Editors.Binders;
|
||||
@@ -43,7 +46,7 @@ namespace Umbraco.Web.Editors
|
||||
[OutgoingNoHyphenGuidFormat]
|
||||
public class MemberController : ContentControllerBase
|
||||
{
|
||||
public MemberController(PropertyEditorCollection propertyEditors)
|
||||
public MemberController(PropertyEditorCollection propertyEditors, IGlobalSettings globalSettings, UmbracoContext umbracoContext, ISqlContext sqlContext, ServiceContext services, AppCaches appCaches, IProfilingLogger logger, IRuntimeState runtimeState, UmbracoHelper umbracoHelper) : base(globalSettings, umbracoContext, sqlContext, services, appCaches, logger, runtimeState, umbracoHelper)
|
||||
{
|
||||
_propertyEditors = propertyEditors ?? throw new ArgumentNullException(nameof(propertyEditors));
|
||||
}
|
||||
|
||||
@@ -30,8 +30,7 @@ namespace Umbraco.Web.Editors
|
||||
[UmbracoTreeAuthorize(new string[] { Constants.Trees.MemberTypes, Constants.Trees.Members})]
|
||||
public class MemberTypeController : ContentTypeControllerBase<IMemberType>
|
||||
{
|
||||
public MemberTypeController(ICultureDictionaryFactory cultureDictionaryFactory, IGlobalSettings globalSettings, UmbracoContext umbracoContext, ISqlContext sqlContext, ServiceContext services, AppCaches appCaches, IProfilingLogger logger, IRuntimeState runtimeState)
|
||||
: base(cultureDictionaryFactory, globalSettings, umbracoContext, sqlContext, services, appCaches, logger, runtimeState)
|
||||
public MemberTypeController(ICultureDictionaryFactory cultureDictionaryFactory, IGlobalSettings globalSettings, UmbracoContext umbracoContext, ISqlContext sqlContext, ServiceContext services, AppCaches appCaches, IProfilingLogger logger, IRuntimeState runtimeState, UmbracoHelper umbracoHelper) : base(cultureDictionaryFactory, globalSettings, umbracoContext, sqlContext, services, appCaches, logger, runtimeState, umbracoHelper)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
@@ -36,8 +36,8 @@ namespace Umbraco.Web.Editors
|
||||
{
|
||||
public PackageInstallController(IGlobalSettings globalSettings, UmbracoContext umbracoContext,
|
||||
ISqlContext sqlContext, ServiceContext services, AppCaches appCaches,
|
||||
IProfilingLogger logger, IRuntimeState runtimeState)
|
||||
: base(globalSettings, umbracoContext, sqlContext, services, appCaches, logger, runtimeState)
|
||||
IProfilingLogger logger, IRuntimeState runtimeState, UmbracoHelper umbracoHelper)
|
||||
: base(globalSettings, umbracoContext, sqlContext, services, appCaches, logger, runtimeState, umbracoHelper)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
@@ -35,7 +35,7 @@ namespace Umbraco.Web.Editors
|
||||
public IHttpActionResult GetEnableState()
|
||||
{
|
||||
var enabled = Current.Configs.Settings().WebRouting.DisableRedirectUrlTracking == false;
|
||||
var userIsAdmin = Umbraco.UmbracoContext.Security.CurrentUser.IsAdmin();
|
||||
var userIsAdmin = UmbracoContext.Security.CurrentUser.IsAdmin();
|
||||
return Ok(new { enabled, userIsAdmin });
|
||||
}
|
||||
|
||||
@@ -92,7 +92,7 @@ namespace Umbraco.Web.Editors
|
||||
[HttpPost]
|
||||
public IHttpActionResult ToggleUrlTracker(bool disable)
|
||||
{
|
||||
var userIsAdmin = Umbraco.UmbracoContext.Security.CurrentUser.IsAdmin();
|
||||
var userIsAdmin = UmbracoContext.Security.CurrentUser.IsAdmin();
|
||||
if (userIsAdmin == false)
|
||||
{
|
||||
var errorMessage = "User is not a member of the administrators group and so is not allowed to toggle the URL tracker";
|
||||
|
||||
@@ -5,7 +5,12 @@ using System.Net.Http;
|
||||
using System.Web.Http;
|
||||
using AutoMapper;
|
||||
using Umbraco.Core;
|
||||
using Umbraco.Core.Cache;
|
||||
using Umbraco.Core.Configuration;
|
||||
using Umbraco.Core.Logging;
|
||||
using Umbraco.Core.Models;
|
||||
using Umbraco.Core.Persistence;
|
||||
using Umbraco.Core.Services;
|
||||
using Umbraco.Web.Models.ContentEditing;
|
||||
using Umbraco.Web.Mvc;
|
||||
using Umbraco.Web.WebApi;
|
||||
@@ -22,6 +27,10 @@ namespace Umbraco.Web.Editors
|
||||
[EnableOverrideAuthorization]
|
||||
public class RelationTypeController : BackOfficeNotificationsController
|
||||
{
|
||||
public RelationTypeController(IGlobalSettings globalSettings, UmbracoContext umbracoContext, ISqlContext sqlContext, ServiceContext services, AppCaches appCaches, IProfilingLogger logger, IRuntimeState runtimeState, UmbracoHelper umbracoHelper) : base(globalSettings, umbracoContext, sqlContext, services, appCaches, logger, runtimeState, umbracoHelper)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets a relation type by ID.
|
||||
/// </summary>
|
||||
|
||||
@@ -27,8 +27,8 @@ namespace Umbraco.Web.Editors
|
||||
private readonly ITreeService _treeService;
|
||||
|
||||
public SectionController(IGlobalSettings globalSettings, UmbracoContext umbracoContext, ISqlContext sqlContext, ServiceContext services, AppCaches appCaches, IProfilingLogger logger, IRuntimeState runtimeState,
|
||||
IDashboardService dashboardService, ISectionService sectionService, ITreeService treeService)
|
||||
: base(globalSettings, umbracoContext, sqlContext, services, appCaches, logger, runtimeState)
|
||||
IDashboardService dashboardService, ISectionService sectionService, ITreeService treeService, UmbracoHelper umbracoHelper)
|
||||
: base(globalSettings, umbracoContext, sqlContext, services, appCaches, logger, runtimeState, umbracoHelper)
|
||||
{
|
||||
_dashboardService = dashboardService;
|
||||
_sectionService = sectionService;
|
||||
@@ -43,7 +43,7 @@ namespace Umbraco.Web.Editors
|
||||
|
||||
// this is a bit nasty since we'll be proxying via the app tree controller but we sort of have to do that
|
||||
// since tree's by nature are controllers and require request contextual data
|
||||
var appTreeController = new ApplicationTreeController(GlobalSettings, UmbracoContext, SqlContext, Services, AppCaches, Logger, RuntimeState, _treeService)
|
||||
var appTreeController = new ApplicationTreeController(GlobalSettings, UmbracoContext, SqlContext, Services, AppCaches, Logger, RuntimeState, _treeService, Umbraco)
|
||||
{
|
||||
ControllerContext = ControllerContext
|
||||
};
|
||||
|
||||
@@ -4,8 +4,14 @@ using System.Linq;
|
||||
using System.Net;
|
||||
using System.Net.Http;
|
||||
using System.Web.Http;
|
||||
using Umbraco.Core;
|
||||
using Umbraco.Core.Cache;
|
||||
using Umbraco.Core.Configuration;
|
||||
using Umbraco.Core.IO;
|
||||
using Umbraco.Core.Logging;
|
||||
using Umbraco.Core.Models;
|
||||
using Umbraco.Core.Persistence;
|
||||
using Umbraco.Core.Services;
|
||||
using Umbraco.Web.Models.ContentEditing;
|
||||
using Umbraco.Web.Mvc;
|
||||
using Umbraco.Web.WebApi.Filters;
|
||||
@@ -17,6 +23,10 @@ namespace Umbraco.Web.Editors
|
||||
[UmbracoTreeAuthorize(Constants.Trees.Templates)]
|
||||
public class TemplateController : BackOfficeNotificationsController
|
||||
{
|
||||
public TemplateController(IGlobalSettings globalSettings, UmbracoContext umbracoContext, ISqlContext sqlContext, ServiceContext services, AppCaches appCaches, IProfilingLogger logger, IRuntimeState runtimeState, UmbracoHelper umbracoHelper) : base(globalSettings, umbracoContext, sqlContext, services, appCaches, logger, runtimeState, umbracoHelper)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets data type by alias
|
||||
/// </summary>
|
||||
|
||||
@@ -20,24 +20,11 @@ namespace Umbraco.Web.Editors
|
||||
[AngularJsonOnlyConfiguration]
|
||||
public abstract class UmbracoAuthorizedJsonController : UmbracoAuthorizedApiController
|
||||
{
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="UmbracoAuthorizedJsonController"/> with auto dependencies.
|
||||
/// </summary>
|
||||
protected UmbracoAuthorizedJsonController()
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="UmbracoAuthorizedJsonController"/> class with all its dependencies.
|
||||
/// </summary>
|
||||
/// <param name="globalSettings"></param>
|
||||
/// <param name="umbracoContext"></param>
|
||||
/// <param name="sqlContext"></param>
|
||||
/// <param name="services"></param>
|
||||
/// <param name="appCaches"></param>
|
||||
/// <param name="logger"></param>
|
||||
/// <param name="runtimeState"></param>
|
||||
protected UmbracoAuthorizedJsonController(IGlobalSettings globalSettings, UmbracoContext umbracoContext, ISqlContext sqlContext, ServiceContext services, AppCaches appCaches, IProfilingLogger logger, IRuntimeState runtimeState) : base(globalSettings, umbracoContext, sqlContext, services, appCaches, logger, runtimeState)
|
||||
protected UmbracoAuthorizedJsonController(IGlobalSettings globalSettings, UmbracoContext umbracoContext, ISqlContext sqlContext, ServiceContext services, AppCaches appCaches, IProfilingLogger logger, IRuntimeState runtimeState, UmbracoHelper umbracoHelper) : base(globalSettings, umbracoContext, sqlContext, services, appCaches, logger, runtimeState, umbracoHelper)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,10 +17,12 @@ using Umbraco.Core.Cache;
|
||||
using Umbraco.Core.Composing;
|
||||
using Umbraco.Core.Configuration;
|
||||
using Umbraco.Core.IO;
|
||||
using Umbraco.Core.Logging;
|
||||
using Umbraco.Core.Models;
|
||||
using Umbraco.Core.Models.Editors;
|
||||
using Umbraco.Core.Models.Identity;
|
||||
using Umbraco.Core.Models.Membership;
|
||||
using Umbraco.Core.Persistence;
|
||||
using Umbraco.Core.Persistence.DatabaseModelDefinitions;
|
||||
using Umbraco.Core.Persistence.Querying;
|
||||
using Umbraco.Core.Security;
|
||||
@@ -43,6 +45,10 @@ namespace Umbraco.Web.Editors
|
||||
[IsCurrentUserModelFilter]
|
||||
public class UsersController : UmbracoAuthorizedJsonController
|
||||
{
|
||||
public UsersController(IGlobalSettings globalSettings, UmbracoContext umbracoContext, ISqlContext sqlContext, ServiceContext services, AppCaches appCaches, IProfilingLogger logger, IRuntimeState runtimeState, UmbracoHelper umbracoHelper) : base(globalSettings, umbracoContext, sqlContext, services, appCaches, logger, runtimeState, umbracoHelper)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns a list of the sizes of gravatar urls for the user or null if the gravatar server cannot be reached
|
||||
/// </summary>
|
||||
|
||||
@@ -92,13 +92,13 @@ namespace Umbraco.Web
|
||||
{
|
||||
throw new InvalidOperationException("Cannot cache by page if the UmbracoContext has not been initialized, this parameter can only be used in the context of an Umbraco request");
|
||||
}
|
||||
cacheKey.AppendFormat("{0}-", UmbracoContext.Current.PageId);
|
||||
cacheKey.AppendFormat("{0}-", UmbracoContext.Current.PublishedRequest?.PublishedContent?.Id ?? 0);
|
||||
}
|
||||
if (cacheByMember)
|
||||
{
|
||||
var helper = Current.Factory.GetInstance<MembershipHelper>();
|
||||
var currentMember = helper.GetCurrentMember();
|
||||
cacheKey.AppendFormat("m{0}-", currentMember == null ? 0 : currentMember.Id);
|
||||
cacheKey.AppendFormat("m{0}-", currentMember?.Id ?? 0);
|
||||
}
|
||||
if (contextualKeyBuilder != null)
|
||||
{
|
||||
|
||||
@@ -12,32 +12,35 @@ namespace Umbraco.Web
|
||||
/// <summary>
|
||||
/// Renders the template for the specified pageId and an optional altTemplateId
|
||||
/// </summary>
|
||||
/// <param name="pageId"></param>
|
||||
/// <param name="contentId"></param>
|
||||
/// <param name="altTemplateId">If not specified, will use the template assigned to the node</param>
|
||||
/// <returns></returns>
|
||||
IHtmlString RenderTemplate(int pageId, int? altTemplateId = null);
|
||||
IHtmlString RenderTemplate(int contentId, int? altTemplateId = null);
|
||||
|
||||
/// <summary>
|
||||
/// Renders the macro with the specified alias.
|
||||
/// </summary>
|
||||
/// <param name="contentId"></param>
|
||||
/// <param name="alias">The alias.</param>
|
||||
/// <returns></returns>
|
||||
IHtmlString RenderMacro(string alias);
|
||||
IHtmlString RenderMacro(int contentId, string alias);
|
||||
|
||||
/// <summary>
|
||||
/// Renders the macro with the specified alias, passing in the specified parameters.
|
||||
/// </summary>
|
||||
/// <param name="contentId"></param>
|
||||
/// <param name="alias">The alias.</param>
|
||||
/// <param name="parameters">The parameters.</param>
|
||||
/// <returns></returns>
|
||||
IHtmlString RenderMacro(string alias, object parameters);
|
||||
IHtmlString RenderMacro(int contentId, string alias, object parameters);
|
||||
|
||||
/// <summary>
|
||||
/// Renders the macro with the specified alias, passing in the specified parameters.
|
||||
/// </summary>
|
||||
/// <param name="contentId"></param>
|
||||
/// <param name="alias">The alias.</param>
|
||||
/// <param name="parameters">The parameters.</param>
|
||||
/// <returns></returns>
|
||||
IHtmlString RenderMacro(string alias, IDictionary<string, object> parameters);
|
||||
IHtmlString RenderMacro(int contentId, string alias, IDictionary<string, object> parameters);
|
||||
}
|
||||
}
|
||||
|
||||
13
src/Umbraco.Web/Macros/IMacroRenderer.cs
Normal file
13
src/Umbraco.Web/Macros/IMacroRenderer.cs
Normal file
@@ -0,0 +1,13 @@
|
||||
using System.Collections.Generic;
|
||||
using Umbraco.Core.Models.PublishedContent;
|
||||
|
||||
namespace Umbraco.Web.Macros
|
||||
{
|
||||
/// <summary>
|
||||
/// Renders a macro
|
||||
/// </summary>
|
||||
public interface IMacroRenderer
|
||||
{
|
||||
MacroContent Render(string macroAlias, IPublishedContent content, IDictionary<string, object> macroParams);
|
||||
}
|
||||
}
|
||||
@@ -1,22 +1,25 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Text.RegularExpressions;
|
||||
using Umbraco.Core;
|
||||
using Umbraco.Core.IO;
|
||||
using Umbraco.Core.Models;
|
||||
using Umbraco.Core.Services.Implement;
|
||||
|
||||
namespace Umbraco.Web.Macros
|
||||
{
|
||||
public class MacroModel
|
||||
{
|
||||
/// <summary>
|
||||
/// The Macro Id
|
||||
/// </summary>
|
||||
public int Id { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The Macro Name
|
||||
/// </summary>
|
||||
public string Name { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The Macro Alias
|
||||
/// </summary>
|
||||
public string Alias { get; set; }
|
||||
|
||||
public string MacroControlIdentifier { get; set; }
|
||||
|
||||
public MacroTypes MacroType { get; set; }
|
||||
|
||||
public string MacroSource { get; set; }
|
||||
|
||||
@@ -3,45 +3,44 @@ using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Net;
|
||||
using System.Net.Security;
|
||||
using System.Security.Cryptography;
|
||||
using System.Security.Cryptography.X509Certificates;
|
||||
using System.Text;
|
||||
using System.Text.RegularExpressions;
|
||||
using System.Web;
|
||||
using System.Web.Caching;
|
||||
using Umbraco.Core;
|
||||
using Umbraco.Core.Cache;
|
||||
using Umbraco.Core.Configuration;
|
||||
using Umbraco.Core.Configuration.UmbracoSettings;
|
||||
using Umbraco.Core.Events;
|
||||
using Umbraco.Core.IO;
|
||||
using Umbraco.Core.Logging;
|
||||
using Umbraco.Core.Macros;
|
||||
using Umbraco.Core.Models;
|
||||
using Umbraco.Core.Models.PublishedContent;
|
||||
using Umbraco.Core.Services;
|
||||
using Umbraco.Web.Composing;
|
||||
|
||||
namespace Umbraco.Web.Macros
|
||||
{
|
||||
public class MacroRenderer
|
||||
internal class MacroRenderer : IMacroRenderer
|
||||
{
|
||||
private readonly IProfilingLogger _plogger;
|
||||
private readonly IUmbracoContextAccessor _umbracoContextAccessor;
|
||||
private readonly IContentSection _contentSection;
|
||||
private readonly ILocalizedTextService _textService;
|
||||
private readonly AppCaches _appCaches;
|
||||
private readonly IMacroService _macroService;
|
||||
|
||||
// TODO: there are many more things that would need to be injected in here
|
||||
|
||||
public MacroRenderer(IProfilingLogger plogger)
|
||||
public MacroRenderer(IProfilingLogger plogger, IUmbracoContextAccessor umbracoContextAccessor, IContentSection contentSection, ILocalizedTextService textService, AppCaches appCaches, IMacroService macroService)
|
||||
{
|
||||
_plogger = plogger;
|
||||
_plogger = plogger ?? throw new ArgumentNullException(nameof(plogger));
|
||||
_umbracoContextAccessor = umbracoContextAccessor ?? throw new ArgumentNullException(nameof(umbracoContextAccessor));
|
||||
_contentSection = contentSection ?? throw new ArgumentNullException(nameof(contentSection));
|
||||
_textService = textService;
|
||||
_appCaches = appCaches ?? throw new ArgumentNullException(nameof(appCaches));
|
||||
_macroService = macroService ?? throw new ArgumentNullException(nameof(macroService));
|
||||
}
|
||||
|
||||
// probably can do better - just porting from v7
|
||||
public IList<Exception> Exceptions { get; } = new List<Exception>();
|
||||
|
||||
#region MacroContent cache
|
||||
|
||||
// gets this macro content cache identifier
|
||||
private static string GetContentCacheIdentifier(MacroModel model, int pageId)
|
||||
private string GetContentCacheIdentifier(MacroModel model, int pageId)
|
||||
{
|
||||
var id = new StringBuilder();
|
||||
|
||||
@@ -55,8 +54,9 @@ namespace Umbraco.Web.Macros
|
||||
{
|
||||
object key = 0;
|
||||
|
||||
if (HttpContext.Current.User.Identity.IsAuthenticated)
|
||||
if (_umbracoContextAccessor.UmbracoContext.HttpContext?.User?.Identity?.IsAuthenticated ?? false)
|
||||
{
|
||||
//ugh, membershipproviders :(
|
||||
var provider = Core.Security.MembershipProviderExtensions.GetMembersMembershipProvider();
|
||||
var member = Core.Security.MembershipProviderExtensions.GetCurrentUser(provider);
|
||||
key = member?.ProviderUserKey ?? 0;
|
||||
@@ -71,34 +71,19 @@ namespace Umbraco.Web.Macros
|
||||
return id.ToString();
|
||||
}
|
||||
|
||||
private static string GenerateCacheKeyFromCode(string input)
|
||||
{
|
||||
if (string.IsNullOrEmpty(input)) throw new ArgumentNullException(nameof(input));
|
||||
|
||||
// step 1, calculate MD5 hash from input
|
||||
var md5 = MD5.Create();
|
||||
var inputBytes = Encoding.ASCII.GetBytes(input);
|
||||
var hash = md5.ComputeHash(inputBytes);
|
||||
|
||||
// step 2, convert byte array to hex string
|
||||
var sb = new StringBuilder();
|
||||
foreach (var h in hash) sb.Append(h.ToString("X2"));
|
||||
return sb.ToString();
|
||||
}
|
||||
|
||||
// gets this macro content from the cache
|
||||
// ensuring that it is appropriate to use the cache
|
||||
private static MacroContent GetMacroContentFromCache(MacroModel model)
|
||||
private MacroContent GetMacroContentFromCache(MacroModel model)
|
||||
{
|
||||
// only if cache is enabled
|
||||
if (UmbracoContext.Current.InPreviewMode || model.CacheDuration <= 0) return null;
|
||||
if (_umbracoContextAccessor.UmbracoContext.InPreviewMode || model.CacheDuration <= 0) return null;
|
||||
|
||||
var cache = Current.AppCaches.RuntimeCache;
|
||||
var cache = _appCaches.RuntimeCache;
|
||||
var macroContent = cache.GetCacheItem<MacroContent>(CacheKeys.MacroContentCacheKey + model.CacheIdentifier);
|
||||
|
||||
if (macroContent == null) return null;
|
||||
|
||||
Current.Logger.Debug<MacroRenderer>("Macro content loaded from cache '{MacroCacheId}'", model.CacheIdentifier);
|
||||
_plogger.Debug<MacroRenderer>("Macro content loaded from cache '{MacroCacheId}'", model.CacheIdentifier);
|
||||
|
||||
// ensure that the source has not changed
|
||||
// note: does not handle dependencies, and never has
|
||||
@@ -107,13 +92,13 @@ namespace Umbraco.Web.Macros
|
||||
{
|
||||
if (macroSource.Exists == false)
|
||||
{
|
||||
Current.Logger.Debug<MacroRenderer>("Macro source does not exist anymore, ignore cache.");
|
||||
_plogger.Debug<MacroRenderer>("Macro source does not exist anymore, ignore cache.");
|
||||
return null;
|
||||
}
|
||||
|
||||
if (macroContent.Date < macroSource.LastWriteTime)
|
||||
{
|
||||
Current.Logger.Debug<MacroRenderer>("Macro source has changed, ignore cache.");
|
||||
_plogger.Debug<MacroRenderer>("Macro source has changed, ignore cache.");
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -126,10 +111,10 @@ namespace Umbraco.Web.Macros
|
||||
}
|
||||
|
||||
// stores macro content into the cache
|
||||
private static void AddMacroContentToCache(MacroModel model, MacroContent macroContent)
|
||||
private void AddMacroContentToCache(MacroModel model, MacroContent macroContent)
|
||||
{
|
||||
// only if cache is enabled
|
||||
if (UmbracoContext.Current.InPreviewMode || model.CacheDuration <= 0) return;
|
||||
if (_umbracoContextAccessor.UmbracoContext.InPreviewMode || model.CacheDuration <= 0) return;
|
||||
|
||||
// just make sure...
|
||||
if (macroContent == null) return;
|
||||
@@ -150,7 +135,7 @@ namespace Umbraco.Web.Macros
|
||||
// remember when we cache the content
|
||||
macroContent.Date = DateTime.Now;
|
||||
|
||||
var cache = Current.AppCaches.RuntimeCache;
|
||||
var cache = _appCaches.RuntimeCache;
|
||||
cache.Insert(
|
||||
CacheKeys.MacroContentCacheKey + model.CacheIdentifier,
|
||||
() => macroContent,
|
||||
@@ -158,7 +143,7 @@ namespace Umbraco.Web.Macros
|
||||
priority: CacheItemPriority.NotRemovable
|
||||
);
|
||||
|
||||
Current.Logger.Debug<MacroRenderer>("Macro content saved to cache '{MacroCacheId}'", model.CacheIdentifier);
|
||||
_plogger.Debug<MacroRenderer>("Macro content saved to cache '{MacroCacheId}'", model.CacheIdentifier);
|
||||
}
|
||||
|
||||
// gets the macro source file name
|
||||
@@ -183,7 +168,7 @@ namespace Umbraco.Web.Macros
|
||||
|
||||
// gets the macro source file
|
||||
// null if macro is not file-based
|
||||
internal static FileInfo GetMacroFile(MacroModel model)
|
||||
private static FileInfo GetMacroFile(MacroModel model)
|
||||
{
|
||||
var filename = GetMacroFileName(model);
|
||||
if (filename == null) return null;
|
||||
@@ -195,47 +180,38 @@ namespace Umbraco.Web.Macros
|
||||
return file.Exists ? file : null;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region MacroModel properties
|
||||
|
||||
// updates the model properties values according to the attributes
|
||||
private static void UpdateMacroModelProperties(MacroModel model, Hashtable attributes)
|
||||
private static void UpdateMacroModelProperties(MacroModel model, IDictionary<string, object> macroParams)
|
||||
{
|
||||
foreach (var prop in model.Properties)
|
||||
{
|
||||
var key = prop.Key.ToLowerInvariant();
|
||||
prop.Value = attributes.ContainsKey(key)
|
||||
? attributes[key]?.ToString() ?? string.Empty
|
||||
prop.Value = macroParams.ContainsKey(key)
|
||||
? macroParams[key]?.ToString() ?? string.Empty
|
||||
: string.Empty;
|
||||
}
|
||||
}
|
||||
|
||||
// generates the model properties according to the attributes
|
||||
public static void GenerateMacroModelPropertiesFromAttributes(MacroModel model, Hashtable attributes)
|
||||
{
|
||||
foreach (string key in attributes.Keys)
|
||||
model.Properties.Add(new MacroPropertyModel(key, attributes[key].ToString()));
|
||||
}
|
||||
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Render/Execute
|
||||
|
||||
// still, this is ugly. The macro should have a Content property
|
||||
// referring to IPublishedContent we're rendering the macro against,
|
||||
// this is all so convoluted ;-(
|
||||
|
||||
public MacroContent Render(MacroModel macro, Hashtable pageElements, int pageId, Hashtable attributes)
|
||||
public MacroContent Render(string macroAlias, IPublishedContent content, IDictionary<string, object> macroParams)
|
||||
{
|
||||
UpdateMacroModelProperties(macro, attributes);
|
||||
return Render(macro, pageElements, pageId);
|
||||
var m = _macroService.GetByAlias(macroAlias);
|
||||
if (m == null)
|
||||
throw new InvalidOperationException("No macro found by alias " + macroAlias);
|
||||
|
||||
var page = new PublishedContentHashtableConverter(content);
|
||||
|
||||
var macro = new MacroModel(m);
|
||||
|
||||
UpdateMacroModelProperties(macro, macroParams);
|
||||
return Render(macro, content, page.Elements);
|
||||
}
|
||||
|
||||
public MacroContent Render(MacroModel macro, Hashtable pageElements, int pageId)
|
||||
private MacroContent Render(MacroModel macro, IPublishedContent content, IDictionary pageElements)
|
||||
{
|
||||
// trigger MacroRendering event so that the model can be manipulated before rendering
|
||||
OnMacroRendering(new MacroRenderingEventArgs(pageElements, pageId));
|
||||
if (content == null) throw new ArgumentNullException(nameof(content));
|
||||
|
||||
var macroInfo = $"Render Macro: {macro.Name}, type: {macro.MacroType}, cache: {macro.CacheDuration}";
|
||||
using (_plogger.DebugDuration<MacroRenderer>(macroInfo, "Rendered Macro."))
|
||||
@@ -244,7 +220,7 @@ namespace Umbraco.Web.Macros
|
||||
foreach (var prop in macro.Properties)
|
||||
prop.Value = ParseAttribute(pageElements, prop.Value);
|
||||
|
||||
macro.CacheIdentifier = GetContentCacheIdentifier(macro, pageId);
|
||||
macro.CacheIdentifier = GetContentCacheIdentifier(macro, content.Id);
|
||||
|
||||
// get the macro from cache if it is there
|
||||
var macroContent = GetMacroContentFromCache(macro);
|
||||
@@ -258,7 +234,7 @@ namespace Umbraco.Web.Macros
|
||||
// this will take care of errors
|
||||
// it may throw, if we actually want to throw, so better not
|
||||
// catch anything here and let the exception be thrown
|
||||
var attempt = ExecuteMacroOfType(macro);
|
||||
var attempt = ExecuteMacroOfType(macro, content);
|
||||
|
||||
// by convention ExecuteMacroByType must either throw or return a result
|
||||
// just check to avoid internal errors
|
||||
@@ -300,8 +276,6 @@ namespace Umbraco.Web.Macros
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Exceptions.Add(e);
|
||||
|
||||
_plogger.Warn<MacroRenderer>(e, "Failed {MsgIn}", msgIn);
|
||||
|
||||
var macroErrorEventArgs = new MacroErrorEventArgs
|
||||
@@ -310,11 +284,9 @@ namespace Umbraco.Web.Macros
|
||||
Alias = macro.Alias,
|
||||
MacroSource = macro.MacroSource,
|
||||
Exception = e,
|
||||
Behaviour = Current.Configs.Settings().Content.MacroErrorBehaviour
|
||||
Behaviour = _contentSection.MacroErrorBehaviour
|
||||
};
|
||||
|
||||
OnError(macroErrorEventArgs);
|
||||
|
||||
switch (macroErrorEventArgs.Behaviour)
|
||||
{
|
||||
case MacroErrorBehaviour.Inline:
|
||||
@@ -341,16 +313,17 @@ namespace Umbraco.Web.Macros
|
||||
/// <remarks>Returns an attempt that is successful if the macro ran successfully. If the macro failed
|
||||
/// to run properly, the attempt fails, though it may contain a content. But for instance that content
|
||||
/// should not be cached. In that case the attempt may also contain an exception.</remarks>
|
||||
private Attempt<MacroContent> ExecuteMacroOfType(MacroModel model)
|
||||
private Attempt<MacroContent> ExecuteMacroOfType(MacroModel model, IPublishedContent content)
|
||||
{
|
||||
if (model == null) throw new ArgumentNullException(nameof(model));
|
||||
|
||||
// ensure that we are running against a published node (ie available in XML)
|
||||
// that may not be the case if the macro is embedded in a RTE of an unpublished document
|
||||
|
||||
if (UmbracoContext.Current.PublishedRequest == null
|
||||
|| UmbracoContext.Current.PublishedRequest.HasPublishedContent == false)
|
||||
return Attempt.Fail(new MacroContent { Text = "[macro]" });
|
||||
if (content == null)
|
||||
return Attempt.Fail(new MacroContent { Text = "[macro failed (no content)]" });
|
||||
|
||||
var textService = Current.Services.TextService;
|
||||
var textService = _textService;
|
||||
|
||||
switch (model.MacroType)
|
||||
{
|
||||
@@ -358,7 +331,7 @@ namespace Umbraco.Web.Macros
|
||||
return ExecuteMacroWithErrorWrapper(model,
|
||||
$"Executing PartialView: MacroSource=\"{model.MacroSource}\".",
|
||||
"Executed PartialView.",
|
||||
() => ExecutePartialView(model),
|
||||
() => ExecutePartialView(model, content),
|
||||
() => textService.Localize("errors/macroErrorLoadingPartialView", new[] { model.MacroSource }));
|
||||
|
||||
default:
|
||||
@@ -370,21 +343,6 @@ namespace Umbraco.Web.Macros
|
||||
}
|
||||
}
|
||||
|
||||
// raised when a macro triggers an error
|
||||
public static event TypedEventHandler<MacroRenderer, MacroErrorEventArgs> Error;
|
||||
|
||||
protected void OnError(MacroErrorEventArgs e)
|
||||
{
|
||||
Error?.Invoke(this, e);
|
||||
}
|
||||
|
||||
// raised before the macro renders, allowing devs to modify it
|
||||
public static event TypedEventHandler<MacroRenderer, MacroRenderingEventArgs> MacroRendering;
|
||||
|
||||
protected void OnMacroRendering(MacroRenderingEventArgs e)
|
||||
{
|
||||
MacroRendering?.Invoke(this, e);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
@@ -394,10 +352,9 @@ namespace Umbraco.Web.Macros
|
||||
/// Renders a PartialView Macro.
|
||||
/// </summary>
|
||||
/// <returns>The text output of the macro execution.</returns>
|
||||
private static MacroContent ExecutePartialView(MacroModel macro)
|
||||
private MacroContent ExecutePartialView(MacroModel macro, IPublishedContent content)
|
||||
{
|
||||
var engine = new PartialViewMacroEngine();
|
||||
var content = UmbracoContext.Current.PublishedRequest.PublishedContent;
|
||||
return engine.Execute(macro, content);
|
||||
}
|
||||
|
||||
@@ -407,8 +364,9 @@ namespace Umbraco.Web.Macros
|
||||
|
||||
// parses attribute value looking for [@requestKey], [%sessionKey], [#pageElement], [$recursiveValue]
|
||||
// supports fallbacks eg "[@requestKey],[%sessionKey],1234"
|
||||
public static string ParseAttribute(IDictionary pageElements, string attributeValue)
|
||||
private string ParseAttribute(IDictionary pageElements, string attributeValue)
|
||||
{
|
||||
if (pageElements == null) throw new ArgumentNullException(nameof(pageElements));
|
||||
|
||||
// check for potential querystring/cookie variables
|
||||
attributeValue = attributeValue.Trim();
|
||||
@@ -431,7 +389,7 @@ namespace Umbraco.Web.Macros
|
||||
return attributeValue;
|
||||
}
|
||||
|
||||
var context = HttpContext.Current;
|
||||
var context = _umbracoContextAccessor.UmbracoContext.HttpContext;
|
||||
|
||||
foreach (var token in tokens)
|
||||
{
|
||||
@@ -458,11 +416,9 @@ namespace Umbraco.Web.Macros
|
||||
attributeValue = context?.Request.GetCookieValue(name);
|
||||
break;
|
||||
case '#':
|
||||
if (pageElements == null) pageElements = GetPageElements();
|
||||
attributeValue = pageElements[name]?.ToString();
|
||||
break;
|
||||
case '$':
|
||||
if (pageElements == null) pageElements = GetPageElements();
|
||||
attributeValue = pageElements[name]?.ToString();
|
||||
if (string.IsNullOrEmpty(attributeValue))
|
||||
attributeValue = ParseAttributeOnParents(pageElements, name);
|
||||
@@ -477,12 +433,13 @@ namespace Umbraco.Web.Macros
|
||||
return attributeValue;
|
||||
}
|
||||
|
||||
private static string ParseAttributeOnParents(IDictionary pageElements, string name)
|
||||
private string ParseAttributeOnParents(IDictionary pageElements, string name)
|
||||
{
|
||||
if (pageElements == null) throw new ArgumentNullException(nameof(pageElements));
|
||||
// this was, and still is, an ugly piece of nonsense
|
||||
|
||||
var value = string.Empty;
|
||||
var cache = UmbracoContext.Current.ContentCache; // should be injected
|
||||
var cache = _umbracoContextAccessor.UmbracoContext.ContentCache;
|
||||
|
||||
var splitpath = (string[])pageElements["splitpath"];
|
||||
for (var i = splitpath.Length - 1; i > 0; i--) // at 0 we have root (-1)
|
||||
@@ -495,195 +452,9 @@ namespace Umbraco.Web.Macros
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
private static IDictionary GetPageElements()
|
||||
{
|
||||
IDictionary pageElements = null;
|
||||
if (HttpContext.Current.Items["pageElements"] != null)
|
||||
pageElements = (IDictionary)HttpContext.Current.Items["pageElements"];
|
||||
return pageElements;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region RTE macros
|
||||
|
||||
public static string RenderMacroStartTag(Hashtable attributes, int pageId, Guid versionId)
|
||||
{
|
||||
var div = "<div ";
|
||||
|
||||
var ide = attributes.GetEnumerator();
|
||||
while (ide.MoveNext())
|
||||
{
|
||||
div += $"umb_{ide.Key}=\"{EncodeMacroAttribute((ide.Value ?? String.Empty).ToString())}\" ";
|
||||
}
|
||||
|
||||
div += $"ismacro=\"true\" onresizestart=\"return false;\" umbVersionId=\"{versionId}\" umbPageid=\"{pageId}\""
|
||||
+ " title=\"This is rendered content from macro\" class=\"umbMacroHolder\"><!-- startUmbMacro -->";
|
||||
|
||||
return div;
|
||||
}
|
||||
|
||||
private static string EncodeMacroAttribute(string attributeContents)
|
||||
{
|
||||
// replace line breaks
|
||||
attributeContents = attributeContents.Replace("\n", "\\n").Replace("\r", "\\r");
|
||||
|
||||
// replace quotes
|
||||
attributeContents = attributeContents.Replace("\"", """);
|
||||
|
||||
// replace tag start/ends
|
||||
attributeContents = attributeContents.Replace("<", "<").Replace(">", ">");
|
||||
|
||||
return attributeContents;
|
||||
}
|
||||
|
||||
public static string RenderMacroEndTag()
|
||||
{
|
||||
return "<!-- endUmbMacro --></div>";
|
||||
}
|
||||
|
||||
private static readonly Regex HrefRegex = new Regex("href=\"([^\"]*)\"",
|
||||
RegexOptions.Compiled | RegexOptions.IgnoreCase | RegexOptions.IgnorePatternWhitespace);
|
||||
|
||||
public static string GetRenderedMacro(int macroId, Hashtable elements, Hashtable attributes, int pageId, IMacroService macroService, IProfilingLogger plogger)
|
||||
{
|
||||
var m = macroService.GetById(macroId);
|
||||
if (m == null) return string.Empty;
|
||||
var model = new MacroModel(m);
|
||||
|
||||
// get as text, will render the control if any
|
||||
var renderer = new MacroRenderer(plogger);
|
||||
var macroContent = renderer.Render(model, elements, pageId);
|
||||
var text = macroContent.GetAsText();
|
||||
|
||||
// remove hrefs
|
||||
text = HrefRegex.Replace(text, match => "href=\"javascript:void(0)\"");
|
||||
|
||||
return text;
|
||||
}
|
||||
|
||||
public static string MacroContentByHttp(int pageId, Guid pageVersion, Hashtable attributes, IMacroService macroService)
|
||||
{
|
||||
// though... we only support FullTrust now?
|
||||
if (SystemUtilities.GetCurrentTrustLevel() != AspNetHostingPermissionLevel.Unrestricted)
|
||||
return "<span style='color: red'>Cannot render macro content in the rich text editor when the application is running in a Partial Trust environment</span>";
|
||||
|
||||
var tempAlias = attributes["macroalias"]?.ToString() ?? attributes["macroAlias"].ToString();
|
||||
|
||||
var m = macroService.GetByAlias(tempAlias);
|
||||
if (m == null) return string.Empty;
|
||||
var macro = new MacroModel(m);
|
||||
if (macro.RenderInEditor == false)
|
||||
return ShowNoMacroContent(macro);
|
||||
|
||||
var querystring = $"umbPageId={pageId}&umbVersionId={pageVersion}";
|
||||
var ide = attributes.GetEnumerator();
|
||||
while (ide.MoveNext())
|
||||
querystring += $"&umb_{ide.Key}={HttpContext.Current.Server.UrlEncode((ide.Value ?? String.Empty).ToString())}";
|
||||
|
||||
// create a new 'HttpWebRequest' object to the mentioned URL.
|
||||
var useSsl = Current.Configs.Global().UseHttps;
|
||||
var protocol = useSsl ? "https" : "http";
|
||||
var currentRequest = HttpContext.Current.Request;
|
||||
var serverVars = currentRequest.ServerVariables;
|
||||
var umbracoDir = IOHelper.ResolveUrl(SystemDirectories.Umbraco);
|
||||
var url = $"{protocol}://{serverVars["SERVER_NAME"]}:{serverVars["SERVER_PORT"]}{umbracoDir}/macroResultWrapper.aspx?{querystring}";
|
||||
|
||||
var myHttpWebRequest = (HttpWebRequest)WebRequest.Create(url);
|
||||
|
||||
// allows for validation of SSL conversations (to bypass SSL errors in debug mode!)
|
||||
ServicePointManager.ServerCertificateValidationCallback += ValidateRemoteCertificate;
|
||||
|
||||
// propagate the user's context
|
||||
// TODO: this is the worst thing ever.
|
||||
// also will not work if people decide to put their own custom auth system in place.
|
||||
var inCookie = currentRequest.Cookies[Current.Configs.Settings().Security.AuthCookieName];
|
||||
if (inCookie == null) throw new NullReferenceException("No auth cookie found");
|
||||
var cookie = new Cookie(inCookie.Name, inCookie.Value, inCookie.Path, serverVars["SERVER_NAME"]);
|
||||
myHttpWebRequest.CookieContainer = new CookieContainer();
|
||||
myHttpWebRequest.CookieContainer.Add(cookie);
|
||||
|
||||
// assign the response object of 'HttpWebRequest' to a 'HttpWebResponse' variable.
|
||||
HttpWebResponse myHttpWebResponse = null;
|
||||
var text = string.Empty;
|
||||
try
|
||||
{
|
||||
myHttpWebResponse = (HttpWebResponse)myHttpWebRequest.GetResponse();
|
||||
if (myHttpWebResponse.StatusCode == HttpStatusCode.OK)
|
||||
{
|
||||
var streamResponse = myHttpWebResponse.GetResponseStream();
|
||||
if (streamResponse == null)
|
||||
throw new Exception("Internal error, no response stream.");
|
||||
var streamRead = new StreamReader(streamResponse);
|
||||
var readBuff = new char[256];
|
||||
var count = streamRead.Read(readBuff, 0, 256);
|
||||
while (count > 0)
|
||||
{
|
||||
var outputData = new string(readBuff, 0, count);
|
||||
text += outputData;
|
||||
count = streamRead.Read(readBuff, 0, 256);
|
||||
}
|
||||
|
||||
streamResponse.Close();
|
||||
streamRead.Close();
|
||||
|
||||
// find the content of a form
|
||||
const string grabStart = "<!-- grab start -->";
|
||||
const string grabEnd = "<!-- grab end -->";
|
||||
|
||||
var grabStartPos = text.InvariantIndexOf(grabStart) + grabStart.Length;
|
||||
var grabEndPos = text.InvariantIndexOf(grabEnd) - grabStartPos;
|
||||
text = text.Substring(grabStartPos, grabEndPos);
|
||||
}
|
||||
else
|
||||
{
|
||||
text = ShowNoMacroContent(macro);
|
||||
}
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
text = ShowNoMacroContent(macro);
|
||||
}
|
||||
finally
|
||||
{
|
||||
// release the HttpWebResponse Resource.
|
||||
myHttpWebResponse?.Close();
|
||||
}
|
||||
|
||||
return text.Replace("\n", string.Empty).Replace("\r", string.Empty);
|
||||
}
|
||||
|
||||
private static string ShowNoMacroContent(MacroModel model)
|
||||
{
|
||||
var name = HttpUtility.HtmlEncode(model.Name); // safe
|
||||
return $"<span style=\"color: green\"><strong>{name}</strong><br />No macro content available for WYSIWYG editing</span>";
|
||||
}
|
||||
|
||||
private static bool ValidateRemoteCertificate(
|
||||
object sender,
|
||||
X509Certificate certificate,
|
||||
X509Chain chain,
|
||||
SslPolicyErrors policyErrors
|
||||
)
|
||||
{
|
||||
// allow any old dodgy certificate in debug mode
|
||||
return GlobalSettings.DebugMode || policyErrors == SslPolicyErrors.None;
|
||||
}
|
||||
|
||||
|
||||
#endregion
|
||||
|
||||
}
|
||||
|
||||
public class MacroRenderingEventArgs : EventArgs
|
||||
{
|
||||
public MacroRenderingEventArgs(Hashtable pageElements, int pageId)
|
||||
{
|
||||
PageElements = pageElements;
|
||||
PageId = pageId;
|
||||
}
|
||||
|
||||
public int PageId { get; }
|
||||
|
||||
public Hashtable PageElements { get; }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -30,14 +30,13 @@ namespace Umbraco.Web.Macros
|
||||
/// </remarks>
|
||||
internal PublishedContentHashtableConverter(PublishedRequest frequest)
|
||||
{
|
||||
|
||||
if (!frequest.HasPublishedContent)
|
||||
throw new ArgumentException("Document request has no node.", "frequest");
|
||||
throw new ArgumentException("Document request has no node.", nameof(frequest));
|
||||
|
||||
PopulatePageData(frequest.PublishedContent.Id,
|
||||
frequest.PublishedContent.Name, frequest.PublishedContent.ContentType.Id, frequest.PublishedContent.ContentType.Alias,
|
||||
frequest.PublishedContent.WriterName, frequest.PublishedContent.CreatorName, frequest.PublishedContent.CreateDate, frequest.PublishedContent.UpdateDate,
|
||||
frequest.PublishedContent.Path, frequest.PublishedContent.Parent == null ? -1 : frequest.PublishedContent.Parent.Id);
|
||||
frequest.PublishedContent.Path, frequest.PublishedContent.Parent?.Id ?? -1);
|
||||
|
||||
if (frequest.HasTemplate)
|
||||
{
|
||||
@@ -54,12 +53,12 @@ namespace Umbraco.Web.Macros
|
||||
/// <param name="doc"></param>
|
||||
internal PublishedContentHashtableConverter(IPublishedContent doc)
|
||||
{
|
||||
if (doc == null) throw new ArgumentNullException("doc");
|
||||
if (doc == null) throw new ArgumentNullException(nameof(doc));
|
||||
|
||||
PopulatePageData(doc.Id,
|
||||
doc.Name, doc.ContentType.Id, doc.ContentType.Alias,
|
||||
doc.WriterName, doc.CreatorName, doc.CreateDate, doc.UpdateDate,
|
||||
doc.Path, doc.Parent == null ? -1 : doc.Parent.Id);
|
||||
doc.Path, doc.Parent?.Id ?? -1);
|
||||
|
||||
if (doc.TemplateId.HasValue)
|
||||
{
|
||||
@@ -132,6 +131,7 @@ namespace Umbraco.Web.Macros
|
||||
/// </summary>
|
||||
public Hashtable Elements { get; } = new Hashtable();
|
||||
|
||||
|
||||
#region PublishedContent
|
||||
|
||||
private class PagePublishedProperty : PublishedPropertyBase
|
||||
|
||||
@@ -9,12 +9,14 @@ namespace Umbraco.Web.Models.Mapping
|
||||
internal class RedirectUrlMapperProfile : Profile
|
||||
{
|
||||
|
||||
public RedirectUrlMapperProfile()
|
||||
public RedirectUrlMapperProfile(IUmbracoContextAccessor umbracoContextAccessor)
|
||||
{
|
||||
CreateMap<IRedirectUrl, ContentRedirectUrl>()
|
||||
.ForMember(x => x.OriginalUrl, expression => expression.MapFrom(item => Current.UmbracoContext.UrlProvider.GetUrlFromRoute(item.ContentId, item.Url, item.Culture)))
|
||||
.ForMember(x => x.DestinationUrl, expression => expression.MapFrom(item => item.ContentId > 0 ? new UmbracoHelper(Current.UmbracoContext, Current.Services).Url(item.ContentId, item.Culture) : "#"))
|
||||
.ForMember(x => x.DestinationUrl, expression => expression.MapFrom(item => item.ContentId > 0 ? GetUrl(umbracoContextAccessor, item) : "#"))
|
||||
.ForMember(x => x.RedirectId, expression => expression.MapFrom(item => item.Key));
|
||||
}
|
||||
|
||||
private static string GetUrl(IUmbracoContextAccessor umbracoContextAccessor, IRedirectUrl item) => umbracoContextAccessor?.UmbracoContext?.UrlProvider?.GetUrl(item.Id, item.Culture);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -22,10 +22,10 @@ namespace Umbraco.Web.Models
|
||||
MacroId = macroId;
|
||||
}
|
||||
|
||||
public IPublishedContent Content { get; private set; }
|
||||
public string MacroName { get; private set; }
|
||||
public string MacroAlias { get; private set; }
|
||||
public int MacroId { get; private set; }
|
||||
public IDictionary<string, object> MacroParameters { get; private set; }
|
||||
public IPublishedContent Content { get; }
|
||||
public string MacroName { get; }
|
||||
public string MacroAlias { get; }
|
||||
public int MacroId { get; }
|
||||
public IDictionary<string, object> MacroParameters { get; }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -77,8 +77,7 @@ namespace Umbraco.Web.Mvc
|
||||
/// <summary>
|
||||
/// Exposes an UmbracoHelper
|
||||
/// </summary>
|
||||
protected UmbracoHelper Umbraco => _helper
|
||||
?? (_helper = new UmbracoHelper(Current.UmbracoContext, Current.Services));
|
||||
protected UmbracoHelper Umbraco => _helper ?? (_helper = Current.Factory.GetInstance<UmbracoHelper>());
|
||||
|
||||
public override void OnActionExecuted(ActionExecutedContext filterContext)
|
||||
{
|
||||
|
||||
@@ -1,10 +1,11 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.Generic;
|
||||
using System.Web;
|
||||
using System.Web.Mvc;
|
||||
using AuthorizeAttribute = System.Web.Mvc.AuthorizeAttribute;
|
||||
using Umbraco.Core;
|
||||
using Umbraco.Web.Composing;
|
||||
using Umbraco.Web.Security;
|
||||
using Umbraco.Core.Composing;
|
||||
using Current = Umbraco.Web.Composing.Current;
|
||||
|
||||
namespace Umbraco.Web.Mvc
|
||||
{
|
||||
@@ -14,35 +15,6 @@ namespace Umbraco.Web.Mvc
|
||||
/// </summary>
|
||||
public sealed class MemberAuthorizeAttribute : AuthorizeAttribute
|
||||
{
|
||||
// see note in HttpInstallAuthorizeAttribute
|
||||
private readonly UmbracoContext _umbracoContext;
|
||||
|
||||
private UmbracoContext UmbracoContext => _umbracoContext ?? Current.UmbracoContext;
|
||||
|
||||
/// <summary>
|
||||
/// THIS SHOULD BE ONLY USED FOR UNIT TESTS
|
||||
/// </summary>
|
||||
/// <param name="umbracoContext"></param>
|
||||
public MemberAuthorizeAttribute(UmbracoContext umbracoContext)
|
||||
{
|
||||
if (umbracoContext == null) throw new ArgumentNullException("umbracoContext");
|
||||
_umbracoContext = umbracoContext;
|
||||
}
|
||||
|
||||
public MemberAuthorizeAttribute()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Flag for whether to allow all site visitors or just authenticated members
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This is the same as applying the [AllowAnonymous] attribute
|
||||
/// </remarks>
|
||||
[Obsolete("Use [AllowAnonymous] instead")]
|
||||
public bool AllowAll { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Comma delimited list of allowed member types
|
||||
/// </summary>
|
||||
@@ -70,17 +42,15 @@ namespace Umbraco.Web.Mvc
|
||||
var members = new List<int>();
|
||||
foreach (var s in AllowMembers.Split(','))
|
||||
{
|
||||
int id;
|
||||
if (int.TryParse(s, out id))
|
||||
if (int.TryParse(s, out var id))
|
||||
{
|
||||
members.Add(id);
|
||||
}
|
||||
}
|
||||
|
||||
return UmbracoContext.Security.IsMemberAuthorized(AllowAll,
|
||||
AllowType.Split(','),
|
||||
AllowGroup.Split(','),
|
||||
members);
|
||||
var helper = Current.Factory.GetInstance<MembershipHelper>();
|
||||
return helper.IsMemberAuthorized(AllowType.Split(','), AllowGroup.Split(','), members);
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -20,8 +20,6 @@ namespace Umbraco.Web.Mvc
|
||||
private static readonly ConcurrentDictionary<Type, PluginControllerMetadata> MetadataStorage
|
||||
= new ConcurrentDictionary<Type, PluginControllerMetadata>();
|
||||
|
||||
private UmbracoHelper _umbracoHelper;
|
||||
|
||||
// for debugging purposes
|
||||
internal Guid InstanceId { get; } = Guid.NewGuid();
|
||||
|
||||
@@ -70,18 +68,7 @@ namespace Umbraco.Web.Mvc
|
||||
/// <summary>
|
||||
/// Gets the Umbraco helper.
|
||||
/// </summary>
|
||||
public UmbracoHelper Umbraco
|
||||
{
|
||||
get
|
||||
{
|
||||
return _umbracoHelper
|
||||
?? (_umbracoHelper = new UmbracoHelper(UmbracoContext, Services));
|
||||
}
|
||||
internal set // tests
|
||||
{
|
||||
_umbracoHelper = value;
|
||||
}
|
||||
}
|
||||
public UmbracoHelper Umbraco { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets metadata for this instance.
|
||||
@@ -95,12 +82,13 @@ namespace Umbraco.Web.Mvc
|
||||
Current.Factory.GetInstance<ServiceContext>(),
|
||||
Current.Factory.GetInstance<AppCaches>(),
|
||||
Current.Factory.GetInstance<ILogger>(),
|
||||
Current.Factory.GetInstance<IProfilingLogger>()
|
||||
Current.Factory.GetInstance<IProfilingLogger>(),
|
||||
Current.Factory.GetInstance<UmbracoHelper>()
|
||||
)
|
||||
{
|
||||
}
|
||||
|
||||
protected PluginController(UmbracoContext umbracoContext, IUmbracoDatabaseFactory databaseFactory, ServiceContext services, AppCaches appCaches, ILogger logger, IProfilingLogger profilingLogger)
|
||||
protected PluginController(UmbracoContext umbracoContext, IUmbracoDatabaseFactory databaseFactory, ServiceContext services, AppCaches appCaches, ILogger logger, IProfilingLogger profilingLogger, UmbracoHelper umbracoHelper)
|
||||
{
|
||||
UmbracoContext = umbracoContext;
|
||||
DatabaseFactory = databaseFactory;
|
||||
@@ -108,6 +96,7 @@ namespace Umbraco.Web.Mvc
|
||||
AppCaches = appCaches;
|
||||
Logger = logger;
|
||||
ProfilingLogger = profilingLogger;
|
||||
Umbraco = umbracoHelper;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -23,8 +23,8 @@ namespace Umbraco.Web.Mvc
|
||||
ActionInvoker = new RenderActionInvoker();
|
||||
}
|
||||
|
||||
public RenderMvcController(IGlobalSettings globalSettings, UmbracoContext umbracoContext, ServiceContext services, AppCaches appCaches, ILogger logger, IProfilingLogger profilingLogger)
|
||||
: base(globalSettings, umbracoContext, services, appCaches, logger, profilingLogger)
|
||||
public RenderMvcController(IGlobalSettings globalSettings, UmbracoContext umbracoContext, ServiceContext services, AppCaches appCaches, IProfilingLogger profilingLogger, UmbracoHelper umbracoHelper)
|
||||
: base(globalSettings, umbracoContext, services, appCaches, profilingLogger, umbracoHelper)
|
||||
{
|
||||
ActionInvoker = new RenderActionInvoker();
|
||||
}
|
||||
@@ -32,7 +32,7 @@ namespace Umbraco.Web.Mvc
|
||||
/// <summary>
|
||||
/// Gets the Umbraco context.
|
||||
/// </summary>
|
||||
public override UmbracoContext UmbracoContext => PublishedRequest.UmbracoContext;
|
||||
public override UmbracoContext UmbracoContext => PublishedRequest.UmbracoContext; //TODO: Why?
|
||||
|
||||
/// <summary>
|
||||
/// Gets the current content item.
|
||||
|
||||
@@ -19,8 +19,8 @@ namespace Umbraco.Web.Mvc
|
||||
protected SurfaceController()
|
||||
{ }
|
||||
|
||||
protected SurfaceController(UmbracoContext umbracoContext, IUmbracoDatabaseFactory databaseFactory, ServiceContext services, AppCaches appCaches, ILogger logger, IProfilingLogger profilingLogger)
|
||||
: base(umbracoContext, databaseFactory, services, appCaches, logger, profilingLogger)
|
||||
protected SurfaceController(UmbracoContext umbracoContext, IUmbracoDatabaseFactory databaseFactory, ServiceContext services, AppCaches appCaches, ILogger logger, IProfilingLogger profilingLogger, UmbracoHelper umbracoHelper)
|
||||
: base(umbracoContext, databaseFactory, services, appCaches, logger, profilingLogger, umbracoHelper)
|
||||
{ }
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -18,10 +18,12 @@ namespace Umbraco.Web.Mvc
|
||||
public abstract class UmbracoAuthorizedController : UmbracoController
|
||||
{
|
||||
protected UmbracoAuthorizedController()
|
||||
{ }
|
||||
{
|
||||
}
|
||||
|
||||
protected UmbracoAuthorizedController(IGlobalSettings globalSettings, UmbracoContext umbracoContext, ServiceContext services, AppCaches appCaches, ILogger logger, IProfilingLogger profilingLogger)
|
||||
: base(globalSettings, umbracoContext, services, appCaches, logger, profilingLogger)
|
||||
{ }
|
||||
protected UmbracoAuthorizedController(IGlobalSettings globalSettings, UmbracoContext umbracoContext, ServiceContext services, AppCaches appCaches, IProfilingLogger profilingLogger, UmbracoHelper umbracoHelper)
|
||||
: base(globalSettings, umbracoContext, services, appCaches, profilingLogger, umbracoHelper)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,15 +17,13 @@ namespace Umbraco.Web.Mvc
|
||||
/// </summary>
|
||||
public abstract class UmbracoController : Controller
|
||||
{
|
||||
private UmbracoHelper _umbracoHelper;
|
||||
|
||||
// for debugging purposes
|
||||
internal Guid InstanceId { get; } = Guid.NewGuid();
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the Umbraco context.
|
||||
/// </summary>
|
||||
public virtual IGlobalSettings GlobalSettings { get; set; }
|
||||
public IGlobalSettings GlobalSettings { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the Umbraco context.
|
||||
@@ -62,8 +60,7 @@ namespace Umbraco.Web.Mvc
|
||||
/// <summary>
|
||||
/// Gets the Umbraco helper.
|
||||
/// </summary>
|
||||
public UmbracoHelper Umbraco => _umbracoHelper
|
||||
?? (_umbracoHelper = new UmbracoHelper(UmbracoContext, Services));
|
||||
public UmbracoHelper Umbraco { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the web security helper.
|
||||
@@ -76,20 +73,21 @@ namespace Umbraco.Web.Mvc
|
||||
Current.Factory.GetInstance<UmbracoContext>(),
|
||||
Current.Factory.GetInstance<ServiceContext>(),
|
||||
Current.Factory.GetInstance<AppCaches>(),
|
||||
Current.Factory.GetInstance<ILogger>(),
|
||||
Current.Factory.GetInstance<IProfilingLogger>()
|
||||
Current.Factory.GetInstance<IProfilingLogger>(),
|
||||
Current.Factory.GetInstance<UmbracoHelper>()
|
||||
)
|
||||
{
|
||||
}
|
||||
|
||||
protected UmbracoController(IGlobalSettings globalSettings, UmbracoContext umbracoContext, ServiceContext services, AppCaches appCaches, ILogger logger, IProfilingLogger profilingLogger)
|
||||
protected UmbracoController(IGlobalSettings globalSettings, UmbracoContext umbracoContext, ServiceContext services, AppCaches appCaches, IProfilingLogger profilingLogger, UmbracoHelper umbracoHelper)
|
||||
{
|
||||
GlobalSettings = globalSettings;
|
||||
UmbracoContext = umbracoContext;
|
||||
Services = services;
|
||||
AppCaches = appCaches;
|
||||
Logger = logger;
|
||||
Logger = profilingLogger;
|
||||
ProfilingLogger = profilingLogger;
|
||||
Umbraco = umbracoHelper;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,6 +7,7 @@ using Umbraco.Core;
|
||||
using Umbraco.Core.Cache;
|
||||
using Umbraco.Core.Composing;
|
||||
using Umbraco.Core.Configuration;
|
||||
using Umbraco.Core.Dictionary;
|
||||
using Umbraco.Core.IO;
|
||||
using Umbraco.Core.Models.PublishedContent;
|
||||
using Umbraco.Core.Services;
|
||||
@@ -84,7 +85,7 @@ namespace Umbraco.Web.Mvc
|
||||
/// <summary>
|
||||
/// Gets the Umbraco helper.
|
||||
/// </summary>
|
||||
public virtual UmbracoHelper Umbraco
|
||||
public UmbracoHelper Umbraco
|
||||
{
|
||||
get
|
||||
{
|
||||
@@ -94,9 +95,12 @@ namespace Umbraco.Web.Mvc
|
||||
var content = model as IPublishedContent;
|
||||
if (content == null && model is IContentModel)
|
||||
content = ((IContentModel) model).Content;
|
||||
_helper = content == null
|
||||
? new UmbracoHelper(UmbracoContext, Services)
|
||||
: new UmbracoHelper(UmbracoContext, Services, content);
|
||||
|
||||
_helper = Current.UmbracoHelper;
|
||||
|
||||
if (content != null)
|
||||
_helper.AssignedContentItem = content;
|
||||
|
||||
return _helper;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,12 +20,12 @@ namespace Umbraco.Web.PropertyEditors.ValueConverters
|
||||
public class MacroContainerValueConverter : PropertyValueConverterBase
|
||||
{
|
||||
private readonly IUmbracoContextAccessor _umbracoContextAccessor;
|
||||
private readonly ServiceContext _services;
|
||||
private readonly IMacroRenderer _macroRenderer;
|
||||
|
||||
public MacroContainerValueConverter(IUmbracoContextAccessor umbracoContextAccessor, ServiceContext services)
|
||||
public MacroContainerValueConverter(IUmbracoContextAccessor umbracoContextAccessor, IMacroRenderer macroRenderer)
|
||||
{
|
||||
_umbracoContextAccessor = umbracoContextAccessor ?? throw new ArgumentNullException(nameof(umbracoContextAccessor));
|
||||
_services = services ?? throw new ArgumentNullException(nameof(services));
|
||||
_macroRenderer = macroRenderer ?? throw new ArgumentNullException(nameof(macroRenderer));
|
||||
}
|
||||
|
||||
public override bool IsConverter(PublishedPropertyType propertyType)
|
||||
@@ -48,14 +48,14 @@ namespace Umbraco.Web.PropertyEditors.ValueConverters
|
||||
{
|
||||
var sb = new StringBuilder();
|
||||
|
||||
var umbracoHelper = new UmbracoHelper(umbracoContext, _services);
|
||||
MacroTagParser.ParseMacros(
|
||||
source,
|
||||
//callback for when text block is found
|
||||
textBlock => sb.Append(textBlock),
|
||||
//callback for when macro syntax is found
|
||||
(macroAlias, macroAttributes) => sb.Append(umbracoHelper.RenderMacro(
|
||||
(macroAlias, macroAttributes) => sb.Append(_macroRenderer.Render(
|
||||
macroAlias,
|
||||
umbracoContext.PublishedRequest?.PublishedContent,
|
||||
//needs to be explicitly casted to Dictionary<string, object>
|
||||
macroAttributes.ConvertTo(x => (string)x, x => x)).ToString()));
|
||||
|
||||
|
||||
@@ -21,7 +21,7 @@ namespace Umbraco.Web.PropertyEditors.ValueConverters
|
||||
public class RteMacroRenderingValueConverter : TinyMceValueConverter
|
||||
{
|
||||
private readonly IUmbracoContextAccessor _umbracoContextAccessor;
|
||||
private readonly ServiceContext _services;
|
||||
private readonly IMacroRenderer _macroRenderer;
|
||||
|
||||
public override PropertyCacheLevel GetPropertyCacheLevel(PublishedPropertyType propertyType)
|
||||
{
|
||||
@@ -30,10 +30,10 @@ namespace Umbraco.Web.PropertyEditors.ValueConverters
|
||||
return PropertyCacheLevel.Snapshot;
|
||||
}
|
||||
|
||||
public RteMacroRenderingValueConverter(IUmbracoContextAccessor umbracoContextAccessor, ServiceContext services)
|
||||
public RteMacroRenderingValueConverter(IUmbracoContextAccessor umbracoContextAccessor, IMacroRenderer macroRenderer)
|
||||
{
|
||||
_umbracoContextAccessor = umbracoContextAccessor;
|
||||
_services = services;
|
||||
_macroRenderer = macroRenderer;
|
||||
}
|
||||
|
||||
// NOT thread-safe over a request because it modifies the
|
||||
@@ -47,14 +47,14 @@ namespace Umbraco.Web.PropertyEditors.ValueConverters
|
||||
{
|
||||
var sb = new StringBuilder();
|
||||
|
||||
var umbracoHelper = new UmbracoHelper(umbracoContext, _services);
|
||||
MacroTagParser.ParseMacros(
|
||||
source,
|
||||
//callback for when text block is found
|
||||
textBlock => sb.Append(textBlock),
|
||||
//callback for when macro syntax is found
|
||||
(macroAlias, macroAttributes) => sb.Append(umbracoHelper.RenderMacro(
|
||||
(macroAlias, macroAttributes) => sb.Append(_macroRenderer.Render(
|
||||
macroAlias,
|
||||
umbracoContext.PublishedRequest?.PublishedContent,
|
||||
//needs to be explicitly casted to Dictionary<string, object>
|
||||
macroAttributes.ConvertTo(x => (string)x, x => x)).ToString()));
|
||||
|
||||
|
||||
@@ -279,7 +279,6 @@ namespace Umbraco.Web.Routing
|
||||
/// <summary>
|
||||
/// Resets the template.
|
||||
/// </summary>
|
||||
/// <remarks>The <c>RenderingEngine</c> becomes unknown.</remarks>
|
||||
public void ResetTemplate()
|
||||
{
|
||||
EnsureWriteable();
|
||||
|
||||
@@ -197,9 +197,6 @@ namespace Umbraco.Web.Routing
|
||||
// handlers like default.aspx will want it and most macros currently need it
|
||||
frequest.LegacyContentHashTable = new PublishedContentHashtableConverter(frequest);
|
||||
|
||||
// used by many legacy objects
|
||||
frequest.UmbracoContext.HttpContext.Items["pageElements"] = frequest.LegacyContentHashTable.Elements;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -239,9 +236,7 @@ namespace Umbraco.Web.Routing
|
||||
// assign the legacy page back to the docrequest
|
||||
// handlers like default.aspx will want it and most macros currently need it
|
||||
request.LegacyContentHashTable = new PublishedContentHashtableConverter(request);
|
||||
|
||||
// this is used by many legacy objects
|
||||
request.UmbracoContext.HttpContext.Items["pageElements"] = request.LegacyContentHashTable.Elements;
|
||||
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
@@ -23,6 +23,7 @@ using Umbraco.Web.Dictionary;
|
||||
using Umbraco.Web.Editors;
|
||||
using Umbraco.Web.Features;
|
||||
using Umbraco.Web.HealthCheck;
|
||||
using Umbraco.Web.Macros;
|
||||
using Umbraco.Web.Media.EmbedProviders;
|
||||
using Umbraco.Web.Models.PublishedContent;
|
||||
using Umbraco.Web.Mvc;
|
||||
@@ -33,6 +34,7 @@ using Umbraco.Web.Security;
|
||||
using Umbraco.Web.Security.Providers;
|
||||
using Umbraco.Web.Services;
|
||||
using Umbraco.Web.SignalR;
|
||||
using Umbraco.Web.Templates;
|
||||
using Umbraco.Web.Tour;
|
||||
using Umbraco.Web.Trees;
|
||||
using Umbraco.Web.WebApi;
|
||||
@@ -86,8 +88,19 @@ namespace Umbraco.Web.Runtime
|
||||
// TODO: stop doing this
|
||||
composition.Register(factory => factory.GetInstance<IUmbracoContextAccessor>().UmbracoContext, Lifetime.Request);
|
||||
|
||||
// register the umbraco helper
|
||||
composition.RegisterUnique<UmbracoHelper>();
|
||||
composition.Register<IPublishedContentQuery>(factory =>
|
||||
{
|
||||
var umbCtx = factory.GetInstance<IUmbracoContextAccessor>();
|
||||
return new PublishedContentQuery(umbCtx.UmbracoContext.ContentCache, umbCtx.UmbracoContext.MediaCache, factory.GetInstance<IVariationContextAccessor>());
|
||||
}, Lifetime.Request);
|
||||
composition.Register<ITagQuery, TagQuery>(Lifetime.Request);
|
||||
|
||||
composition.RegisterUnique<ITemplateRenderer, TemplateRenderer>();
|
||||
composition.RegisterUnique<IMacroRenderer, MacroRenderer>();
|
||||
composition.RegisterUnique<IUmbracoComponentRenderer, UmbracoComponentRenderer>();
|
||||
|
||||
// register the umbraco helper - this is Transient! very important!
|
||||
composition.Register<UmbracoHelper>();
|
||||
|
||||
// register distributed cache
|
||||
composition.RegisterUnique(f => new DistributedCache());
|
||||
|
||||
@@ -23,16 +23,19 @@ namespace Umbraco.Web.Search
|
||||
public class UmbracoTreeSearcher
|
||||
{
|
||||
private readonly IExamineManager _examineManager;
|
||||
private readonly UmbracoContext _umbracoContext;
|
||||
private readonly UmbracoHelper _umbracoHelper;
|
||||
private readonly ILocalizationService _languageService;
|
||||
private readonly IEntityService _entityService;
|
||||
|
||||
public UmbracoTreeSearcher(IExamineManager examineManager,
|
||||
UmbracoContext umbracoContext,
|
||||
UmbracoHelper umbracoHelper,
|
||||
ILocalizationService languageService,
|
||||
IEntityService entityService)
|
||||
{
|
||||
_examineManager = examineManager ?? throw new ArgumentNullException(nameof(examineManager));
|
||||
_umbracoContext = umbracoContext;
|
||||
_umbracoHelper = umbracoHelper ?? throw new ArgumentNullException(nameof(umbracoHelper));
|
||||
_languageService = languageService;
|
||||
_entityService = entityService;
|
||||
@@ -61,9 +64,7 @@ namespace Umbraco.Web.Search
|
||||
string type;
|
||||
var indexName = Constants.UmbracoIndexes.InternalIndexName;
|
||||
var fields = new[] { "id", "__NodeId" };
|
||||
|
||||
var umbracoContext = _umbracoHelper.UmbracoContext;
|
||||
|
||||
|
||||
// TODO: WE should try to allow passing in a lucene raw query, however we will still need to do some manual string
|
||||
// manipulation for things like start paths, member types, etc...
|
||||
//if (Examine.ExamineExtensions.TryParseLuceneQuery(query))
|
||||
@@ -86,12 +87,12 @@ namespace Umbraco.Web.Search
|
||||
break;
|
||||
case UmbracoEntityTypes.Media:
|
||||
type = "media";
|
||||
var allMediaStartNodes = umbracoContext.Security.CurrentUser.CalculateMediaStartNodeIds(_entityService);
|
||||
var allMediaStartNodes = _umbracoContext.Security.CurrentUser.CalculateMediaStartNodeIds(_entityService);
|
||||
AppendPath(sb, UmbracoObjectTypes.Media, allMediaStartNodes, searchFrom, _entityService);
|
||||
break;
|
||||
case UmbracoEntityTypes.Document:
|
||||
type = "content";
|
||||
var allContentStartNodes = umbracoContext.Security.CurrentUser.CalculateContentStartNodeIds(_entityService);
|
||||
var allContentStartNodes = _umbracoContext.Security.CurrentUser.CalculateContentStartNodeIds(_entityService);
|
||||
AppendPath(sb, UmbracoObjectTypes.Document, allContentStartNodes, searchFrom, _entityService);
|
||||
break;
|
||||
default:
|
||||
|
||||
@@ -599,20 +599,15 @@ namespace Umbraco.Web.Security
|
||||
/// <summary>
|
||||
/// Returns true or false if the currently logged in member is authorized based on the parameters provided
|
||||
/// </summary>
|
||||
/// <param name="allowAll"></param>
|
||||
/// <param name="allowTypes"></param>
|
||||
/// <param name="allowGroups"></param>
|
||||
/// <param name="allowMembers"></param>
|
||||
/// <returns></returns>
|
||||
public virtual bool IsMemberAuthorized(
|
||||
bool allowAll = false,
|
||||
IEnumerable<string> allowTypes = null,
|
||||
IEnumerable<string> allowGroups = null,
|
||||
IEnumerable<int> allowMembers = null)
|
||||
{
|
||||
if (allowAll)
|
||||
return true;
|
||||
|
||||
if (allowTypes == null)
|
||||
allowTypes = Enumerable.Empty<string>();
|
||||
if (allowGroups == null)
|
||||
|
||||
@@ -33,30 +33,7 @@ namespace Umbraco.Web.Security
|
||||
_userService = userService;
|
||||
_globalSettings = globalSettings;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns true or false if the currently logged in member is authorized based on the parameters provided
|
||||
/// </summary>
|
||||
/// <param name="allowAll"></param>
|
||||
/// <param name="allowTypes"></param>
|
||||
/// <param name="allowGroups"></param>
|
||||
/// <param name="allowMembers"></param>
|
||||
/// <returns></returns>
|
||||
[Obsolete("Use MembershipHelper.IsMemberAuthorized instead")]
|
||||
public bool IsMemberAuthorized(
|
||||
bool allowAll = false,
|
||||
IEnumerable<string> allowTypes = null,
|
||||
IEnumerable<string> allowGroups = null,
|
||||
IEnumerable<int> allowMembers = null)
|
||||
{
|
||||
if (Current.UmbracoContext == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
var helper = Current.Factory.GetInstance<MembershipHelper>();
|
||||
return helper.IsMemberAuthorized(allowAll, allowTypes, allowGroups, allowMembers);
|
||||
}
|
||||
|
||||
|
||||
private IUser _currentUser;
|
||||
|
||||
/// <summary>
|
||||
|
||||
12
src/Umbraco.Web/Templates/ITemplateRenderer.cs
Normal file
12
src/Umbraco.Web/Templates/ITemplateRenderer.cs
Normal file
@@ -0,0 +1,12 @@
|
||||
using System.IO;
|
||||
|
||||
namespace Umbraco.Web.Templates
|
||||
{
|
||||
/// <summary>
|
||||
/// This is used purely for the RenderTemplate functionality in Umbraco
|
||||
/// </summary>
|
||||
public interface ITemplateRenderer
|
||||
{
|
||||
void Render(int pageId, int? altTemplateId, StringWriter writer);
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,5 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Globalization;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
@@ -9,6 +10,7 @@ using Umbraco.Web.Models;
|
||||
using Umbraco.Web.Mvc;
|
||||
using Umbraco.Web.Routing;
|
||||
using Umbraco.Core.Composing;
|
||||
using Umbraco.Core.Configuration.UmbracoSettings;
|
||||
using Umbraco.Core.Services;
|
||||
using Umbraco.Web.Macros;
|
||||
using Current = Umbraco.Web.Composing.Current;
|
||||
@@ -21,92 +23,81 @@ namespace Umbraco.Web.Templates
|
||||
/// <remarks>
|
||||
/// This allows you to render an MVC template based purely off of a node id and an optional alttemplate id as string output.
|
||||
/// </remarks>
|
||||
internal class TemplateRenderer
|
||||
internal class TemplateRenderer : ITemplateRenderer
|
||||
{
|
||||
private readonly UmbracoContext _umbracoContext;
|
||||
private object _oldPageElements;
|
||||
private PublishedRequest _oldPublishedRequest;
|
||||
private object _oldAltTemplate;
|
||||
private readonly IUmbracoContextAccessor _umbracoContextAccessor;
|
||||
private readonly IPublishedRouter _publishedRouter;
|
||||
private readonly IFileService _fileService;
|
||||
private readonly ILocalizationService _languageService;
|
||||
private readonly IWebRoutingSection _webRoutingSection;
|
||||
|
||||
public TemplateRenderer(UmbracoContext umbracoContext, int pageId, int? altTemplateId)
|
||||
public TemplateRenderer(IUmbracoContextAccessor umbracoContextAccessor, IPublishedRouter publishedRouter, IFileService fileService, ILocalizationService textService, IWebRoutingSection webRoutingSection)
|
||||
{
|
||||
PageId = pageId;
|
||||
AltTemplateId = altTemplateId;
|
||||
_umbracoContext = umbracoContext ?? throw new ArgumentNullException(nameof(umbracoContext));
|
||||
_umbracoContextAccessor = umbracoContextAccessor ?? throw new ArgumentNullException(nameof(umbracoContextAccessor));
|
||||
_publishedRouter = publishedRouter ?? throw new ArgumentNullException(nameof(publishedRouter));
|
||||
_fileService = fileService ?? throw new ArgumentNullException(nameof(fileService));
|
||||
_languageService = textService ?? throw new ArgumentNullException(nameof(textService));
|
||||
_webRoutingSection = webRoutingSection ?? throw new ArgumentNullException(nameof(webRoutingSection));
|
||||
}
|
||||
|
||||
private IFileService FileService => Current.Services.FileService; // TODO: inject
|
||||
private IPublishedRouter PublishedRouter => Core.Composing.Current.Factory.GetInstance<IPublishedRouter>(); // TODO: inject
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Gets/sets the page id for the template to render
|
||||
/// </summary>
|
||||
public int PageId { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets/sets the alt template to render if there is one
|
||||
/// </summary>
|
||||
public int? AltTemplateId { get; }
|
||||
|
||||
public void Render(StringWriter writer)
|
||||
|
||||
public void Render(int pageId, int? altTemplateId, StringWriter writer)
|
||||
{
|
||||
if (writer == null) throw new ArgumentNullException(nameof(writer));
|
||||
|
||||
// instantiate a request and process
|
||||
// important to use CleanedUmbracoUrl - lowercase path-only version of the current url, though this isn't going to matter
|
||||
// terribly much for this implementation since we are just creating a doc content request to modify it's properties manually.
|
||||
var contentRequest = PublishedRouter.CreateRequest(_umbracoContext);
|
||||
var contentRequest = _publishedRouter.CreateRequest(_umbracoContextAccessor.UmbracoContext);
|
||||
|
||||
var doc = contentRequest.UmbracoContext.ContentCache.GetById(PageId);
|
||||
var doc = contentRequest.UmbracoContext.ContentCache.GetById(pageId);
|
||||
|
||||
if (doc == null)
|
||||
{
|
||||
writer.Write("<!-- Could not render template for Id {0}, the document was not found -->", PageId);
|
||||
writer.Write("<!-- Could not render template for Id {0}, the document was not found -->", pageId);
|
||||
return;
|
||||
}
|
||||
|
||||
//in some cases the UmbracoContext will not have a PublishedContentRequest assigned to it if we are not in the
|
||||
//execution of a front-end rendered page. In this case set the culture to the default.
|
||||
//set the culture to the same as is currently rendering
|
||||
if (_umbracoContext.PublishedRequest == null)
|
||||
if (_umbracoContextAccessor.UmbracoContext.PublishedRequest == null)
|
||||
{
|
||||
var defaultLanguage = Current.Services.LocalizationService.GetAllLanguages().FirstOrDefault();
|
||||
var defaultLanguage = _languageService.GetAllLanguages().FirstOrDefault();
|
||||
contentRequest.Culture = defaultLanguage == null
|
||||
? CultureInfo.CurrentUICulture
|
||||
: defaultLanguage.CultureInfo;
|
||||
}
|
||||
else
|
||||
{
|
||||
contentRequest.Culture = _umbracoContext.PublishedRequest.Culture;
|
||||
contentRequest.Culture = _umbracoContextAccessor.UmbracoContext.PublishedRequest.Culture;
|
||||
}
|
||||
|
||||
//set the doc that was found by id
|
||||
contentRequest.PublishedContent = doc;
|
||||
//set the template, either based on the AltTemplate found or the standard template of the doc
|
||||
var templateId = Current.Configs.Settings().WebRouting.DisableAlternativeTemplates || !AltTemplateId.HasValue
|
||||
var templateId = _webRoutingSection.DisableAlternativeTemplates || !altTemplateId.HasValue
|
||||
? doc.TemplateId
|
||||
: AltTemplateId.Value;
|
||||
: altTemplateId.Value;
|
||||
if (templateId.HasValue)
|
||||
contentRequest.TemplateModel = FileService.GetTemplate(templateId.Value);
|
||||
contentRequest.TemplateModel = _fileService.GetTemplate(templateId.Value);
|
||||
|
||||
//if there is not template then exit
|
||||
if (contentRequest.HasTemplate == false)
|
||||
{
|
||||
if (AltTemplateId.HasValue == false)
|
||||
if (altTemplateId.HasValue == false)
|
||||
{
|
||||
writer.Write("<!-- Could not render template for Id {0}, the document's template was not found with id {0}-->", doc.TemplateId);
|
||||
}
|
||||
else
|
||||
{
|
||||
writer.Write("<!-- Could not render template for Id {0}, the altTemplate was not found with id {0}-->", AltTemplateId);
|
||||
writer.Write("<!-- Could not render template for Id {0}, the altTemplate was not found with id {0}-->", altTemplateId);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
//First, save all of the items locally that we know are used in the chain of execution, we'll need to restore these
|
||||
//after this page has rendered.
|
||||
SaveExistingItems();
|
||||
SaveExistingItems(out var oldPublishedRequest, out var oldAltTemplate);
|
||||
|
||||
try
|
||||
{
|
||||
@@ -119,7 +110,7 @@ namespace Umbraco.Web.Templates
|
||||
finally
|
||||
{
|
||||
//restore items on context objects to continuing rendering the parent template
|
||||
RestoreItems();
|
||||
RestoreItems(oldPublishedRequest, oldAltTemplate);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -134,11 +125,11 @@ namespace Umbraco.Web.Templates
|
||||
//var queryString = _umbracoContext.HttpContext.Request.QueryString.AllKeys
|
||||
// .ToDictionary(key => key, key => context.Request.QueryString[key]);
|
||||
|
||||
var requestContext = new RequestContext(_umbracoContext.HttpContext, new RouteData()
|
||||
var requestContext = new RequestContext(_umbracoContextAccessor.UmbracoContext.HttpContext, new RouteData()
|
||||
{
|
||||
Route = RouteTable.Routes["Umbraco_default"]
|
||||
});
|
||||
var routeHandler = new RenderRouteHandler(_umbracoContext, ControllerBuilder.Current.GetControllerFactory());
|
||||
var routeHandler = new RenderRouteHandler(_umbracoContextAccessor, ControllerBuilder.Current.GetControllerFactory());
|
||||
var routeDef = routeHandler.GetUmbracoRouteDefinition(requestContext, request);
|
||||
var renderModel = new ContentModel(request.PublishedContent);
|
||||
//manually add the action/controller, this is required by mvc
|
||||
@@ -181,34 +172,29 @@ namespace Umbraco.Web.Templates
|
||||
|
||||
private void SetNewItemsOnContextObjects(PublishedRequest request)
|
||||
{
|
||||
// handlers like default.aspx will want it and most macros currently need it
|
||||
request.LegacyContentHashTable = new PublishedContentHashtableConverter(request);
|
||||
//now, set the new ones for this page execution
|
||||
_umbracoContext.HttpContext.Items["pageElements"] = request.LegacyContentHashTable.Elements;
|
||||
_umbracoContext.HttpContext.Items[Core.Constants.Conventions.Url.AltTemplate] = null;
|
||||
_umbracoContext.PublishedRequest = request;
|
||||
_umbracoContextAccessor.UmbracoContext.HttpContext.Items[Core.Constants.Conventions.Url.AltTemplate] = null;
|
||||
_umbracoContextAccessor.UmbracoContext.PublishedRequest = request;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Save all items that we know are used for rendering execution to variables so we can restore after rendering
|
||||
/// </summary>
|
||||
private void SaveExistingItems()
|
||||
private void SaveExistingItems(out PublishedRequest oldPublishedRequest, out object oldAltTemplate)
|
||||
{
|
||||
//Many objects require that these legacy items are in the http context items... before we render this template we need to first
|
||||
//save the values in them so that we can re-set them after we render so the rest of the execution works as per normal
|
||||
_oldPageElements = _umbracoContext.HttpContext.Items["pageElements"];
|
||||
_oldPublishedRequest = _umbracoContext.PublishedRequest;
|
||||
_oldAltTemplate = _umbracoContext.HttpContext.Items[Core.Constants.Conventions.Url.AltTemplate];
|
||||
oldPublishedRequest = _umbracoContextAccessor.UmbracoContext.PublishedRequest;
|
||||
oldAltTemplate = _umbracoContextAccessor.UmbracoContext.HttpContext.Items[Core.Constants.Conventions.Url.AltTemplate];
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Restores all items back to their context's to continue normal page rendering execution
|
||||
/// </summary>
|
||||
private void RestoreItems()
|
||||
private void RestoreItems(PublishedRequest oldPublishedRequest, object oldAltTemplate)
|
||||
{
|
||||
_umbracoContext.PublishedRequest = _oldPublishedRequest;
|
||||
_umbracoContext.HttpContext.Items["pageElements"] = _oldPageElements;
|
||||
_umbracoContext.HttpContext.Items[Core.Constants.Conventions.Url.AltTemplate] = _oldAltTemplate;
|
||||
_umbracoContextAccessor.UmbracoContext.PublishedRequest = oldPublishedRequest;
|
||||
_umbracoContextAccessor.UmbracoContext.HttpContext.Items[Core.Constants.Conventions.Url.AltTemplate] = oldAltTemplate;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -36,8 +36,8 @@ namespace Umbraco.Web.Trees
|
||||
|
||||
public ApplicationTreeController(IGlobalSettings globalSettings, UmbracoContext umbracoContext,
|
||||
ISqlContext sqlContext, ServiceContext services, AppCaches appCaches, IProfilingLogger logger,
|
||||
IRuntimeState runtimeState, ITreeService treeService)
|
||||
: base(globalSettings, umbracoContext, sqlContext, services, appCaches, logger, runtimeState)
|
||||
IRuntimeState runtimeState, ITreeService treeService, UmbracoHelper umbracoHelper)
|
||||
: base(globalSettings, umbracoContext, sqlContext, services, appCaches, logger, runtimeState, umbracoHelper)
|
||||
{
|
||||
_treeService = treeService;
|
||||
}
|
||||
|
||||
@@ -18,8 +18,8 @@ namespace Umbraco.Web.Trees
|
||||
|
||||
private readonly TreeAttribute _treeAttribute;
|
||||
|
||||
protected TreeController(IGlobalSettings globalSettings, UmbracoContext umbracoContext, ISqlContext sqlContext, ServiceContext services, AppCaches appCaches, IProfilingLogger logger, IRuntimeState runtimeState)
|
||||
: base(globalSettings, umbracoContext, sqlContext, services, appCaches, logger, runtimeState)
|
||||
protected TreeController(IGlobalSettings globalSettings, UmbracoContext umbracoContext, ISqlContext sqlContext, ServiceContext services, AppCaches appCaches, IProfilingLogger logger, IRuntimeState runtimeState, UmbracoHelper umbracoHelper)
|
||||
: base(globalSettings, umbracoContext, sqlContext, services, appCaches, logger, runtimeState, umbracoHelper)
|
||||
{
|
||||
_treeAttribute = GetTreeAttribute();
|
||||
}
|
||||
|
||||
@@ -27,11 +27,12 @@ namespace Umbraco.Web.Trees
|
||||
public abstract class TreeControllerBase : UmbracoAuthorizedApiController, ITree
|
||||
{
|
||||
protected TreeControllerBase()
|
||||
{ }
|
||||
{
|
||||
}
|
||||
|
||||
protected TreeControllerBase(IGlobalSettings globalSettings, UmbracoContext umbracoContext, ISqlContext sqlContext, ServiceContext services, AppCaches appCaches, IProfilingLogger logger, IRuntimeState runtimeState)
|
||||
: base(globalSettings, umbracoContext, sqlContext, services, appCaches, logger, runtimeState)
|
||||
{ }
|
||||
protected TreeControllerBase(IGlobalSettings globalSettings, UmbracoContext umbracoContext, ISqlContext sqlContext, ServiceContext services, AppCaches appCaches, IProfilingLogger logger, IRuntimeState runtimeState, UmbracoHelper umbracoHelper) : base(globalSettings, umbracoContext, sqlContext, services, appCaches, logger, runtimeState, umbracoHelper)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The method called to render the contents of the tree structure
|
||||
|
||||
@@ -143,6 +143,7 @@
|
||||
<Compile Include="Logging\WebProfilerComponent.cs" />
|
||||
<Compile Include="Logging\WebProfilerComposer.cs" />
|
||||
<Compile Include="Logging\WebProfilerProvider.cs" />
|
||||
<Compile Include="Macros\IMacroRenderer.cs" />
|
||||
<Compile Include="Media\EmbedProviders\YouTube.cs" />
|
||||
<Compile Include="Media\EmbedProviders\EmbedProviderBase.cs" />
|
||||
<Compile Include="Media\EmbedProviders\EmbedProvidersCollection.cs" />
|
||||
@@ -212,6 +213,7 @@
|
||||
<Compile Include="PropertyEditors\MultiUrlPickerPropertyEditor.cs" />
|
||||
<Compile Include="PropertyEditors\MultiUrlPickerValueEditor.cs" />
|
||||
<Compile Include="PropertyEditors\ValueConverters\MultiUrlPickerValueConverter.cs" />
|
||||
<Compile Include="Templates\ITemplateRenderer.cs" />
|
||||
<Compile Include="Trees\BackOfficeSectionCollectionBuilder.cs" />
|
||||
<Compile Include="Trees\MediaBackOfficeSection.cs" />
|
||||
<Compile Include="Trees\MembersBackOfficeSection.cs" />
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
using System.Security;
|
||||
using Umbraco.Core;
|
||||
using Umbraco.Core.Cache;
|
||||
using Umbraco.Core.Logging;
|
||||
using Umbraco.Web.Security;
|
||||
using Umbraco.Core.Models.Membership;
|
||||
using Umbraco.Core.Services;
|
||||
@@ -11,10 +12,10 @@ namespace Umbraco.Web
|
||||
public abstract class UmbracoAuthorizedHttpHandler : UmbracoHttpHandler
|
||||
{
|
||||
protected UmbracoAuthorizedHttpHandler()
|
||||
{ }
|
||||
{
|
||||
}
|
||||
|
||||
protected UmbracoAuthorizedHttpHandler(UmbracoContext umbracoContext, ServiceContext services)
|
||||
: base(umbracoContext, services)
|
||||
protected UmbracoAuthorizedHttpHandler(UmbracoContext umbracoContext, UmbracoHelper umbracoHelper, ServiceContext service, IProfilingLogger plogger) : base(umbracoContext, umbracoHelper, service, plogger)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.Collections;
|
||||
using System.IO;
|
||||
using System.Web;
|
||||
@@ -6,6 +7,9 @@ using System.Web.UI;
|
||||
using Umbraco.Core;
|
||||
using Umbraco.Web.Templates;
|
||||
using System.Collections.Generic;
|
||||
using Umbraco.Core.Logging;
|
||||
using Umbraco.Core.Models.PublishedContent;
|
||||
using Umbraco.Core.Services;
|
||||
using Umbraco.Web.Composing;
|
||||
using Umbraco.Web.Macros;
|
||||
|
||||
@@ -20,31 +24,34 @@ namespace Umbraco.Web
|
||||
/// </remarks>
|
||||
internal class UmbracoComponentRenderer : IUmbracoComponentRenderer
|
||||
{
|
||||
private readonly UmbracoContext _umbracoContext;
|
||||
private readonly IUmbracoContextAccessor _umbracoContextAccessor;
|
||||
private readonly IMacroRenderer _macroRenderer;
|
||||
private readonly ITemplateRenderer _templateRenderer;
|
||||
|
||||
public UmbracoComponentRenderer(UmbracoContext umbracoContext)
|
||||
public UmbracoComponentRenderer(IUmbracoContextAccessor umbracoContextAccessor, IMacroRenderer macroRenderer, ITemplateRenderer templateRenderer)
|
||||
{
|
||||
_umbracoContext = umbracoContext;
|
||||
_umbracoContextAccessor = umbracoContextAccessor;
|
||||
_macroRenderer = macroRenderer;
|
||||
_templateRenderer = templateRenderer ?? throw new ArgumentNullException(nameof(templateRenderer));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Renders the template for the specified pageId and an optional altTemplateId
|
||||
/// </summary>
|
||||
/// <param name="pageId"></param>
|
||||
/// <param name="contentId"></param>
|
||||
/// <param name="altTemplateId">If not specified, will use the template assigned to the node</param>
|
||||
/// <returns></returns>
|
||||
public IHtmlString RenderTemplate(int pageId, int? altTemplateId = null)
|
||||
public IHtmlString RenderTemplate(int contentId, int? altTemplateId = null)
|
||||
{
|
||||
var templateRenderer = new TemplateRenderer(_umbracoContext, pageId, altTemplateId);
|
||||
using (var sw = new StringWriter())
|
||||
{
|
||||
try
|
||||
{
|
||||
templateRenderer.Render(sw);
|
||||
_templateRenderer.Render(contentId, altTemplateId, sw);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
sw.Write("<!-- Error rendering template with id {0}: '{1}' -->", pageId, ex);
|
||||
sw.Write("<!-- Error rendering template with id {0}: '{1}' -->", contentId, ex);
|
||||
}
|
||||
return new HtmlString(sw.ToString());
|
||||
}
|
||||
@@ -53,129 +60,107 @@ namespace Umbraco.Web
|
||||
/// <summary>
|
||||
/// Renders the macro with the specified alias.
|
||||
/// </summary>
|
||||
/// <param name="contentId"></param>
|
||||
/// <param name="alias">The alias.</param>
|
||||
/// <returns></returns>
|
||||
public IHtmlString RenderMacro(string alias)
|
||||
public IHtmlString RenderMacro(int contentId, string alias)
|
||||
{
|
||||
return RenderMacro(alias, new { });
|
||||
return RenderMacro(contentId, alias, new { });
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Renders the macro with the specified alias, passing in the specified parameters.
|
||||
/// </summary>
|
||||
/// <param name="contentId"></param>
|
||||
/// <param name="alias">The alias.</param>
|
||||
/// <param name="parameters">The parameters.</param>
|
||||
/// <returns></returns>
|
||||
public IHtmlString RenderMacro(string alias, object parameters)
|
||||
public IHtmlString RenderMacro(int contentId, string alias, object parameters)
|
||||
{
|
||||
return RenderMacro(alias, parameters.ToDictionary<object>());
|
||||
return RenderMacro(contentId, alias, parameters.ToDictionary<object>());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Renders the macro with the specified alias, passing in the specified parameters.
|
||||
/// </summary>
|
||||
/// <param name="contentId"></param>
|
||||
/// <param name="alias">The alias.</param>
|
||||
/// <param name="parameters">The parameters.</param>
|
||||
/// <returns></returns>
|
||||
public IHtmlString RenderMacro(string alias, IDictionary<string, object> parameters)
|
||||
public IHtmlString RenderMacro(int contentId, string alias, IDictionary<string, object> parameters)
|
||||
{
|
||||
if (contentId == default)
|
||||
throw new ArgumentException("Invalid content id " + contentId);
|
||||
|
||||
if (_umbracoContext.PublishedRequest == null)
|
||||
{
|
||||
throw new InvalidOperationException("Cannot render a macro when there is no current PublishedContentRequest.");
|
||||
}
|
||||
var content = _umbracoContextAccessor.UmbracoContext.ContentCache?.GetById(true, contentId);
|
||||
|
||||
return RenderMacro(alias, parameters, _umbracoContext.PublishedRequest.LegacyContentHashTable);
|
||||
if (content == null)
|
||||
throw new InvalidOperationException("Cannot render a macro, no content found by id " + contentId);
|
||||
|
||||
return RenderMacro(alias, parameters, content);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Renders the macro with the specified alias, passing in the specified parameters.
|
||||
/// </summary>
|
||||
/// <param name="alias">The alias.</param>
|
||||
/// <param name="alias">The macro alias.</param>
|
||||
/// <param name="parameters">The parameters.</param>
|
||||
/// <param name="umbracoPage">The legacy umbraco page object that is required for some macros</param>
|
||||
/// <param name="content">The content used for macro rendering</param>
|
||||
/// <returns></returns>
|
||||
internal IHtmlString RenderMacro(string alias, IDictionary<string, object> parameters, PublishedContentHashtableConverter umbracoPage)
|
||||
private IHtmlString RenderMacro(string alias, IDictionary<string, object> parameters, IPublishedContent content)
|
||||
{
|
||||
if (alias == null) throw new ArgumentNullException("alias");
|
||||
if (umbracoPage == null) throw new ArgumentNullException("umbracoPage");
|
||||
if (content == null) throw new ArgumentNullException(nameof(content));
|
||||
|
||||
var m = Current.Services.MacroService.GetByAlias(alias);
|
||||
if (m == null)
|
||||
throw new KeyNotFoundException("Could not find macro with alias " + alias);
|
||||
|
||||
return RenderMacro(new MacroModel(m), parameters, umbracoPage);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Renders the macro with the specified alias, passing in the specified parameters.
|
||||
/// </summary>
|
||||
/// <param name="m">The macro.</param>
|
||||
/// <param name="parameters">The parameters.</param>
|
||||
/// <param name="umbracoPage">The legacy umbraco page object that is required for some macros</param>
|
||||
/// <returns></returns>
|
||||
internal IHtmlString RenderMacro(MacroModel m, IDictionary<string, object> parameters, PublishedContentHashtableConverter umbracoPage)
|
||||
{
|
||||
if (umbracoPage == null) throw new ArgumentNullException(nameof(umbracoPage));
|
||||
if (m == null) throw new ArgumentNullException(nameof(m));
|
||||
|
||||
if (_umbracoContext.PageId == null)
|
||||
{
|
||||
throw new InvalidOperationException("Cannot render a macro when UmbracoContext.PageId is null.");
|
||||
}
|
||||
|
||||
var macroProps = new Hashtable();
|
||||
foreach (var i in parameters)
|
||||
{
|
||||
// TODO: We are doing at ToLower here because for some insane reason the UpdateMacroModel method of macro.cs
|
||||
// looks for a lower case match. WTF. the whole macro concept needs to be rewritten.
|
||||
|
||||
|
||||
//NOTE: the value could have HTML encoded values, so we need to deal with that
|
||||
macroProps.Add(i.Key.ToLowerInvariant(), (i.Value is string) ? HttpUtility.HtmlDecode(i.Value.ToString()) : i.Value);
|
||||
}
|
||||
var renderer = new MacroRenderer(Current.ProfilingLogger);
|
||||
var macroControl = renderer.Render(m, umbracoPage.Elements, _umbracoContext.PageId.Value, macroProps).GetAsControl();
|
||||
// TODO: We are doing at ToLower here because for some insane reason the UpdateMacroModel method looks for a lower case match. the whole macro concept needs to be rewritten.
|
||||
//NOTE: the value could have HTML encoded values, so we need to deal with that
|
||||
var macroProps = parameters.ToDictionary(
|
||||
x => x.Key.ToLowerInvariant(),
|
||||
i => (i.Value is string) ? HttpUtility.HtmlDecode(i.Value.ToString()) : i.Value);
|
||||
|
||||
var macroControl = _macroRenderer.Render(alias, content, macroProps).GetAsControl();
|
||||
|
||||
string html;
|
||||
if (macroControl is LiteralControl)
|
||||
if (macroControl is LiteralControl control)
|
||||
{
|
||||
// no need to execute, we already have text
|
||||
html = (macroControl as LiteralControl).Text;
|
||||
html = control.Text;
|
||||
}
|
||||
else
|
||||
{
|
||||
var containerPage = new FormlessPage();
|
||||
containerPage.Controls.Add(macroControl);
|
||||
|
||||
using (var output = new StringWriter())
|
||||
using (var containerPage = new FormlessPage())
|
||||
{
|
||||
// .Execute() does a PushTraceContext/PopTraceContext and writes trace output straight into 'output'
|
||||
// and I do not see how we could wire the trace context to the current context... so it creates dirty
|
||||
// trace output right in the middle of the page.
|
||||
//
|
||||
// The only thing we can do is fully disable trace output while .Execute() runs and restore afterwards
|
||||
// which means trace output is lost if the macro is a control (.ascx or user control) that is invoked
|
||||
// from within Razor -- which makes sense anyway because the control can _not_ run correctly from
|
||||
// within Razor since it will never be inserted into the page pipeline (which may even not exist at all
|
||||
// if we're running MVC).
|
||||
//
|
||||
// I'm sure there's more things that will get lost with this context changing but I guess we'll figure
|
||||
// those out as we go along. One thing we lose is the content type response output.
|
||||
// http://issues.umbraco.org/issue/U4-1599 if it is setup during the macro execution. So
|
||||
// here we'll save the content type response and reset it after execute is called.
|
||||
containerPage.Controls.Add(macroControl);
|
||||
|
||||
var contentType = _umbracoContext.HttpContext.Response.ContentType;
|
||||
var traceIsEnabled = containerPage.Trace.IsEnabled;
|
||||
containerPage.Trace.IsEnabled = false;
|
||||
_umbracoContext.HttpContext.Server.Execute(containerPage, output, true);
|
||||
containerPage.Trace.IsEnabled = traceIsEnabled;
|
||||
//reset the content type
|
||||
_umbracoContext.HttpContext.Response.ContentType = contentType;
|
||||
using (var output = new StringWriter())
|
||||
{
|
||||
// .Execute() does a PushTraceContext/PopTraceContext and writes trace output straight into 'output'
|
||||
// and I do not see how we could wire the trace context to the current context... so it creates dirty
|
||||
// trace output right in the middle of the page.
|
||||
//
|
||||
// The only thing we can do is fully disable trace output while .Execute() runs and restore afterwards
|
||||
// which means trace output is lost if the macro is a control (.ascx or user control) that is invoked
|
||||
// from within Razor -- which makes sense anyway because the control can _not_ run correctly from
|
||||
// within Razor since it will never be inserted into the page pipeline (which may even not exist at all
|
||||
// if we're running MVC).
|
||||
//
|
||||
// I'm sure there's more things that will get lost with this context changing but I guess we'll figure
|
||||
// those out as we go along. One thing we lose is the content type response output.
|
||||
// http://issues.umbraco.org/issue/U4-1599 if it is setup during the macro execution. So
|
||||
// here we'll save the content type response and reset it after execute is called.
|
||||
|
||||
//Now, we need to ensure that local links are parsed
|
||||
html = TemplateUtilities.ParseInternalLinks(output.ToString(), _umbracoContext.UrlProvider);
|
||||
var contentType = _umbracoContextAccessor.UmbracoContext.HttpContext.Response.ContentType;
|
||||
var traceIsEnabled = containerPage.Trace.IsEnabled;
|
||||
containerPage.Trace.IsEnabled = false;
|
||||
_umbracoContextAccessor.UmbracoContext.HttpContext.Server.Execute(containerPage, output, true);
|
||||
containerPage.Trace.IsEnabled = traceIsEnabled;
|
||||
//reset the content type
|
||||
_umbracoContextAccessor.UmbracoContext.HttpContext.Response.ContentType = contentType;
|
||||
|
||||
//Now, we need to ensure that local links are parsed
|
||||
html = TemplateUtilities.ParseInternalLinks(output.ToString(), _umbracoContextAccessor.UmbracoContext.UrlProvider);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return new HtmlString(html);
|
||||
|
||||
@@ -281,29 +281,7 @@ namespace Umbraco.Web
|
||||
|| string.IsNullOrEmpty(request["umbdebug"]) == false);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the current page ID, or <c>null</c> if no page ID is available (e.g. a custom page).
|
||||
/// </summary>
|
||||
public int? PageId
|
||||
{
|
||||
get
|
||||
{
|
||||
try
|
||||
{
|
||||
// This was changed but the comments used to refer to
|
||||
// macros in the backoffice not working with this Id
|
||||
// it's probably not a problem any more though. Old comment:
|
||||
// https://github.com/umbraco/Umbraco-CMS/blob/7a615133ff9de84ee667fb7794169af65e2b4d7a/src/Umbraco.Web/UmbracoContext.cs#L256
|
||||
return Current.PublishedRequest.PublishedContent.Id;
|
||||
}
|
||||
catch
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Determines whether the current user is in a preview mode and browsing the site (ie. not in the admin UI)
|
||||
/// </summary>
|
||||
@@ -312,7 +290,7 @@ namespace Umbraco.Web
|
||||
get
|
||||
{
|
||||
if (_previewing.HasValue == false) DetectPreviewMode();
|
||||
return _previewing.Value;
|
||||
return _previewing ?? false;
|
||||
}
|
||||
private set => _previewing = value;
|
||||
}
|
||||
|
||||
@@ -8,139 +8,89 @@ using Umbraco.Core.Dictionary;
|
||||
using Umbraco.Core.Exceptions;
|
||||
using Umbraco.Core.Models;
|
||||
using Umbraco.Core.Models.PublishedContent;
|
||||
using Umbraco.Core.Services;
|
||||
using Umbraco.Core.Xml;
|
||||
using Umbraco.Core.Composing;
|
||||
using Umbraco.Web.Routing;
|
||||
using Umbraco.Web.Security;
|
||||
using Current = Umbraco.Web.Composing.Current;
|
||||
|
||||
namespace Umbraco.Web
|
||||
{
|
||||
using Examine = global::Examine;
|
||||
|
||||
/// <summary>
|
||||
/// A helper class that provides many useful methods and functionality for using Umbraco in templates
|
||||
/// </summary>
|
||||
public class UmbracoHelper : IUmbracoComponentRenderer
|
||||
/// <remarks>
|
||||
/// This object is a request based lifetime
|
||||
/// </remarks>
|
||||
public class UmbracoHelper
|
||||
{
|
||||
private static readonly HtmlStringUtilities StringUtilities = new HtmlStringUtilities();
|
||||
|
||||
private readonly UmbracoContext _umbracoContext;
|
||||
private readonly IPublishedContent _currentPage;
|
||||
private readonly ServiceContext _services;
|
||||
private IPublishedContent _currentPage;
|
||||
|
||||
private IUmbracoComponentRenderer _componentRenderer;
|
||||
private IPublishedContentQuery _query;
|
||||
private MembershipHelper _membershipHelper;
|
||||
private ITagQuery _tag;
|
||||
private readonly IUmbracoComponentRenderer _componentRenderer;
|
||||
private readonly ICultureDictionaryFactory _cultureDictionaryFactory;
|
||||
private ICultureDictionary _cultureDictionary;
|
||||
|
||||
#region Constructors
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="UmbracoHelper"/> class.
|
||||
/// Initializes a new instance of <see cref="UmbracoHelper"/>.
|
||||
/// </summary>
|
||||
/// <remarks>For tests.</remarks>
|
||||
internal UmbracoHelper(UmbracoContext umbracoContext, IPublishedContent content,
|
||||
ITagQuery tagQuery,
|
||||
ICultureDictionary cultureDictionary,
|
||||
/// <param name="umbracoContext">An Umbraco context.</param>
|
||||
/// <param name="tagQuery"></param>
|
||||
/// <param name="cultureDictionary"></param>
|
||||
/// <param name="componentRenderer"></param>
|
||||
/// <param name="publishedContentQuery"></param>
|
||||
/// <param name="membershipHelper"></param>
|
||||
/// <remarks>Sets the current page to the context's published content request's content item.</remarks>
|
||||
public UmbracoHelper(UmbracoContext umbracoContext, ITagQuery tagQuery,
|
||||
ICultureDictionaryFactory cultureDictionary,
|
||||
IUmbracoComponentRenderer componentRenderer,
|
||||
MembershipHelper membershipHelper,
|
||||
ServiceContext services)
|
||||
IPublishedContentQuery publishedContentQuery,
|
||||
MembershipHelper membershipHelper)
|
||||
{
|
||||
_umbracoContext = umbracoContext ?? throw new ArgumentNullException(nameof(umbracoContext));
|
||||
_tag = tagQuery ?? throw new ArgumentNullException(nameof(tagQuery));
|
||||
_cultureDictionary = cultureDictionary ?? throw new ArgumentNullException(nameof(cultureDictionary));
|
||||
TagQuery = tagQuery ?? throw new ArgumentNullException(nameof(tagQuery));
|
||||
_cultureDictionaryFactory = cultureDictionary ?? throw new ArgumentNullException(nameof(cultureDictionary));
|
||||
_componentRenderer = componentRenderer ?? throw new ArgumentNullException(nameof(componentRenderer));
|
||||
_membershipHelper = membershipHelper ?? throw new ArgumentNullException(nameof(membershipHelper));
|
||||
_currentPage = content ?? throw new ArgumentNullException(nameof(content));
|
||||
_services = services ?? throw new ArgumentNullException(nameof(services));
|
||||
MembershipHelper = membershipHelper ?? throw new ArgumentNullException(nameof(membershipHelper));
|
||||
ContentQuery = publishedContentQuery ?? throw new ArgumentNullException(nameof(publishedContentQuery));
|
||||
|
||||
if (_umbracoContext.IsFrontEndUmbracoRequest)
|
||||
_currentPage = _umbracoContext.PublishedRequest.PublishedContent;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="UmbracoHelper"/> class.
|
||||
/// Initializes a new empty instance of <see cref="UmbracoHelper"/>.
|
||||
/// </summary>
|
||||
/// <remarks>For tests - nothing is initialized.</remarks>
|
||||
internal UmbracoHelper()
|
||||
{ }
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="UmbracoHelper"/> class with an Umbraco context
|
||||
/// and a specific content item.
|
||||
/// </summary>
|
||||
/// <param name="umbracoContext">An Umbraco context.</param>
|
||||
/// <param name="content">A content item.</param>
|
||||
/// <param name="services">A services context.</param>
|
||||
/// <remarks>Sets the current page to the supplied content item.</remarks>
|
||||
public UmbracoHelper(UmbracoContext umbracoContext, ServiceContext services, IPublishedContent content)
|
||||
: this(umbracoContext, services)
|
||||
{
|
||||
_currentPage = content ?? throw new ArgumentNullException(nameof(content));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="UmbracoHelper"/> class with an Umbraco context.
|
||||
/// </summary>
|
||||
/// <param name="umbracoContext">An Umbraco context.</param>
|
||||
/// <param name="services">A services context.</param>
|
||||
/// <remarks>Sets the current page to the context's published content request's content item.</remarks>
|
||||
public UmbracoHelper(UmbracoContext umbracoContext, ServiceContext services)
|
||||
{
|
||||
_services = services ?? throw new ArgumentNullException(nameof(services));
|
||||
_umbracoContext = umbracoContext ?? throw new ArgumentNullException(nameof(umbracoContext));
|
||||
if (_umbracoContext.IsFrontEndUmbracoRequest)
|
||||
_currentPage = _umbracoContext.PublishedRequest.PublishedContent;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
/// <summary>
|
||||
/// Gets the tag context.
|
||||
/// </summary>
|
||||
public ITagQuery TagQuery => _tag ??
|
||||
(_tag = new TagQuery(_services.TagService, ContentQuery));
|
||||
public ITagQuery TagQuery { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the query context.
|
||||
/// </summary>
|
||||
public IPublishedContentQuery ContentQuery => _query ??
|
||||
(_query = new PublishedContentQuery(UmbracoContext.ContentCache, UmbracoContext.MediaCache, UmbracoContext.VariationContextAccessor));
|
||||
|
||||
/// <summary>
|
||||
/// Gets the Umbraco context.
|
||||
/// </summary>
|
||||
public UmbracoContext UmbracoContext
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_umbracoContext == null)
|
||||
throw new NullReferenceException("UmbracoContext has not been set.");
|
||||
return _umbracoContext;
|
||||
}
|
||||
}
|
||||
|
||||
public IPublishedContentQuery ContentQuery { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the membership helper.
|
||||
/// </summary>
|
||||
public MembershipHelper MembershipHelper => _membershipHelper
|
||||
?? (_membershipHelper = Current.Factory.GetInstance<MembershipHelper>());
|
||||
public MembershipHelper MembershipHelper { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the url provider.
|
||||
/// </summary>
|
||||
public UrlProvider UrlProvider => UmbracoContext.UrlProvider;
|
||||
public UrlProvider UrlProvider => _umbracoContext.UrlProvider;
|
||||
|
||||
/// <summary>
|
||||
/// Gets the component renderer.
|
||||
/// </summary>
|
||||
public IUmbracoComponentRenderer UmbracoComponentRenderer => _componentRenderer
|
||||
?? (_componentRenderer = new UmbracoComponentRenderer(UmbracoContext));
|
||||
|
||||
/// <summary>
|
||||
/// Returns the current <seealso cref="IPublishedContent"/> item
|
||||
/// assigned to the UmbracoHelper.
|
||||
/// Gets (or sets) the current <see cref="IPublishedContent"/> item assigned to the UmbracoHelper.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// <para>
|
||||
@@ -173,17 +123,18 @@ namespace Umbraco.Web
|
||||
);
|
||||
|
||||
}
|
||||
set => _currentPage = value;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Renders the template for the specified pageId and an optional altTemplateId
|
||||
/// </summary>
|
||||
/// <param name="pageId"></param>
|
||||
/// <param name="contentId"></param>
|
||||
/// <param name="altTemplateId">If not specified, will use the template assigned to the node</param>
|
||||
/// <returns></returns>
|
||||
public IHtmlString RenderTemplate(int pageId, int? altTemplateId = null)
|
||||
public IHtmlString RenderTemplate(int contentId, int? altTemplateId = null)
|
||||
{
|
||||
return UmbracoComponentRenderer.RenderTemplate(pageId, altTemplateId);
|
||||
return _componentRenderer.RenderTemplate(contentId, altTemplateId);
|
||||
}
|
||||
|
||||
#region RenderMacro
|
||||
@@ -195,7 +146,7 @@ namespace Umbraco.Web
|
||||
/// <returns></returns>
|
||||
public IHtmlString RenderMacro(string alias)
|
||||
{
|
||||
return UmbracoComponentRenderer.RenderMacro(alias, new { });
|
||||
return _componentRenderer.RenderMacro(_umbracoContext.PublishedRequest?.PublishedContent?.Id ?? 0, alias, new { });
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -206,7 +157,7 @@ namespace Umbraco.Web
|
||||
/// <returns></returns>
|
||||
public IHtmlString RenderMacro(string alias, object parameters)
|
||||
{
|
||||
return UmbracoComponentRenderer.RenderMacro(alias, parameters.ToDictionary<object>());
|
||||
return _componentRenderer.RenderMacro(_umbracoContext.PublishedRequest?.PublishedContent?.Id ?? 0, alias, parameters.ToDictionary<object>());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -217,7 +168,7 @@ namespace Umbraco.Web
|
||||
/// <returns></returns>
|
||||
public IHtmlString RenderMacro(string alias, IDictionary<string, object> parameters)
|
||||
{
|
||||
return UmbracoComponentRenderer.RenderMacro(alias, parameters);
|
||||
return _componentRenderer.RenderMacro(_umbracoContext.PublishedRequest?.PublishedContent?.Id ?? 0, alias, parameters);
|
||||
}
|
||||
|
||||
#endregion
|
||||
@@ -254,7 +205,7 @@ namespace Umbraco.Web
|
||||
/// Returns the ICultureDictionary for access to dictionary items
|
||||
/// </summary>
|
||||
public ICultureDictionary CultureDictionary => _cultureDictionary
|
||||
?? (_cultureDictionary = Current.CultureDictionaryFactory.CreateDictionary());
|
||||
?? (_cultureDictionary = _cultureDictionaryFactory.CreateDictionary());
|
||||
|
||||
#endregion
|
||||
|
||||
@@ -287,6 +238,7 @@ namespace Umbraco.Web
|
||||
/// Gets the url of a content identified by its identifier.
|
||||
/// </summary>
|
||||
/// <param name="contentId">The content identifier.</param>
|
||||
/// <param name="culture"></param>
|
||||
/// <returns>The url for the content.</returns>
|
||||
public string Url(int contentId, string culture = null)
|
||||
{
|
||||
@@ -454,11 +406,9 @@ namespace Umbraco.Web
|
||||
private IEnumerable<IPublishedContent> ContentForObjects(IEnumerable<object> ids)
|
||||
{
|
||||
var idsA = ids.ToArray();
|
||||
IEnumerable<int> intIds;
|
||||
if (ConvertIdsObjectToInts(idsA, out intIds))
|
||||
if (ConvertIdsObjectToInts(idsA, out var intIds))
|
||||
return ContentQuery.Content(intIds);
|
||||
IEnumerable<Guid> guidIds;
|
||||
if (ConvertIdsObjectToGuids(idsA, out guidIds))
|
||||
if (ConvertIdsObjectToGuids(idsA, out var guidIds))
|
||||
return ContentQuery.Content(guidIds);
|
||||
return Enumerable.Empty<IPublishedContent>();
|
||||
}
|
||||
@@ -638,12 +588,7 @@ namespace Umbraco.Web
|
||||
|
||||
public IPublishedContent Media(Guid id)
|
||||
{
|
||||
// TODO: This is horrible but until the media cache properly supports GUIDs we have no choice here and
|
||||
// currently there won't be any way to add this method correctly to `ITypedPublishedContentQuery` without breaking an interface and adding GUID support for media
|
||||
|
||||
var entityService = Current.Services.EntityService; // TODO: inject
|
||||
var mediaAttempt = entityService.GetId(id, UmbracoObjectTypes.Media);
|
||||
return mediaAttempt.Success ? ContentQuery.Media(mediaAttempt.Result) : null;
|
||||
return ContentQuery.Media(id);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -696,12 +641,10 @@ namespace Umbraco.Web
|
||||
private IEnumerable<IPublishedContent> MediaForObjects(IEnumerable<object> ids)
|
||||
{
|
||||
var idsA = ids.ToArray();
|
||||
IEnumerable<int> intIds;
|
||||
if (ConvertIdsObjectToInts(idsA, out intIds))
|
||||
if (ConvertIdsObjectToInts(idsA, out var intIds))
|
||||
return ContentQuery.Media(intIds);
|
||||
//IEnumerable<Guid> guidIds;
|
||||
//if (ConvertIdsObjectToGuids(idsA, out guidIds))
|
||||
// return ContentQuery.Media(guidIds);
|
||||
if (ConvertIdsObjectToGuids(idsA, out var guidIds))
|
||||
return ContentQuery.Media(guidIds);
|
||||
return Enumerable.Empty<IPublishedContent>();
|
||||
}
|
||||
|
||||
|
||||
@@ -14,19 +14,16 @@ namespace Umbraco.Web
|
||||
private UrlHelper _url;
|
||||
|
||||
protected UmbracoHttpHandler()
|
||||
: this(Current.UmbracoContext, Current.Services)
|
||||
: this(Current.UmbracoContext, Current.UmbracoHelper, Current.Services, Current.ProfilingLogger)
|
||||
{ }
|
||||
|
||||
protected UmbracoHttpHandler(UmbracoContext umbracoContext, ServiceContext services)
|
||||
protected UmbracoHttpHandler(UmbracoContext umbracoContext, UmbracoHelper umbracoHelper, ServiceContext service, IProfilingLogger plogger)
|
||||
{
|
||||
if (umbracoContext == null) throw new ArgumentNullException(nameof(umbracoContext));
|
||||
UmbracoContext = umbracoContext;
|
||||
Umbraco = new UmbracoHelper(umbracoContext, services);
|
||||
|
||||
// TODO: inject somehow
|
||||
Logger = Current.Logger;
|
||||
ProfilingLogger = Current.ProfilingLogger;
|
||||
Services = Current.Services;
|
||||
Logger = plogger;
|
||||
ProfilingLogger = plogger;
|
||||
Services = service;
|
||||
Umbraco = umbracoHelper;
|
||||
}
|
||||
|
||||
public abstract void ProcessRequest(HttpContext context);
|
||||
|
||||
@@ -21,15 +21,19 @@ namespace Umbraco.Web
|
||||
{
|
||||
private UrlHelper _url;
|
||||
|
||||
protected UmbracoWebService()
|
||||
protected UmbracoWebService(IProfilingLogger profilingLogger, UmbracoContext umbracoContext, UmbracoHelper umbraco, ServiceContext services, IGlobalSettings globalSettings)
|
||||
{
|
||||
UmbracoContext = Current.UmbracoContext;
|
||||
Umbraco = new UmbracoHelper(UmbracoContext, Current.Services);
|
||||
Logger = profilingLogger;
|
||||
ProfilingLogger = profilingLogger;
|
||||
UmbracoContext = umbracoContext;
|
||||
Umbraco = umbraco;
|
||||
Services = services;
|
||||
GlobalSettings = globalSettings;
|
||||
}
|
||||
|
||||
Logger = Current.Logger;
|
||||
ProfilingLogger = Current.ProfilingLogger;
|
||||
Services = Current.Services;
|
||||
GlobalSettings = Current.Configs.Global();
|
||||
protected UmbracoWebService()
|
||||
: this(Current.ProfilingLogger, Current.UmbracoContext, Current.UmbracoHelper, Current.Services, Current.Configs.Global())
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -1,7 +1,9 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.Generic;
|
||||
using System.Web.Http;
|
||||
using Umbraco.Core;
|
||||
using Umbraco.Web.Security;
|
||||
using Umbraco.Core.Composing;
|
||||
using Current = Umbraco.Web.Composing.Current;
|
||||
|
||||
namespace Umbraco.Web.WebApi
|
||||
{
|
||||
@@ -11,37 +13,6 @@ namespace Umbraco.Web.WebApi
|
||||
/// </summary>
|
||||
public sealed class MemberAuthorizeAttribute : AuthorizeAttribute
|
||||
{
|
||||
private readonly UmbracoContext _umbracoContext;
|
||||
|
||||
private UmbracoContext GetUmbracoContext()
|
||||
{
|
||||
return _umbracoContext ?? UmbracoContext.Current;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// THIS SHOULD BE ONLY USED FOR UNIT TESTS
|
||||
/// </summary>
|
||||
/// <param name="umbracoContext"></param>
|
||||
public MemberAuthorizeAttribute(UmbracoContext umbracoContext)
|
||||
{
|
||||
if (umbracoContext == null) throw new ArgumentNullException("umbracoContext");
|
||||
_umbracoContext = umbracoContext;
|
||||
}
|
||||
|
||||
public MemberAuthorizeAttribute()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Flag for whether to allow all site visitors or just authenticated members
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This is the same as applying the [AllowAnonymous] attribute
|
||||
/// </remarks>
|
||||
[Obsolete("Use [AllowAnonymous] instead")]
|
||||
public bool AllowAll { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Comma delimited list of allowed member types
|
||||
/// </summary>
|
||||
@@ -69,17 +40,14 @@ namespace Umbraco.Web.WebApi
|
||||
var members = new List<int>();
|
||||
foreach (var s in AllowMembers.Split(','))
|
||||
{
|
||||
int id;
|
||||
if (int.TryParse(s, out id))
|
||||
if (int.TryParse(s, out var id))
|
||||
{
|
||||
members.Add(id);
|
||||
}
|
||||
}
|
||||
|
||||
return GetUmbracoContext().Security.IsMemberAuthorized(AllowAll,
|
||||
AllowType.Split(','),
|
||||
AllowGroup.Split(','),
|
||||
members);
|
||||
var helper = Current.Factory.GetInstance<MembershipHelper>();
|
||||
return helper.IsMemberAuthorized(AllowType.Split(','), AllowGroup.Split(','), members);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -13,18 +13,12 @@ namespace Umbraco.Web.WebApi
|
||||
/// </summary>
|
||||
public abstract class UmbracoApiController : UmbracoApiControllerBase, IDiscoverable
|
||||
{
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="UmbracoApiController"/> with auto dependencies.
|
||||
/// </summary>
|
||||
/// <remarks>Dependencies are obtained from the <see cref="Current"/> service locator.</remarks>
|
||||
protected UmbracoApiController()
|
||||
{ }
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initialize a new instance of the <see cref="UmbracoApiController"/> with all its dependencies.
|
||||
/// </summary>
|
||||
protected UmbracoApiController(IGlobalSettings globalSettings, UmbracoContext umbracoContext, ISqlContext sqlContext, ServiceContext services, AppCaches appCaches, IProfilingLogger logger, IRuntimeState runtimeState)
|
||||
: base(globalSettings, umbracoContext, sqlContext, services, appCaches, logger, runtimeState)
|
||||
{ }
|
||||
protected UmbracoApiController(IGlobalSettings globalSettings, UmbracoContext umbracoContext, ISqlContext sqlContext, ServiceContext services, AppCaches appCaches, IProfilingLogger logger, IRuntimeState runtimeState, UmbracoHelper umbracoHelper) : base(globalSettings, umbracoContext, sqlContext, services, appCaches, logger, runtimeState, umbracoHelper)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -21,8 +21,6 @@ namespace Umbraco.Web.WebApi
|
||||
[FeatureAuthorize]
|
||||
public abstract class UmbracoApiControllerBase : ApiController
|
||||
{
|
||||
private UmbracoHelper _umbracoHelper;
|
||||
|
||||
// note: all Umbraco controllers have two constructors: one with all dependencies, which should be used,
|
||||
// and one with auto dependencies, ie no dependencies - and then dependencies are automatically obtained
|
||||
// here from the Current service locator - this is obviously evil, but it allows us to add new dependencies
|
||||
@@ -40,14 +38,15 @@ namespace Umbraco.Web.WebApi
|
||||
Current.Factory.GetInstance<ServiceContext>(),
|
||||
Current.Factory.GetInstance<AppCaches>(),
|
||||
Current.Factory.GetInstance<IProfilingLogger>(),
|
||||
Current.Factory.GetInstance<IRuntimeState>()
|
||||
Current.Factory.GetInstance<IRuntimeState>(),
|
||||
Current.Factory.GetInstance<UmbracoHelper>()
|
||||
)
|
||||
{ }
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="UmbracoApiControllerBase"/> class with all its dependencies.
|
||||
/// </summary>
|
||||
protected UmbracoApiControllerBase(IGlobalSettings globalSettings, UmbracoContext umbracoContext, ISqlContext sqlContext, ServiceContext services, AppCaches appCaches, IProfilingLogger logger, IRuntimeState runtimeState)
|
||||
protected UmbracoApiControllerBase(IGlobalSettings globalSettings, UmbracoContext umbracoContext, ISqlContext sqlContext, ServiceContext services, AppCaches appCaches, IProfilingLogger logger, IRuntimeState runtimeState, UmbracoHelper umbracoHelper)
|
||||
{
|
||||
GlobalSettings = globalSettings;
|
||||
SqlContext = sqlContext;
|
||||
@@ -56,6 +55,7 @@ namespace Umbraco.Web.WebApi
|
||||
Logger = logger;
|
||||
RuntimeState = runtimeState;
|
||||
UmbracoContext = umbracoContext;
|
||||
Umbraco = umbracoHelper;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -112,9 +112,8 @@ namespace Umbraco.Web.WebApi
|
||||
/// <summary>
|
||||
/// Gets the Umbraco helper.
|
||||
/// </summary>
|
||||
public UmbracoHelper Umbraco => _umbracoHelper
|
||||
?? (_umbracoHelper = new UmbracoHelper(UmbracoContext, Services));
|
||||
|
||||
public UmbracoHelper Umbraco { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the web security helper.
|
||||
/// </summary>
|
||||
|
||||
@@ -30,19 +30,13 @@ namespace Umbraco.Web.WebApi
|
||||
{
|
||||
private BackOfficeUserManager<BackOfficeIdentityUser> _userManager;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="UmbracoAuthorizedApiController"/> with auto dependencies.
|
||||
/// </summary>
|
||||
/// <remarks>Dependencies are obtained from the <see cref="Current"/> service locator.</remarks>
|
||||
protected UmbracoAuthorizedApiController()
|
||||
{ }
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="UmbracoAuthorizedApiController"/> class with all its dependencies.
|
||||
/// </summary>
|
||||
protected UmbracoAuthorizedApiController(IGlobalSettings globalSettings, UmbracoContext umbracoContext, ISqlContext sqlContext, ServiceContext services, AppCaches appCaches, IProfilingLogger logger, IRuntimeState runtimeState)
|
||||
: base(globalSettings, umbracoContext, sqlContext, services, appCaches, logger, runtimeState)
|
||||
{ }
|
||||
protected UmbracoAuthorizedApiController(IGlobalSettings globalSettings, UmbracoContext umbracoContext, ISqlContext sqlContext, ServiceContext services, AppCaches appCaches, IProfilingLogger logger, IRuntimeState runtimeState, UmbracoHelper umbracoHelper) : base(globalSettings, umbracoContext, sqlContext, services, appCaches, logger, runtimeState, umbracoHelper)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the user manager.
|
||||
|
||||
Reference in New Issue
Block a user