diff --git a/src/Umbraco.Core/Actions/ActionCollection.cs b/src/Umbraco.Core/Actions/ActionCollection.cs index f6a3d92995..1ba60317f5 100644 --- a/src/Umbraco.Core/Actions/ActionCollection.cs +++ b/src/Umbraco.Core/Actions/ActionCollection.cs @@ -19,7 +19,7 @@ namespace Umbraco.Web.Actions return this.OfType().FirstOrDefault(); } - internal IEnumerable GetByLetters(IEnumerable letters) + public IEnumerable GetByLetters(IEnumerable letters) { var actions = this.ToArray(); // no worry: internally, it's already an array return letters @@ -29,7 +29,7 @@ namespace Umbraco.Web.Actions .ToList(); } - internal IReadOnlyList FromEntityPermission(EntityPermission entityPermission) + public IReadOnlyList FromEntityPermission(EntityPermission entityPermission) { var actions = this.ToArray(); // no worry: internally, it's already an array return entityPermission.AssignedPermissions diff --git a/src/Umbraco.Core/Models/Trees/MenuItem.cs b/src/Umbraco.Core/Models/Trees/MenuItem.cs index 094c6b24ff..b8743a957a 100644 --- a/src/Umbraco.Core/Models/Trees/MenuItem.cs +++ b/src/Umbraco.Core/Models/Trees/MenuItem.cs @@ -57,7 +57,8 @@ namespace Umbraco.Web.Models.Trees #endregion #region Properties - internal IAction Action { get; set; } + [IgnoreDataMember] + public IAction Action { get; set; } /// /// A dictionary to support any additional meta data that should be rendered for the node which is diff --git a/src/Umbraco.Core/Routing/UrlProviderExtensions.cs b/src/Umbraco.Core/Routing/UrlProviderExtensions.cs index a7f8a97c6d..352209b987 100644 --- a/src/Umbraco.Core/Routing/UrlProviderExtensions.cs +++ b/src/Umbraco.Core/Routing/UrlProviderExtensions.cs @@ -9,7 +9,7 @@ using Umbraco.Core.Models.PublishedContent; namespace Umbraco.Web.Routing { - internal static class UrlProviderExtensions + public static class UrlProviderExtensions { /// /// Gets the Urls of the content item. diff --git a/src/Umbraco.Core/Services/DateTypeServiceExtensions.cs b/src/Umbraco.Core/Services/DateTypeServiceExtensions.cs index 3b72a6f258..6c2a1f7799 100644 --- a/src/Umbraco.Core/Services/DateTypeServiceExtensions.cs +++ b/src/Umbraco.Core/Services/DateTypeServiceExtensions.cs @@ -4,7 +4,7 @@ using Umbraco.Core.PropertyEditors; namespace Umbraco.Core.Services { - internal static class DateTypeServiceExtensions + public static class DateTypeServiceExtensions { public static bool IsDataTypeIgnoringUserStartNodes(this IDataTypeService dataTypeService, Guid key) { diff --git a/src/Umbraco.Core/Umbraco.Core.csproj b/src/Umbraco.Core/Umbraco.Core.csproj index dc76ed39e7..53e6fe3fbc 100644 --- a/src/Umbraco.Core/Umbraco.Core.csproj +++ b/src/Umbraco.Core/Umbraco.Core.csproj @@ -27,5 +27,8 @@ <_Parameter1>Umbraco.Tests.Benchmarks + + <_Parameter1>Umbraco.Tests.Integration + diff --git a/src/Umbraco.Infrastructure/Models/Mapping/TabsAndPropertiesMapper.cs b/src/Umbraco.Infrastructure/Models/Mapping/TabsAndPropertiesMapper.cs index d9c76b5ebc..932b12cff1 100644 --- a/src/Umbraco.Infrastructure/Models/Mapping/TabsAndPropertiesMapper.cs +++ b/src/Umbraco.Infrastructure/Models/Mapping/TabsAndPropertiesMapper.cs @@ -143,7 +143,7 @@ namespace Umbraco.Web.Models.Mapping // merge properties for groups with the same name foreach (var group in groupsByName) { - var groupProperties = source.GetPropertiesForGroup(group) + var groupProperties = source.GetPropertiesForGroup(group) .Where(x => IgnoreProperties.Contains(x.Alias) == false); // skip ignored properties.AddRange(groupProperties); diff --git a/src/Umbraco.Tests.Common/Builders/ContentBuilder.cs b/src/Umbraco.Tests.Common/Builders/ContentBuilder.cs index 33acd3a38e..0229961277 100644 --- a/src/Umbraco.Tests.Common/Builders/ContentBuilder.cs +++ b/src/Umbraco.Tests.Common/Builders/ContentBuilder.cs @@ -33,9 +33,11 @@ namespace Umbraco.Tests.Common.Builders private string _path; private int? _sortOrder; private bool? _trashed; + private IContentType _contentType; public ContentTypeBuilder AddContentType() { + _contentType = null; var builder = new ContentTypeBuilder(this); _contentTypeBuilder = builder; return builder; @@ -55,14 +57,14 @@ namespace Umbraco.Tests.Common.Builders var sortOrder = _sortOrder ?? 0; var trashed = _trashed ?? false; - if (_contentTypeBuilder == null) + if (_contentTypeBuilder is null && _contentType is null) { - throw new InvalidOperationException("A member cannot be constructed without providing a member type. Use AddContentType()."); + throw new InvalidOperationException("A member cannot be constructed without providing a member type. Use AddContentType() or WithContentType()."); } - var memberType = _contentTypeBuilder.Build(); + var contentType = _contentType ?? _contentTypeBuilder.Build(); - var member = new Content(name, parentId, memberType) + var content = new Content(name, parentId, contentType) { Id = id, Key = key, @@ -80,13 +82,21 @@ namespace Umbraco.Tests.Common.Builders var propertyData = _propertyDataBuilder.Build(); foreach (var kvp in propertyData) { - member.SetValue(kvp.Key, kvp.Value); + content.SetValue(kvp.Key, kvp.Value); } - member.ResetDirtyProperties(false); + content.ResetDirtyProperties(false); } - return member; + return content; + } + + public ContentBuilder WithContentType(IContentType contentType) + { + _contentTypeBuilder = null; + _contentType = contentType; + + return this; } int? IWithIdBuilder.Id @@ -153,5 +163,7 @@ namespace Umbraco.Tests.Common.Builders get => _parentId; set => _parentId = value; } + + } } diff --git a/src/Umbraco.Tests.Common/Builders/ContentTypeBuilder.cs b/src/Umbraco.Tests.Common/Builders/ContentTypeBuilder.cs index a8887e95ae..3c7dc4c76d 100644 --- a/src/Umbraco.Tests.Common/Builders/ContentTypeBuilder.cs +++ b/src/Umbraco.Tests.Common/Builders/ContentTypeBuilder.cs @@ -7,9 +7,10 @@ namespace Umbraco.Tests.Common.Builders { public class ContentTypeBuilder : ContentTypeBaseBuilder, - IWithPropertyTypeIdsIncrementingFrom + IWithPropertyTypeIdsIncrementingFrom, IBuildPropertyTypes { private List> _propertyGroupBuilders = new List>(); + private List> _noGroupPropertyTypeBuilders = new List>(); private List _templateBuilders = new List(); private List _allowedContentTypeBuilders = new List(); @@ -37,6 +38,13 @@ namespace Umbraco.Tests.Common.Builders return builder; } + public PropertyTypeBuilder AddPropertyType() + { + var builder = new PropertyTypeBuilder(this); + _noGroupPropertyTypeBuilders.Add(builder); + return builder; + } + public TemplateBuilder AddAllowedTemplate() { var builder = new TemplateBuilder(this); @@ -72,6 +80,7 @@ namespace Umbraco.Tests.Common.Builders IsContainer = GetIsContainer(), }; + contentType.NoGroupPropertyTypes = _noGroupPropertyTypeBuilders.Select(x => x.Build()); BuildPropertyGroups(contentType, _propertyGroupBuilders.Select(x => x.Build())); BuildPropertyTypeIds(contentType, _propertyTypeIdsIncrementingFrom); @@ -84,6 +93,7 @@ namespace Umbraco.Tests.Common.Builders .SingleOrDefault(x => x.Id == _defaultTemplateId.Value)); } + contentType.ResetDirtyProperties(false); return contentType; diff --git a/src/Umbraco.Tests/TestHelpers/Stubs/TestProfiler.cs b/src/Umbraco.Tests.Common/TestHelpers/Stubs/TestProfiler.cs similarity index 100% rename from src/Umbraco.Tests/TestHelpers/Stubs/TestProfiler.cs rename to src/Umbraco.Tests.Common/TestHelpers/Stubs/TestProfiler.cs diff --git a/src/Umbraco.Tests.Common/Umbraco.Tests.Common.csproj b/src/Umbraco.Tests.Common/Umbraco.Tests.Common.csproj index e6963bc8aa..3822f3d191 100644 --- a/src/Umbraco.Tests.Common/Umbraco.Tests.Common.csproj +++ b/src/Umbraco.Tests.Common/Umbraco.Tests.Common.csproj @@ -5,6 +5,7 @@ + @@ -14,5 +15,4 @@ - diff --git a/src/Umbraco.Tests.Integration/Mapping/UmbracoMapperTests.cs b/src/Umbraco.Tests.Integration/Mapping/UmbracoMapperTests.cs new file mode 100644 index 0000000000..2b26c862f0 --- /dev/null +++ b/src/Umbraco.Tests.Integration/Mapping/UmbracoMapperTests.cs @@ -0,0 +1,360 @@ +using System.Globalization; +using System.Linq; +using Microsoft.Extensions.DependencyInjection; +using NUnit.Framework; +using Umbraco.Core; +using Umbraco.Core.Mapping; +using Umbraco.Core.Models; +using Umbraco.Core.PropertyEditors; +using Umbraco.Core.Services; +using Umbraco.Tests.Common.Builders; +using Umbraco.Tests.Common.Builders.Extensions; +using Umbraco.Tests.Integration.Testing; +using Umbraco.Tests.Testing; +using Umbraco.Web.Models.ContentEditing; + +namespace Umbraco.Tests.Integration.Mapping +{ + [TestFixture] + [UmbracoTest(Mapper = true, Database = UmbracoTestOptions.Database.NewSchemaPerTest)] + public class UmbracoMapperTests : UmbracoIntegrationTest + { + [SetUp] + public void SetUp() + { + _sut = Services.GetRequiredService(); + + _dataTypeService = Services.GetRequiredService(); + _propertyEditorCollection = Services.GetRequiredService(); + _mediaBuilder = new MediaBuilder(); + _contentBuilder = new ContentBuilder(); + _contentTypeBuilder = new ContentTypeBuilder(); + _contentTypeService = Services.GetRequiredService(); + _localizedTextService = Services.GetRequiredService(); + } + + private UmbracoMapper _sut; + private IDataTypeService _dataTypeService; + private PropertyEditorCollection _propertyEditorCollection; + private MediaBuilder _mediaBuilder; + private ContentBuilder _contentBuilder; + private ContentTypeBuilder _contentTypeBuilder; + private IContentTypeService _contentTypeService; + private ILocalizedTextService _localizedTextService; + + + [Test] + public void To_Media_Item_Simple() + { + var content = _mediaBuilder + .AddMediaType() + .AddPropertyGroup() + .AddPropertyType() + .Done() + .Done() + .Done() + .WithCreatorId(Constants.Security.SuperUserId) + .Build(); + + var result = _sut.Map>(content); + + AssertBasics(result, content); + + foreach (var p in content.Properties) + { + AssertBasicProperty(result, p); + } + } + + [Test] + public void To_Content_Item_Simple() + { + var content = _contentBuilder + .AddContentType() + .AddPropertyGroup() + .AddPropertyType() + .Done() + .Done() + .Done() + .WithCreatorId(Constants.Security.SuperUserId) + .Build(); + + var result = _sut.Map>(content); + + AssertBasics(result, content); + + foreach (var p in content.Properties) + { + AssertBasicProperty(result, p); + } + } + + [Test] + public void To_Content_Item_Dto() + { + var content = _contentBuilder + .AddContentType() + .AddPropertyGroup() + .AddPropertyType() + .Done() + .Done() + .Done() + .WithCreatorId(Constants.Security.SuperUserId) + .Build(); + + var result = _sut.Map(content); + + foreach (var p in content.Properties) + { + AssertProperty(result, p); + } + } + + [Test] + public void To_Media_Item_Dto() + { + var content = _mediaBuilder + .AddMediaType() + .AddPropertyGroup() + .AddPropertyType() + .Done() + .Done() + .Done() + .Build(); + + var result = _sut.Map(content); + + Assert.GreaterOrEqual(result.Properties.Count(), 1); + Assert.AreEqual(content.Properties.Count, result.Properties.Count()); + foreach (var p in content.Properties) + { + AssertProperty(result, p); + } + } + + #region Assertions + + private void AssertDisplayProperty(IContentProperties result, IProperty p) + where T : ContentPropertyBasic + { + var pDto = result.Properties.SingleOrDefault(x => x.Alias == p.Alias); + Assert.IsNotNull(pDto); + + //pDto.Alias = p.Alias; + //pDto.Description = p.PropertyType.Description; + //pDto.Label = p.PropertyType.Name; + //pDto.Config = applicationContext.Services.DataTypeService.GetPreValuesByDataTypeId(p.PropertyType.DataTypeDefinitionId); + + } + + [Test] + public void To_Display_Model() + { + var contentType = _contentTypeBuilder + .WithId(0) + .AddPropertyGroup() + .WithId(1) + .AddPropertyType() + .Done() + .Done() + .AddPropertyGroup() + .WithId(2) + .AddPropertyType() + .Done() + .Done() + .AddPropertyGroup() + .WithId(3) + .AddPropertyType() + .Done() + .Done() + .AddPropertyGroup() + .WithId(4) + .AddPropertyType() + .Done() + .Done() + .Build(); + _contentTypeService.Save(contentType); + + var content = _contentBuilder + .WithContentType(contentType) + .WithCreatorId(Constants.Security.SuperUserId) + .Build(); + + var result = _sut.Map(content); + + AssertBasics(result, content); + + var invariantContent = result.Variants.First(); + foreach (var p in content.Properties) + { + AssertBasicProperty(invariantContent, p); + AssertDisplayProperty(invariantContent, p); + } + + Assert.AreEqual(4, invariantContent.Tabs.Count()); + Assert.IsTrue(invariantContent.Tabs.First().IsActive); + Assert.IsTrue(invariantContent.Tabs.Except(new[] { invariantContent.Tabs.First() }).All(x => x.IsActive == false)); + } + + [Test] + public void To_Display_Model_No_Tabs() + { + var contentType = _contentTypeBuilder + .WithId(0) + .Build(); + _contentTypeService.Save(contentType); + + var content = _contentBuilder + .WithContentType(contentType) + .WithCreatorId(Constants.Security.SuperUserId) + .Build(); + + var result = _sut.Map(content); + + AssertBasics(result, content); + + var invariantContent = result.Variants.First(); + foreach (var p in content.Properties) + { + AssertBasicProperty(invariantContent, p); + AssertDisplayProperty(invariantContent, p); + } + + Assert.AreEqual(contentType.CompositionPropertyGroups.Count(), invariantContent.Tabs.Count()); + } + + [Test] + public void To_Display_Model_With_Non_Grouped_Properties() + { + var contentType = _contentTypeBuilder + .WithId(0) + .AddPropertyType() + .WithId(1) + .WithValueStorageType(ValueStorageType.Ntext) + .WithPropertyEditorAlias("nonGrouped1") + .WithName("Non Grouped 1") + .Done() + .AddPropertyType() + .WithId(2) + .WithValueStorageType(ValueStorageType.Ntext) + .WithPropertyEditorAlias("nonGrouped2") + .WithName("Non Grouped 2") + .Done() + .Build(); + _contentTypeService.Save(contentType); + + var content = _contentBuilder + .WithContentType(contentType) + .WithCreatorId(Constants.Security.SuperUserId) + .Build(); + + var result = _sut.Map(content); + + AssertBasics(result, content); + + var invariantContent = result.Variants.First(); + foreach (var p in content.Properties) + { + AssertBasicProperty(invariantContent, p); + AssertDisplayProperty(invariantContent, p); + } + + Assert.AreEqual(contentType.CompositionPropertyGroups.Count(), invariantContent.Tabs.Count() - 1); + Assert.IsTrue(invariantContent.Tabs.Any(x => x.Label == _localizedTextService.Localize("general/properties"))); + Assert.AreEqual(2, invariantContent.Tabs.Where(x => x.Label == _localizedTextService.Localize("general/properties")).SelectMany(x => x.Properties.Where(p => p.Alias.StartsWith("_umb_") == false)).Count()); + } + + private void AssertBasics(ContentItemDisplay result, IContent content) + { + Assert.AreEqual(content.Id, result.Id); + + var ownerId = content.CreatorId; + if (ownerId != 0) + { + Assert.IsNotNull(result.Owner); + Assert.AreEqual(Constants.Security.SuperUserId, result.Owner.UserId); + Assert.AreEqual("Administrator", result.Owner.Name); + } + else + { + Assert.IsNull(result.Owner); // because, 0 is no user + } + + var invariantContent = result.Variants.First(); + + Assert.AreEqual(content.ParentId, result.ParentId); + Assert.AreEqual(content.UpdateDate, invariantContent.UpdateDate); + Assert.AreEqual(content.CreateDate, invariantContent.CreateDate); + Assert.AreEqual(content.Name, invariantContent.Name); + Assert.AreEqual(content.Properties.Count(), + ((IContentProperties)invariantContent).Properties.Count(x => x.Alias.StartsWith("_umb_") == false)); + } + + private void AssertBasics(ContentItemBasic result, TPersisted content) + where T : ContentPropertyBasic + where TPersisted : IContentBase + { + Assert.AreEqual(content.Id, result.Id); + + var ownerId = content.CreatorId; + if (ownerId != 0) + { + Assert.IsNotNull(result.Owner); + Assert.AreEqual(Constants.Security.SuperUserId, result.Owner.UserId); + Assert.AreEqual("Administrator", result.Owner.Name); + } + else + { + Assert.IsNull(result.Owner); // because, 0 is no user + } + + Assert.AreEqual(content.ParentId, result.ParentId); + Assert.AreEqual(content.UpdateDate, result.UpdateDate); + Assert.AreEqual(content.CreateDate, result.CreateDate); + Assert.AreEqual(content.Name, result.Name); + Assert.AreEqual(content.Properties.Count(), result.Properties.Count(x => x.Alias.StartsWith("_umb_") == false)); + } + + private void AssertBasicProperty(IContentProperties result, IProperty p) + where T : ContentPropertyBasic + { + var pDto = result.Properties.SingleOrDefault(x => x.Alias == p.Alias); + Assert.IsNotNull(pDto); + Assert.AreEqual(p.Alias, pDto.Alias); + Assert.AreEqual(p.Id, pDto.Id); + + if (p.GetValue() == null) + Assert.AreEqual(pDto.Value, string.Empty); + else if (p.GetValue() is decimal) + Assert.AreEqual(pDto.Value, ((decimal) p.GetValue()).ToString(NumberFormatInfo.InvariantInfo)); + else + Assert.AreEqual(pDto.Value, p.GetValue().ToString()); + } + + private void AssertProperty(IContentProperties result, IProperty p) + { + AssertBasicProperty(result, p); + + var pDto = result.Properties.SingleOrDefault(x => x.Alias == p.Alias); + Assert.IsNotNull(pDto); + Assert.AreEqual(p.PropertyType.Mandatory, pDto.IsRequired); + Assert.AreEqual(p.PropertyType.ValidationRegExp, pDto.ValidationRegExp); + Assert.AreEqual(p.PropertyType.Description, pDto.Description); + Assert.AreEqual(p.PropertyType.Name, pDto.Label); + Assert.AreEqual(_dataTypeService.GetDataType(p.PropertyType.DataTypeId), pDto.DataType); + Assert.AreEqual(_propertyEditorCollection[p.PropertyType.PropertyEditorAlias], pDto.PropertyEditor); + } + + private void AssertContentItem(ContentItemBasic result, T content) + where T : IContentBase + { + AssertBasics(result, content); + + foreach (var p in content.Properties) + { + AssertProperty(result, p); + } + } + #endregion + } +} diff --git a/src/Umbraco.Tests.Integration/Testing/UmbracoIntegrationTest.cs b/src/Umbraco.Tests.Integration/Testing/UmbracoIntegrationTest.cs index 8f9ec4d833..372afbecd2 100644 --- a/src/Umbraco.Tests.Integration/Testing/UmbracoIntegrationTest.cs +++ b/src/Umbraco.Tests.Integration/Testing/UmbracoIntegrationTest.cs @@ -18,6 +18,7 @@ using Umbraco.Tests.Common.Builders; using Umbraco.Tests.Integration.Extensions; using Umbraco.Tests.Integration.Implementations; using Umbraco.Extensions; +using Umbraco.Web; namespace Umbraco.Tests.Integration.Testing { @@ -109,6 +110,12 @@ namespace Umbraco.Tests.Integration.Testing // Add it! services.AddUmbracoConfiguration(hostContext.Configuration); services.AddUmbracoCore(webHostEnvironment, umbracoContainer, GetType().Assembly, NoAppCache.Instance, testHelper.GetLoggingConfiguration(), out _); + services.AddUmbracoWebComponents(); + services.AddUmbracoRuntimeMinifier(hostContext.Configuration); + services.AddUmbracoBackOffice(); + services.AddUmbracoBackOfficeIdentity(); + + services.AddMvc(); CustomTestSetup(services); }); @@ -117,10 +124,12 @@ namespace Umbraco.Tests.Integration.Testing var app = new ApplicationBuilder(host.Services); Services = app.ApplicationServices; + Services.GetRequiredService().EnsureUmbracoContext(); // This will create a db, install the schema and ensure the app is configured to run app.UseTestLocalDb(testHelper.WorkingDirectory, this); app.UseUmbracoCore(); + } #region Common services diff --git a/src/Umbraco.Tests.Integration/Umbraco.Tests.Integration.csproj b/src/Umbraco.Tests.Integration/Umbraco.Tests.Integration.csproj index cc8e1f5bb5..c38b34db2c 100644 --- a/src/Umbraco.Tests.Integration/Umbraco.Tests.Integration.csproj +++ b/src/Umbraco.Tests.Integration/Umbraco.Tests.Integration.csproj @@ -29,6 +29,7 @@ + diff --git a/src/Umbraco.Tests/Composing/TypeFinderTests.cs b/src/Umbraco.Tests.UnitTests/Umbraco.Core/Composing/TypeFinderTests.cs similarity index 76% rename from src/Umbraco.Tests/Composing/TypeFinderTests.cs rename to src/Umbraco.Tests.UnitTests/Umbraco.Core/Composing/TypeFinderTests.cs index a872ad03b7..e0e87fb1ee 100644 --- a/src/Umbraco.Tests/Composing/TypeFinderTests.cs +++ b/src/Umbraco.Tests.UnitTests/Umbraco.Core/Composing/TypeFinderTests.cs @@ -1,24 +1,11 @@ using System; -using System.Collections.Concurrent; -using System.Collections.Generic; -using System.Collections.ObjectModel; -using System.IO; using System.Linq; using System.Reflection; -using System.Security; -using System.Text; -using System.Threading; -using System.Web; -using System.Web.Compilation; -using Moq; using NUnit.Framework; -using Umbraco.Core; using Umbraco.Core.Composing; -using Umbraco.Core.IO; using Umbraco.Core.Logging; using Umbraco.Tests.TestHelpers.Stubs; -using Umbraco.Web; -using Umbraco.Web.Trees; +using Umbraco.Web.BackOffice.Trees; namespace Umbraco.Tests.Composing { @@ -42,14 +29,9 @@ namespace Umbraco.Tests.Composing this.GetType().Assembly, typeof(System.Guid).Assembly, typeof(NUnit.Framework.Assert).Assembly, - typeof(Microsoft.CSharp.CSharpCodeProvider).Assembly, typeof(System.Xml.NameTable).Assembly, typeof(System.Configuration.GenericEnumConverter).Assembly, - typeof(System.Web.SiteMap).Assembly, - //typeof(TabPage).Assembly, - typeof(System.Web.Mvc.ActionResult).Assembly, typeof(TypeFinder).Assembly, - typeof(global::Umbraco.Examine.UmbracoExamineIndex).Assembly }; } @@ -69,11 +51,11 @@ namespace Umbraco.Tests.Composing var typesFound = typeFinder.FindClassesWithAttribute(_assemblies); Assert.AreEqual(0, typesFound.Count()); // 0 classes in _assemblies are marked with [Tree] - typesFound = typeFinder.FindClassesWithAttribute(new[] { typeof (UmbracoContext).Assembly }); - Assert.AreEqual(21, typesFound.Count()); // + classes in Umbraco.Web are marked with [Tree] + typesFound = typeFinder.FindClassesWithAttribute(new[] { typeof (TreeAttribute).Assembly }); + Assert.AreEqual(22, typesFound.Count()); // + classes in Umbraco.Web are marked with [Tree] typesFound = typeFinder.FindClassesWithAttribute(); - Assert.AreEqual(21, typesFound.Count()); // + classes in Umbraco.Web are marked with [Tree] + Assert.AreEqual(22, typesFound.Count()); // + classes in Umbraco.Web are marked with [Tree] } private static IProfilingLogger GetTestProfilingLogger() diff --git a/src/Umbraco.Tests.UnitTests/Umbraco.Web.Website/Controllers/SurfaceControllerTests.cs b/src/Umbraco.Tests.UnitTests/Umbraco.Web.Website/Controllers/SurfaceControllerTests.cs index 1b4630c2da..7a202d7902 100644 --- a/src/Umbraco.Tests.UnitTests/Umbraco.Web.Website/Controllers/SurfaceControllerTests.cs +++ b/src/Umbraco.Tests.UnitTests/Umbraco.Web.Website/Controllers/SurfaceControllerTests.cs @@ -15,6 +15,7 @@ using Umbraco.Tests.Testing; using Umbraco.Web; using Umbraco.Web.PublishedCache; using Umbraco.Web.Routing; +using Umbraco.Web.Security; using Umbraco.Web.Website; using Umbraco.Web.Website.Controllers; @@ -50,7 +51,8 @@ namespace Umbraco.Tests.Integration new UriUtility(hostingEnvironment), httpContextAccessor, Mock.Of(), - Mock.Of()); + Mock.Of(), + Mock.Of()); var umbracoContextReference = umbracoContextFactory.EnsureUmbracoContext(); var umbracoContext = umbracoContextReference.UmbracoContext; @@ -82,7 +84,8 @@ namespace Umbraco.Tests.Integration new UriUtility(hostingEnvironment), httpContextAccessor, Mock.Of(), - Mock.Of()); + Mock.Of(), + Mock.Of()); var umbracoContextReference = umbracoContextFactory.EnsureUmbracoContext(); var umbCtx = umbracoContextReference.UmbracoContext; @@ -118,7 +121,8 @@ namespace Umbraco.Tests.Integration new UriUtility(hostingEnvironment), httpContextAccessor, Mock.Of(), - Mock.Of()); + Mock.Of(), + Mock.Of()); var umbracoContextReference = umbracoContextFactory.EnsureUmbracoContext(); var umbracoContext = umbracoContextReference.UmbracoContext; @@ -154,7 +158,8 @@ namespace Umbraco.Tests.Integration new UriUtility(hostingEnvironment), httpContextAccessor, Mock.Of(), - Mock.Of()); + Mock.Of(), + Mock.Of()); var umbracoContextReference = umbracoContextFactory.EnsureUmbracoContext(); var umbracoContext = umbracoContextReference.UmbracoContext; diff --git a/src/Umbraco.Tests/Composing/TypeLoaderTests.cs b/src/Umbraco.Tests/Composing/TypeLoaderTests.cs index 980878d6f2..2202ca9fc7 100644 --- a/src/Umbraco.Tests/Composing/TypeLoaderTests.cs +++ b/src/Umbraco.Tests/Composing/TypeLoaderTests.cs @@ -275,7 +275,7 @@ AnotherContentFinder public void GetDataEditors() { var types = _typeLoader.GetDataEditors(); - Assert.AreEqual(39, types.Count()); + Assert.AreEqual(38, types.Count()); } /// diff --git a/src/Umbraco.Tests/Models/Mapping/ContentWebModelMappingTests.cs b/src/Umbraco.Tests/Models/Mapping/ContentWebModelMappingTests.cs deleted file mode 100644 index cc923df4b4..0000000000 --- a/src/Umbraco.Tests/Models/Mapping/ContentWebModelMappingTests.cs +++ /dev/null @@ -1,367 +0,0 @@ -using System.Globalization; -using System.Linq; -using Moq; -using NUnit.Framework; -using Umbraco.Core; -using Umbraco.Core.Configuration.UmbracoSettings; -using Umbraco.Core.Services; -using Umbraco.Core.Logging; -using Umbraco.Core.Models; -using Umbraco.Core.PropertyEditors; -using Umbraco.Core.Services.Implement; -using Umbraco.Core.Strings; -using Umbraco.Tests.TestHelpers; -using Umbraco.Tests.TestHelpers.Entities; -using Umbraco.Web.Models.ContentEditing; -using Umbraco.Tests.Testing; -using Umbraco.Web.PropertyEditors; -using Current = Umbraco.Web.Composing.Current; -using Umbraco.Core.Composing.CompositionExtensions; - -namespace Umbraco.Tests.Models.Mapping -{ - [TestFixture] - [UmbracoTest(Mapper = true, Database = UmbracoTestOptions.Database.NewSchemaPerFixture)] - public class ContentWebModelMappingTests : TestWithDatabaseBase - { - private IContentTypeService _contentTypeService; - - - protected override void Compose() - { - base.Compose(); - - Composition.ComposeFileSystems(); - - Composition.Register(_ => Mock.Of()); - Composition.Register(_ => Mock.Of()); - - // all this is required so we can validate properties... - var editor = new TextboxPropertyEditor(Mock.Of(), Mock.Of(), Mock.Of(), IOHelper, ShortStringHelper, LocalizedTextService) { Alias = "test" }; - Composition.Register(_ => new DataEditorCollection(new[] { editor })); - Composition.Register(); - var dataType = Mock.Of(); - Mock.Get(dataType).Setup(x => x.Configuration).Returns(() => new object()); - var dataTypeService = Mock.Of(); - Mock.Get(dataTypeService) - .Setup(x => x.GetDataType(It.IsAny())) - .Returns(() => dataType); - - _contentTypeService = Mock.Of(); - var mediaTypeService = Mock.Of(); - var memberTypeService = Mock.Of(); - Composition.RegisterUnique(_ => _contentTypeService); - Composition.Register(_ => ServiceContext.CreatePartial(dataTypeService: dataTypeService, contentTypeBaseServiceProvider: new ContentTypeBaseServiceProvider(_contentTypeService, mediaTypeService, memberTypeService))); - } - - [DataEditor("Test.Test", "Test", "~/Test.html")] - public class TestPropertyEditor : DataEditor - { - /// - /// The constructor will setup the property editor based on the attribute if one is found - /// - public TestPropertyEditor(ILogger logger) : base(logger, Mock.Of(), Mock.Of(), Mock.Of(),Mock.Of()) - { } - } - - private void FixUsers(IContentBase content) - { - // CreateSimpleContentType leaves CreatorId == 0 - // which used to be both the "super" user and the "default" user - // v8 is changing this, so the test would report a creator - // temp. fixing by assigning super here - // - content.CreatorId = Constants.Security.SuperUserId; - } - - [Test] - public void To_Media_Item_Simple() - { - var contentType = MockedContentTypes.CreateImageMediaType(); - Mock.Get(_contentTypeService).As().Setup(x => x.Get(It.IsAny())).Returns(contentType); - - var content = MockedMedia.CreateMediaImage(contentType, -1); - FixUsers(content); - - var result = Mapper.Map>(content); - - AssertBasics(result, content); - - foreach (var p in content.Properties) - { - AssertBasicProperty(result, p); - } - } - - [Test] - public void To_Content_Item_Simple() - { - var contentType = MockedContentTypes.CreateSimpleContentType(); - Mock.Get(_contentTypeService).As().Setup(x => x.Get(It.IsAny())).Returns(contentType); - - var content = MockedContent.CreateSimpleContent(contentType); - FixUsers(content); - - var result = Mapper.Map>(content); - - AssertBasics(result, content); - - foreach (var p in content.Properties) - { - AssertBasicProperty(result, p); - } - } - - [Test] - public void To_Content_Item_Dto() - { - var contentType = MockedContentTypes.CreateSimpleContentType(); - Mock.Get(_contentTypeService).As().Setup(x => x.Get(It.IsAny())).Returns(contentType); - - var content = MockedContent.CreateSimpleContent(contentType); - FixUsers(content); - - var result = Mapper.Map(content); - - foreach (var p in content.Properties) - { - AssertProperty(result, p); - } - } - - [Test] - public void To_Media_Item_Dto() - { - var contentType = MockedContentTypes.CreateImageMediaType(); - var content = MockedMedia.CreateMediaImage(contentType, -1); - FixUsers(content); - - var result = Mapper.Map(content); - - foreach (var p in content.Properties) - { - AssertProperty(result, p); - } - } - - [Test] - public void To_Display_Model() - { - var contentType = MockedContentTypes.CreateSimpleContentType(); - Mock.Get(_contentTypeService).As().Setup(x => x.Get(It.IsAny())).Returns(contentType); - Mock.Get(_contentTypeService).Setup(x => x.Get(It.IsAny())).Returns(contentType); - - var content = MockedContent.CreateSimpleContent(contentType); - - - FixUsers(content); - - // need ids for tabs - var id = 1; - foreach (var g in contentType.CompositionPropertyGroups) - g.Id = id++; - - var result = Mapper.Map(content); - - AssertBasics(result, content); - - var invariantContent = result.Variants.First(); - foreach (var p in content.Properties) - { - AssertBasicProperty(invariantContent, p); - AssertDisplayProperty(invariantContent, p); - } - - Assert.AreEqual(contentType.CompositionPropertyGroups.Count(), invariantContent.Tabs.Count()); - Assert.IsTrue(invariantContent.Tabs.First().IsActive); - Assert.IsTrue(invariantContent.Tabs.Except(new[] { invariantContent.Tabs.First() }).All(x => x.IsActive == false)); - } - - [Test] - public void To_Display_Model_No_Tabs() - { - var contentType = MockedContentTypes.CreateSimpleContentType(); - contentType.PropertyGroups.Clear(); - Mock.Get(_contentTypeService).As().Setup(x => x.Get(It.IsAny())).Returns(contentType); - Mock.Get(_contentTypeService).Setup(x => x.Get(It.IsAny())).Returns(contentType); - - var content = new Content("Home", -1, contentType) { Level = 1, SortOrder = 1, CreatorId = 0, WriterId = 0 }; - - var result = Mapper.Map(content); - - AssertBasics(result, content); - - var invariantContent = result.Variants.First(); - foreach (var p in content.Properties) - { - AssertBasicProperty(invariantContent, p); - AssertDisplayProperty(invariantContent, p); - } - - Assert.AreEqual(contentType.CompositionPropertyGroups.Count(), invariantContent.Tabs.Count()); - } - - [Test] - public void To_Display_Model_With_Non_Grouped_Properties() - { - var idSeed = 1; - var contentType = MockedContentTypes.CreateSimpleContentType(); - //add non-grouped properties - contentType.AddPropertyType(new PropertyType(ShortStringHelper, Constants.PropertyEditors.Aliases.TextBox, ValueStorageType.Ntext, "nonGrouped1") { Name = "Non Grouped 1", Description = "", Mandatory = false, SortOrder = 1, DataTypeId = -88 }); - contentType.AddPropertyType(new PropertyType(ShortStringHelper, Constants.PropertyEditors.Aliases.TextBox, ValueStorageType.Ntext, "nonGrouped2") { Name = "Non Grouped 2", Description = "", Mandatory = false, SortOrder = 1, DataTypeId = -88 }); - //set ids or it wont work - contentType.Id = idSeed; - foreach (var p in contentType.PropertyTypes) - { - p.Id = idSeed; - idSeed++; - } - Mock.Get(_contentTypeService).As().Setup(x => x.Get(It.IsAny())).Returns(contentType); - Mock.Get(_contentTypeService).Setup(x => x.Get(It.IsAny())).Returns(contentType); - - - var content = MockedContent.CreateSimpleContent(contentType); - FixUsers(content); - - foreach (var p in content.Properties) - { - p.Id = idSeed; - idSeed++; - } - //need ids for tabs - var id = 1; - foreach (var g in contentType.CompositionPropertyGroups) - { - g.Id = id; - id++; - } - //ensure that nothing is marked as dirty - contentType.ResetDirtyProperties(false); - //ensure that nothing is marked as dirty - content.ResetDirtyProperties(false); - - var result = Mapper.Map(content); - - AssertBasics(result, content); - - var invariantContent = result.Variants.First(); - foreach (var p in content.Properties) - { - AssertBasicProperty(invariantContent, p); - AssertDisplayProperty(invariantContent, p); - } - - Assert.AreEqual(contentType.CompositionPropertyGroups.Count(), invariantContent.Tabs.Count() - 1); - Assert.IsTrue(invariantContent.Tabs.Any(x => x.Label == ServiceContext.TextService.Localize("general/properties"))); - Assert.AreEqual(2, invariantContent.Tabs.Where(x => x.Label == ServiceContext.TextService.Localize("general/properties")).SelectMany(x => x.Properties.Where(p => p.Alias.StartsWith("_umb_") == false)).Count()); - } - - #region Assertions - - private void AssertDisplayProperty(IContentProperties result, IProperty p) - where T : ContentPropertyBasic - { - var pDto = result.Properties.SingleOrDefault(x => x.Alias == p.Alias); - Assert.IsNotNull(pDto); - - //pDto.Alias = p.Alias; - //pDto.Description = p.PropertyType.Description; - //pDto.Label = p.PropertyType.Name; - //pDto.Config = applicationContext.Services.DataTypeService.GetPreValuesByDataTypeId(p.PropertyType.DataTypeDefinitionId); - - } - - private void AssertBasics(ContentItemDisplay result, IContent content) - { - Assert.AreEqual(content.Id, result.Id); - - var ownerId = content.CreatorId; - if (ownerId != 0) - { - Assert.IsNotNull(result.Owner); - Assert.AreEqual(Constants.Security.SuperUserId, result.Owner.UserId); - Assert.AreEqual("Administrator", result.Owner.Name); - } - else - { - Assert.IsNull(result.Owner); // because, 0 is no user - } - - var invariantContent = result.Variants.First(); - - Assert.AreEqual(content.ParentId, result.ParentId); - Assert.AreEqual(content.UpdateDate, invariantContent.UpdateDate); - Assert.AreEqual(content.CreateDate, invariantContent.CreateDate); - Assert.AreEqual(content.Name, invariantContent.Name); - Assert.AreEqual(content.Properties.Count(), - ((IContentProperties)invariantContent).Properties.Count(x => x.Alias.StartsWith("_umb_") == false)); - } - - private void AssertBasics(ContentItemBasic result, TPersisted content) - where T : ContentPropertyBasic - where TPersisted : IContentBase - { - Assert.AreEqual(content.Id, result.Id); - - var ownerId = content.CreatorId; - if (ownerId != 0) - { - Assert.IsNotNull(result.Owner); - Assert.AreEqual(Constants.Security.SuperUserId, result.Owner.UserId); - Assert.AreEqual("Administrator", result.Owner.Name); - } - else - { - Assert.IsNull(result.Owner); // because, 0 is no user - } - - Assert.AreEqual(content.ParentId, result.ParentId); - Assert.AreEqual(content.UpdateDate, result.UpdateDate); - Assert.AreEqual(content.CreateDate, result.CreateDate); - Assert.AreEqual(content.Name, result.Name); - Assert.AreEqual(content.Properties.Count(), result.Properties.Count(x => x.Alias.StartsWith("_umb_") == false)); - } - - private void AssertBasicProperty(IContentProperties result, IProperty p) - where T : ContentPropertyBasic - { - var pDto = result.Properties.SingleOrDefault(x => x.Alias == p.Alias); - Assert.IsNotNull(pDto); - Assert.AreEqual(p.Alias, pDto.Alias); - Assert.AreEqual(p.Id, pDto.Id); - - if (p.GetValue() == null) - Assert.AreEqual(pDto.Value, string.Empty); - else if (p.GetValue() is decimal) - Assert.AreEqual(pDto.Value, ((decimal) p.GetValue()).ToString(NumberFormatInfo.InvariantInfo)); - else - Assert.AreEqual(pDto.Value, p.GetValue().ToString()); - } - - private void AssertProperty(IContentProperties result, IProperty p) - { - AssertBasicProperty(result, p); - - var pDto = result.Properties.SingleOrDefault(x => x.Alias == p.Alias); - Assert.IsNotNull(pDto); - Assert.AreEqual(p.PropertyType.Mandatory, pDto.IsRequired); - Assert.AreEqual(p.PropertyType.ValidationRegExp, pDto.ValidationRegExp); - Assert.AreEqual(p.PropertyType.Description, pDto.Description); - Assert.AreEqual(p.PropertyType.Name, pDto.Label); - Assert.AreEqual(ServiceContext.DataTypeService.GetDataType(p.PropertyType.DataTypeId), pDto.DataType); - Assert.AreEqual(Current.PropertyEditors[p.PropertyType.PropertyEditorAlias], pDto.PropertyEditor); - } - - private void AssertContentItem(ContentItemBasic result, T content) - where T : IContentBase - { - AssertBasics(result, content); - - foreach (var p in content.Properties) - { - AssertProperty(result, p); - } - } - #endregion - } -} diff --git a/src/Umbraco.Tests/TestHelpers/ControllerTesting/TestStartup.cs b/src/Umbraco.Tests/TestHelpers/ControllerTesting/TestStartup.cs index f038112b0b..200d7653f9 100644 --- a/src/Umbraco.Tests/TestHelpers/ControllerTesting/TestStartup.cs +++ b/src/Umbraco.Tests/TestHelpers/ControllerTesting/TestStartup.cs @@ -30,9 +30,9 @@ namespace Umbraco.Tests.TestHelpers.ControllerTesting var httpConfig = new HttpConfiguration(); // TODO: Enable this if you can't see the errors produced - //var traceWriter = httpConfig.EnableSystemDiagnosticsTracing(); - //traceWriter.IsVerbose = true; - //traceWriter.MinimumLevel = TraceLevel.Debug; + // var traceWriter = httpConfig.EnableSystemDiagnosticsTracing(); + // traceWriter.IsVerbose = true; + // traceWriter.MinimumLevel = TraceLevel.Debug; httpConfig.IncludeErrorDetailPolicy = IncludeErrorDetailPolicy.Always; diff --git a/src/Umbraco.Tests/Umbraco.Tests.csproj b/src/Umbraco.Tests/Umbraco.Tests.csproj index 5959898a87..46fb33335f 100644 --- a/src/Umbraco.Tests/Umbraco.Tests.csproj +++ b/src/Umbraco.Tests/Umbraco.Tests.csproj @@ -93,6 +93,7 @@ + @@ -145,6 +146,14 @@ + + + + + + + + @@ -212,7 +221,6 @@ - @@ -226,7 +234,6 @@ - @@ -304,7 +311,6 @@ - @@ -389,9 +395,6 @@ - - - @@ -425,10 +428,6 @@ - - - - @@ -454,7 +453,6 @@ - diff --git a/src/Umbraco.Tests/Web/Controllers/ContentControllerTests.cs b/src/Umbraco.Tests/Web/Controllers/ContentControllerTests.cs index 65259fc6ac..55629fde62 100644 --- a/src/Umbraco.Tests/Web/Controllers/ContentControllerTests.cs +++ b/src/Umbraco.Tests/Web/Controllers/ContentControllerTests.cs @@ -115,7 +115,7 @@ namespace Umbraco.Tests.Web.Controllers Composition.RegisterUnique(f => langService.Object); Composition.RegisterUnique(f => textService.Object); Composition.RegisterUnique(f => Mock.Of()); - Composition.RegisterUnique(f => new UmbracoApiControllerTypeCollection(new[] { typeof(ContentTreeController) })); + Composition.RegisterUnique(f => new UmbracoApiControllerTypeCollection(new Type[] { })); } private MultipartFormDataContent GetMultiPartRequestContent(string json) diff --git a/src/Umbraco.Web.BackOffice/Controllers/BackOfficeServerVariables.cs b/src/Umbraco.Web.BackOffice/Controllers/BackOfficeServerVariables.cs index 548afbdd88..fb23b722f4 100644 --- a/src/Umbraco.Web.BackOffice/Controllers/BackOfficeServerVariables.cs +++ b/src/Umbraco.Web.BackOffice/Controllers/BackOfficeServerVariables.cs @@ -37,7 +37,7 @@ namespace Umbraco.Web.BackOffice.Controllers private readonly IGlobalSettings _globalSettings; private readonly IUmbracoVersion _umbracoVersion; private readonly IContentSettings _contentSettings; - //private readonly TreeCollection _treeCollection; + private readonly TreeCollection _treeCollection; private readonly IHttpContextAccessor _httpContextAccessor; private readonly IHostingEnvironment _hostingEnvironment; private readonly IRuntimeSettings _settings; @@ -53,7 +53,7 @@ namespace Umbraco.Web.BackOffice.Controllers IUmbracoVersion umbracoVersion, IContentSettings contentSettings, IHttpContextAccessor httpContextAccessor, - //TreeCollection treeCollection, // TODO: If we need this we need to migrate trees + TreeCollection treeCollection, IHostingEnvironment hostingEnvironment, IRuntimeSettings settings, ISecuritySettings securitySettings, @@ -67,7 +67,7 @@ namespace Umbraco.Web.BackOffice.Controllers _umbracoVersion = umbracoVersion; _contentSettings = contentSettings ?? throw new ArgumentNullException(nameof(contentSettings)); _httpContextAccessor = httpContextAccessor; - //_treeCollection = treeCollection ?? throw new ArgumentNullException(nameof(treeCollection)); + _treeCollection = treeCollection ?? throw new ArgumentNullException(nameof(treeCollection)); _hostingEnvironment = hostingEnvironment; _settings = settings; _securitySettings = securitySettings; @@ -184,14 +184,14 @@ namespace Umbraco.Web.BackOffice.Controllers "imagesApiBaseUrl", _linkGenerator.GetUmbracoApiServiceBaseUrl( controller => controller.GetBigThumbnail("")) }, - // { - // "sectionApiBaseUrl", _linkGenerator.GetUmbracoApiServiceBaseUrl( - // controller => controller.GetSections()) - // }, - // { - // "treeApplicationApiBaseUrl", _linkGenerator.GetUmbracoApiServiceBaseUrl( - // controller => controller.GetApplicationTrees(null, null, null, TreeUse.None)) - // }, + { + "sectionApiBaseUrl", _linkGenerator.GetUmbracoApiServiceBaseUrl( + controller => controller.GetSections()) + }, + { + "treeApplicationApiBaseUrl", _linkGenerator.GetUmbracoApiServiceBaseUrl( + controller => controller.GetApplicationTrees(null, null, null, TreeUse.None)) + }, // { // "contentTypeApiBaseUrl", _linkGenerator.GetUmbracoApiServiceBaseUrl( // controller => controller.GetAllowedChildren(0)) @@ -272,18 +272,18 @@ namespace Umbraco.Web.BackOffice.Controllers "templateApiBaseUrl", _linkGenerator.GetUmbracoApiServiceBaseUrl( controller => controller.GetById(0)) }, - // { - // "memberTreeBaseUrl", _linkGenerator.GetUmbracoApiServiceBaseUrl( - // controller => controller.GetNodes("-1", null)) - // }, - // { - // "mediaTreeBaseUrl", _linkGenerator.GetUmbracoApiServiceBaseUrl( - // controller => controller.GetNodes("-1", null)) - // }, - // { - // "contentTreeBaseUrl", _linkGenerator.GetUmbracoApiServiceBaseUrl( - // controller => controller.GetNodes("-1", null)) - // }, + { + "memberTreeBaseUrl", _linkGenerator.GetUmbracoApiServiceBaseUrl( + controller => controller.GetNodes("-1", null)) + }, + { + "mediaTreeBaseUrl", _linkGenerator.GetUmbracoApiServiceBaseUrl( + controller => controller.GetNodes("-1", null)) + }, + { + "contentTreeBaseUrl", _linkGenerator.GetUmbracoApiServiceBaseUrl( + controller => controller.GetNodes("-1", null)) + }, { "tagsDataBaseUrl", _linkGenerator.GetUmbracoApiServiceBaseUrl( controller => controller.GetTags("", "", null)) @@ -447,8 +447,6 @@ namespace Umbraco.Web.BackOffice.Controllers private IEnumerable GetPluginTrees() { - // TODO: Use the code below once we migrate trees - return Enumerable.Empty(); // used to be (cached) //var treeTypes = Current.TypeLoader.GetAttributedTreeControllers(); @@ -458,20 +456,20 @@ namespace Umbraco.Web.BackOffice.Controllers // do this instead // inheriting from TreeControllerBase and marked with TreeAttribute - //foreach (var tree in _treeCollection) - //{ - // var treeType = tree.TreeControllerType; + foreach (var tree in _treeCollection) + { + var treeType = tree.TreeControllerType; - // // exclude anything marked with CoreTreeAttribute - // var coreTree = treeType.GetCustomAttribute(false); - // if (coreTree != null) continue; + // exclude anything marked with CoreTreeAttribute + var coreTree = treeType.GetCustomAttribute(false); + if (coreTree != null) continue; - // // exclude anything not marked with PluginControllerAttribute - // var pluginController = treeType.GetCustomAttribute(false); - // if (pluginController == null) continue; + // exclude anything not marked with PluginControllerAttribute + var pluginController = treeType.GetCustomAttribute(false); + if (pluginController == null) continue; - // yield return new PluginTree { Alias = tree.TreeAlias, PackageFolder = pluginController.AreaName }; - //} + yield return new PluginTree { Alias = tree.TreeAlias, PackageFolder = pluginController.AreaName }; + } } /// diff --git a/src/Umbraco.Web.BackOffice/Extensions/WebMappingProfiles.cs b/src/Umbraco.Web.BackOffice/Extensions/WebMappingProfiles.cs new file mode 100644 index 0000000000..666ad75e55 --- /dev/null +++ b/src/Umbraco.Web.BackOffice/Extensions/WebMappingProfiles.cs @@ -0,0 +1,25 @@ +using Umbraco.Core; +using Umbraco.Core.BackOffice; +using Umbraco.Core.Composing; +using Umbraco.Core.Mapping; +using Umbraco.Web.Models.Mapping; + +namespace Umbraco.Extensions +{ + public static class WebMappingProfiles + { + public static Composition ComposeWebMappingProfiles(this Composition composition) + { + composition.WithCollectionBuilder() + .Add() + .Add() + .Add(); + + composition.Register(); + composition.Register(); + composition.Register(); + + return composition; + } + } +} diff --git a/src/Umbraco.Web.BackOffice/Filters/UmbracoTreeAuthorizeAttribute.cs b/src/Umbraco.Web.BackOffice/Filters/UmbracoTreeAuthorizeAttribute.cs index d6b18b4b29..d4ec1b45e1 100644 --- a/src/Umbraco.Web.BackOffice/Filters/UmbracoTreeAuthorizeAttribute.cs +++ b/src/Umbraco.Web.BackOffice/Filters/UmbracoTreeAuthorizeAttribute.cs @@ -8,79 +8,77 @@ using Umbraco.Web.Services; namespace Umbraco.Web.BackOffice.Filters { - + /// + /// Ensures that the current user has access to the application for which the specified tree(s) belongs + /// + /// + /// This would allow a tree to be moved between sections + /// public class UmbracoTreeAuthorizeAttribute : TypeFilterAttribute { public UmbracoTreeAuthorizeAttribute(params string[] treeAliases) : base(typeof(UmbracoTreeAuthorizeFilter)) { - base.Arguments = new object[] + Arguments = new object[] { treeAliases }; } - /// - /// Ensures that the current user has access to the application for which the specified tree(s) belongs - /// - /// - /// This would allow a tree to be moved between sections - /// - private sealed class UmbracoTreeAuthorizeFilter : IAuthorizationFilter - { - /// - /// Can be used by unit tests to enable/disable this filter - /// - internal static bool Enable = true; - - private readonly ITreeService _treeService; - private readonly IWebSecurity _webSecurity; - private readonly string[] _treeAliases; - - /// - /// Constructor to set authorization to be based on a tree alias for which application security will be applied - /// - /// - /// - /// If the user has access to the application that the treeAlias is specified in, they will be authorized. - /// Multiple trees may be specified. - /// - /// - public UmbracoTreeAuthorizeFilter(ITreeService treeService, IWebSecurity webSecurity, params string[] treeAliases) + private sealed class UmbracoTreeAuthorizeFilter : IAuthorizationFilter { - _treeService = treeService ?? throw new ArgumentNullException(nameof(treeService)); - _webSecurity = webSecurity ?? throw new ArgumentNullException(nameof(webSecurity)); - _treeAliases = treeAliases; - } + /// + /// Can be used by unit tests to enable/disable this filter + /// + internal static readonly bool Enable = true; - private bool IsAuthorized() - { - if (Enable == false) + private readonly string[] _treeAliases; + + private readonly ITreeService _treeService; + private readonly IWebSecurity _webSecurity; + + /// + /// Constructor to set authorization to be based on a tree alias for which application security will be applied + /// + /// + /// + /// If the user has access to the application that the treeAlias is specified in, they will be authorized. + /// Multiple trees may be specified. + /// + /// + public UmbracoTreeAuthorizeFilter(ITreeService treeService, IWebSecurity webSecurity, + params string[] treeAliases) { - return true; + _treeService = treeService ?? throw new ArgumentNullException(nameof(treeService)); + _webSecurity = webSecurity ?? throw new ArgumentNullException(nameof(webSecurity)); + _treeAliases = treeAliases; } - var apps = _treeAliases.Select(x => _treeService - .GetByAlias(x)) - .WhereNotNull() - .Select(x => x.SectionAlias) - .Distinct() - .ToArray(); - - return _webSecurity.CurrentUser != null - && apps.Any(app => _webSecurity.UserHasSectionAccess( - app, _webSecurity.CurrentUser)); - } - - public void OnAuthorization(AuthorizationFilterContext context) - { - if (!IsAuthorized()) + public void OnAuthorization(AuthorizationFilterContext context) { + if (!IsAuthorized()) + { + context.Result = new ForbidResult(); + } + } - context.Result = new ForbidResult(); + private bool IsAuthorized() + { + if (Enable == false) + { + return true; + } + + var apps = _treeAliases.Select(x => _treeService + .GetByAlias(x)) + .WhereNotNull() + .Select(x => x.SectionAlias) + .Distinct() + .ToArray(); + + return _webSecurity.CurrentUser != null + && apps.Any(app => _webSecurity.UserHasSectionAccess( + app, _webSecurity.CurrentUser)); } } } - } - - } diff --git a/src/Umbraco.Web.BackOffice/Mapping/CommonTreeNodeMapper.cs b/src/Umbraco.Web.BackOffice/Mapping/CommonTreeNodeMapper.cs new file mode 100644 index 0000000000..bd03ef9a88 --- /dev/null +++ b/src/Umbraco.Web.BackOffice/Mapping/CommonTreeNodeMapper.cs @@ -0,0 +1,30 @@ +using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Mvc; +using Microsoft.AspNetCore.Mvc.Routing; +using Microsoft.AspNetCore.Routing; +using Umbraco.Core.Models; +using Umbraco.Extensions; +using Umbraco.Web.Common.Controllers; +using Umbraco.Web.Trees; + +namespace Umbraco.Web.Models.Mapping +{ + public class CommonTreeNodeMapper + { + private readonly LinkGenerator _linkGenerator; + + + public CommonTreeNodeMapper( LinkGenerator linkGenerator) + { + _linkGenerator = linkGenerator; + } + + + public string GetTreeNodeUrl(IContentBase source) + where TController : UmbracoApiController, ITreeNodeController + { + return _linkGenerator.GetUmbracoApiService(controller => controller.GetTreeNode(source.Key.ToString("N"), null)); + } + + } +} diff --git a/src/Umbraco.Web.BackOffice/Mapping/ContentMapDefinition.cs b/src/Umbraco.Web.BackOffice/Mapping/ContentMapDefinition.cs new file mode 100644 index 0000000000..aa3730f54f --- /dev/null +++ b/src/Umbraco.Web.BackOffice/Mapping/ContentMapDefinition.cs @@ -0,0 +1,325 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using Umbraco.Core; +using Umbraco.Core.Dictionary; +using Umbraco.Core.Logging; +using Umbraco.Core.Mapping; +using Umbraco.Core.Models; +using Umbraco.Core.Models.PublishedContent; +using Umbraco.Core.Models.Membership; +using Umbraco.Core.Services; +using Umbraco.Web.Models.ContentEditing; +using Umbraco.Web.Routing; +using Umbraco.Web.Trees; + +namespace Umbraco.Web.Models.Mapping +{ + /// + /// Declares how model mappings for content + /// + internal class ContentMapDefinition : IMapDefinition + { + private readonly CommonMapper _commonMapper; + private readonly CommonTreeNodeMapper _commonTreeNodeMapper; + private readonly ICultureDictionary _cultureDictionary; + private readonly ILocalizedTextService _localizedTextService; + private readonly IContentService _contentService; + private readonly IContentTypeService _contentTypeService; + private readonly IFileService _fileService; + private readonly IUmbracoContextAccessor _umbracoContextAccessor; + private readonly IPublishedRouter _publishedRouter; + private readonly ILocalizationService _localizationService; + private readonly ILogger _logger; + private readonly IUserService _userService; + private readonly IEntityService _entityService; + private readonly IVariationContextAccessor _variationContextAccessor; + private readonly IPublishedUrlProvider _publishedUrlProvider; + private readonly UriUtility _uriUtility; + private readonly TabsAndPropertiesMapper _tabsAndPropertiesMapper; + private readonly ContentSavedStateMapper _stateMapper; + private readonly ContentBasicSavedStateMapper _basicStateMapper; + private readonly ContentVariantMapper _contentVariantMapper; + + + public ContentMapDefinition(CommonMapper commonMapper, CommonTreeNodeMapper commonTreeNodeMapper, ICultureDictionary cultureDictionary, ILocalizedTextService localizedTextService, IContentService contentService, IContentTypeService contentTypeService, + IFileService fileService, IUmbracoContextAccessor umbracoContextAccessor, IPublishedRouter publishedRouter, ILocalizationService localizationService, ILogger logger, + IUserService userService, IVariationContextAccessor variationContextAccessor, IContentTypeBaseServiceProvider contentTypeBaseServiceProvider, UriUtility uriUtility, IPublishedUrlProvider publishedUrlProvider, IEntityService entityService) + { + _commonMapper = commonMapper; + _commonTreeNodeMapper = commonTreeNodeMapper; + _cultureDictionary = cultureDictionary; + _localizedTextService = localizedTextService; + _contentService = contentService; + _contentTypeService = contentTypeService; + _fileService = fileService; + _umbracoContextAccessor = umbracoContextAccessor; + _publishedRouter = publishedRouter; + _localizationService = localizationService; + _logger = logger; + _userService = userService; + _entityService = entityService; + _variationContextAccessor = variationContextAccessor; + _uriUtility = uriUtility; + _publishedUrlProvider = publishedUrlProvider; + + _tabsAndPropertiesMapper = new TabsAndPropertiesMapper(cultureDictionary, localizedTextService, contentTypeBaseServiceProvider); + _stateMapper = new ContentSavedStateMapper(); + _basicStateMapper = new ContentBasicSavedStateMapper(); + _contentVariantMapper = new ContentVariantMapper(_localizationService, localizedTextService); + } + + public void DefineMaps(UmbracoMapper mapper) + { + mapper.Define((source, context) => new ContentPropertyCollectionDto(), Map); + mapper.Define((source, context) => new ContentItemDisplay(), Map); + mapper.Define((source, context) => new ContentVariantDisplay(), Map); + mapper.Define>((source, context) => new ContentItemBasic(), Map); + } + + // Umbraco.Code.MapAll + private static void Map(IContent source, ContentPropertyCollectionDto target, MapperContext context) + { + target.Properties = context.MapEnumerable(source.Properties); + } + + // Umbraco.Code.MapAll -AllowPreview -Errors -PersistedContent + private void Map(IContent source, ContentItemDisplay target, MapperContext context) + { + target.AllowedActions = GetActions(source); + target.AllowedTemplates = GetAllowedTemplates(source); + target.ContentApps = _commonMapper.GetContentApps(source); + target.ContentTypeId = source.ContentType.Id; + target.ContentTypeAlias = source.ContentType.Alias; + target.ContentTypeName = _localizedTextService.UmbracoDictionaryTranslate(_cultureDictionary, source.ContentType.Name); + target.DocumentType = _commonMapper.GetContentType(source, context); + target.Icon = source.ContentType.Icon; + target.Id = source.Id; + target.IsBlueprint = source.Blueprint; + target.IsChildOfListView = DetermineIsChildOfListView(source, context); + target.IsContainer = source.ContentType.IsContainer; + target.IsElement = source.ContentType.IsElement; + target.Key = source.Key; + target.Owner = _commonMapper.GetOwner(source, context); + target.ParentId = source.ParentId; + target.Path = source.Path; + target.SortOrder = source.SortOrder; + target.TemplateAlias = GetDefaultTemplate(source); + target.TemplateId = source.TemplateId ?? default; + target.Trashed = source.Trashed; + target.TreeNodeUrl = _commonTreeNodeMapper.GetTreeNodeUrl(source); + target.Udi = Udi.Create(source.Blueprint ? Constants.UdiEntityType.DocumentBlueprint : Constants.UdiEntityType.Document, source.Key); + target.UpdateDate = source.UpdateDate; + target.Updater = _commonMapper.GetCreator(source, context); + target.Urls = GetUrls(source); + target.Variants = _contentVariantMapper.Map(source, context); + + target.ContentDto = new ContentPropertyCollectionDto(); + target.ContentDto.Properties = context.MapEnumerable(source.Properties); + } + + // Umbraco.Code.MapAll -Segment -Language -DisplayName + private void Map(IContent source, ContentVariantDisplay target, MapperContext context) + { + target.CreateDate = source.CreateDate; + target.ExpireDate = GetScheduledDate(source, ContentScheduleAction.Expire, context); + target.Name = source.Name; + target.PublishDate = source.PublishDate; + target.ReleaseDate = GetScheduledDate(source, ContentScheduleAction.Release, context); + target.State = _stateMapper.Map(source, context); + target.Tabs = _tabsAndPropertiesMapper.Map(source, context); + target.UpdateDate = source.UpdateDate; + } + + // Umbraco.Code.MapAll -Alias + private void Map(IContent source, ContentItemBasic target, MapperContext context) + { + target.ContentTypeId = source.ContentType.Id; + target.ContentTypeAlias = source.ContentType.Alias; + target.CreateDate = source.CreateDate; + target.Edited = source.Edited; + target.Icon = source.ContentType.Icon; + target.Id = source.Id; + target.Key = source.Key; + target.Name = GetName(source, context); + target.Owner = _commonMapper.GetOwner(source, context); + target.ParentId = source.ParentId; + target.Path = source.Path; + target.Properties = context.MapEnumerable(source.Properties); + target.SortOrder = source.SortOrder; + target.State = _basicStateMapper.Map(source, context); + target.Trashed = source.Trashed; + target.Udi = Udi.Create(source.Blueprint ? Constants.UdiEntityType.DocumentBlueprint : Constants.UdiEntityType.Document, source.Key); + target.UpdateDate = GetUpdateDate(source, context); + target.Updater = _commonMapper.GetCreator(source, context); + target.VariesByCulture = source.ContentType.VariesByCulture(); + } + + private IEnumerable GetActions(IContent source) + { + var umbracoContext = _umbracoContextAccessor.UmbracoContext; + + //cannot check permissions without a context + if (umbracoContext == null) + return Enumerable.Empty(); + + string path; + if (source.HasIdentity) + path = source.Path; + else + { + var parent = _contentService.GetById(source.ParentId); + path = parent == null ? "-1" : parent.Path; + } + + // TODO: This is certainly not ideal usage here - perhaps the best way to deal with this in the future is + // with the IUmbracoContextAccessor. In the meantime, if used outside of a web app this will throw a null + // reference exception :( + return _userService.GetPermissionsForPath(umbracoContext.Security.CurrentUser, path).GetAllPermissions(); + } + + private UrlInfo[] GetUrls(IContent source) + { + if (source.ContentType.IsElement) + return Array.Empty(); + + var umbracoContext = _umbracoContextAccessor.UmbracoContext; + + var urls = umbracoContext == null + ? new[] { UrlInfo.Message("Cannot generate urls without a current Umbraco Context") } + : source.GetContentUrls(_publishedRouter, umbracoContext, _localizationService, _localizedTextService, _contentService, _variationContextAccessor, _logger, _uriUtility, _publishedUrlProvider).ToArray(); + + return urls; + } + + private DateTime GetUpdateDate(IContent source, MapperContext context) + { + // invariant = global date + if (!source.ContentType.VariesByCulture()) return source.UpdateDate; + + // variant = depends on culture + var culture = context.GetCulture(); + + // if there's no culture here, the issue is somewhere else (UI, whatever) - throw! + if (culture == null) + throw new InvalidOperationException("Missing culture in mapping options."); + + // if we don't have a date for a culture, it means the culture is not available, and + // hey we should probably not be mapping it, but it's too late, return a fallback date + var date = source.GetUpdateDate(culture); + return date ?? source.UpdateDate; + } + + private string GetName(IContent source, MapperContext context) + { + // invariant = only 1 name + if (!source.ContentType.VariesByCulture()) return source.Name; + + // variant = depends on culture + var culture = context.GetCulture(); + + // if there's no culture here, the issue is somewhere else (UI, whatever) - throw! + if (culture == null) + throw new InvalidOperationException("Missing culture in mapping options."); + + // if we don't have a name for a culture, it means the culture is not available, and + // hey we should probably not be mapping it, but it's too late, return a fallback name + return source.CultureInfos.TryGetValue(culture, out var name) && !name.Name.IsNullOrWhiteSpace() ? name.Name : $"({source.Name})"; + } + + /// + /// Checks if the content item is a descendant of a list view + /// + /// + /// + /// + /// Returns true if the content item is a descendant of a list view and where the content is + /// not a current user's start node. + /// + /// + /// We must check if it's the current user's start node because in that case we will actually be + /// rendering the tree node underneath the list view to visually show context. In this case we return + /// false because the item is technically not being rendered as part of a list view but instead as a + /// real tree node. If we didn't perform this check then tree syncing wouldn't work correctly. + /// + private bool DetermineIsChildOfListView(IContent source, MapperContext context) + { + var userStartNodes = Array.Empty(); + + // In cases where a user's start node is below a list view, we will actually render + // out the tree to that start node and in that case for that start node, we want to return + // false here. + if (context.HasItems && context.Items.TryGetValue("CurrentUser", out var usr) && usr is IUser currentUser) + { + userStartNodes = currentUser.CalculateContentStartNodeIds(_entityService); + if (!userStartNodes.Contains(Constants.System.Root)) + { + // return false if this is the user's actual start node, the node will be rendered in the tree + // regardless of if it's a list view or not + if (userStartNodes.Contains(source.Id)) + return false; + } + } + + var parent = _contentService.GetParent(source); + + if (parent == null) + return false; + + var pathParts = parent.Path.Split(',').Select(x => int.TryParse(x, out var i) ? i : 0).ToList(); + + // reduce the path parts so we exclude top level content items that + // are higher up than a user's start nodes + foreach (var n in userStartNodes) + { + var index = pathParts.IndexOf(n); + if (index != -1) + { + // now trim all top level start nodes to the found index + for (var i = 0; i < index; i++) + { + pathParts.RemoveAt(0); + } + } + } + + return parent.ContentType.IsContainer || _contentTypeService.HasContainerInPath(pathParts.ToArray()); + } + + + private DateTime? GetScheduledDate(IContent source, ContentScheduleAction action, MapperContext context) + { + var culture = context.GetCulture() ?? string.Empty; + var schedule = source.ContentSchedule.GetSchedule(culture, action); + return schedule.FirstOrDefault()?.Date; // take the first, it's ordered by date + } + + private IDictionary GetAllowedTemplates(IContent source) + { + var contentType = _contentTypeService.Get(source.ContentTypeId); + + return contentType.AllowedTemplates + .Where(t => t.Alias.IsNullOrWhiteSpace() == false && t.Name.IsNullOrWhiteSpace() == false) + .ToDictionary(t => t.Alias, t => _localizedTextService.UmbracoDictionaryTranslate(_cultureDictionary, t.Name)); + } + + private string GetDefaultTemplate(IContent source) + { + if (source == null) + return null; + + // If no template id was set... + if (!source.TemplateId.HasValue) + { + // ... and no default template is set, return null... + // ... otherwise return the content type default template alias. + return string.IsNullOrWhiteSpace(source.ContentType.DefaultTemplate?.Alias) + ? null + : source.ContentType.DefaultTemplate?.Alias; + } + + var template = _fileService.GetTemplate(source.TemplateId.Value); + return template.Alias; + } + } +} diff --git a/src/Umbraco.Web.BackOffice/Mapping/MediaMapDefinition.cs b/src/Umbraco.Web.BackOffice/Mapping/MediaMapDefinition.cs new file mode 100644 index 0000000000..0a7bdb0026 --- /dev/null +++ b/src/Umbraco.Web.BackOffice/Mapping/MediaMapDefinition.cs @@ -0,0 +1,111 @@ +using Umbraco.Core; +using Umbraco.Core.Dictionary; +using Umbraco.Core.Logging; +using Umbraco.Core.Mapping; +using Umbraco.Core.Models; +using Umbraco.Core.PropertyEditors; +using Umbraco.Core.Services; +using Umbraco.Web.Models.ContentEditing; +using Umbraco.Web.Trees; +using Umbraco.Core.Configuration.UmbracoSettings; +using System; + +namespace Umbraco.Web.Models.Mapping +{ + /// + /// Declares model mappings for media. + /// + public class MediaMapDefinition : IMapDefinition + { + private readonly CommonMapper _commonMapper; + private readonly CommonTreeNodeMapper _commonTreeNodeMapper; + private readonly IMediaService _mediaService; + private readonly IMediaTypeService _mediaTypeService; + private readonly MediaUrlGeneratorCollection _mediaUrlGenerators; + private readonly TabsAndPropertiesMapper _tabsAndPropertiesMapper; + private readonly IContentSettings _contentSettings; + + public MediaMapDefinition(ICultureDictionary cultureDictionary, CommonMapper commonMapper, CommonTreeNodeMapper commonTreeNodeMapper, IMediaService mediaService, IMediaTypeService mediaTypeService, + ILocalizedTextService localizedTextService, MediaUrlGeneratorCollection mediaUrlGenerators, IContentSettings contentSettings, IContentTypeBaseServiceProvider contentTypeBaseServiceProvider) + { + _commonMapper = commonMapper; + _commonTreeNodeMapper = commonTreeNodeMapper; + _mediaService = mediaService; + _mediaTypeService = mediaTypeService; + _mediaUrlGenerators = mediaUrlGenerators; + _contentSettings = contentSettings ?? throw new ArgumentNullException(nameof(contentSettings)); + + _tabsAndPropertiesMapper = new TabsAndPropertiesMapper(cultureDictionary, localizedTextService, contentTypeBaseServiceProvider); + } + + public void DefineMaps(UmbracoMapper mapper) + { + mapper.Define((source, context) => new ContentPropertyCollectionDto(), Map); + mapper.Define((source, context) => new MediaItemDisplay(), Map); + mapper.Define>((source, context) => new ContentItemBasic(), Map); + } + + // Umbraco.Code.MapAll + private static void Map(IMedia source, ContentPropertyCollectionDto target, MapperContext context) + { + target.Properties = context.MapEnumerable(source.Properties); + } + + // Umbraco.Code.MapAll -Properties -Errors -Edited -Updater -Alias -IsContainer + private void Map(IMedia source, MediaItemDisplay target, MapperContext context) + { + target.ContentApps = _commonMapper.GetContentApps(source); + target.ContentType = _commonMapper.GetContentType(source, context); + target.ContentTypeId = source.ContentType.Id; + target.ContentTypeAlias = source.ContentType.Alias; + target.ContentTypeName = source.ContentType.Name; + target.CreateDate = source.CreateDate; + target.Icon = source.ContentType.Icon; + target.Id = source.Id; + target.IsChildOfListView = DetermineIsChildOfListView(source); + target.Key = source.Key; + target.MediaLink = string.Join(",", source.GetUrls(_contentSettings, _mediaUrlGenerators)); + target.Name = source.Name; + target.Owner = _commonMapper.GetOwner(source, context); + target.ParentId = source.ParentId; + target.Path = source.Path; + target.SortOrder = source.SortOrder; + target.State = null; + target.Tabs = _tabsAndPropertiesMapper.Map(source, context); + target.Trashed = source.Trashed; + target.TreeNodeUrl = _commonTreeNodeMapper.GetTreeNodeUrl(source); + target.Udi = Udi.Create(Constants.UdiEntityType.Media, source.Key); + target.UpdateDate = source.UpdateDate; + target.VariesByCulture = source.ContentType.VariesByCulture(); + } + + // Umbraco.Code.MapAll -Edited -Updater -Alias + private void Map(IMedia source, ContentItemBasic target, MapperContext context) + { + target.ContentTypeId = source.ContentType.Id; + target.ContentTypeAlias = source.ContentType.Alias; + target.CreateDate = source.CreateDate; + target.Icon = source.ContentType.Icon; + target.Id = source.Id; + target.Key = source.Key; + target.Name = source.Name; + target.Owner = _commonMapper.GetOwner(source, context); + target.ParentId = source.ParentId; + target.Path = source.Path; + target.Properties = context.MapEnumerable(source.Properties); + target.SortOrder = source.SortOrder; + target.State = null; + target.Trashed = source.Trashed; + target.Udi = Udi.Create(Constants.UdiEntityType.Media, source.Key); + target.UpdateDate = source.UpdateDate; + target.VariesByCulture = source.ContentType.VariesByCulture(); + } + + private bool DetermineIsChildOfListView(IMedia source) + { + // map the IsChildOfListView (this is actually if it is a descendant of a list view!) + var parent = _mediaService.GetParent(source); + return parent != null && (parent.ContentType.IsContainer || _mediaTypeService.HasContainerInPath(parent.Path)); + } + } +} diff --git a/src/Umbraco.Web.BackOffice/Mapping/MemberMapDefinition.cs b/src/Umbraco.Web.BackOffice/Mapping/MemberMapDefinition.cs new file mode 100644 index 0000000000..cf001b17db --- /dev/null +++ b/src/Umbraco.Web.BackOffice/Mapping/MemberMapDefinition.cs @@ -0,0 +1,104 @@ +using Microsoft.AspNetCore.Http; +using Umbraco.Core; +using Umbraco.Core.Mapping; +using Umbraco.Core.Models; +using Umbraco.Web.Models.ContentEditing; +using Umbraco.Web.Trees; + +namespace Umbraco.Web.Models.Mapping +{ + /// + /// Declares model mappings for members. + /// + public class MemberMapDefinition : IMapDefinition + { + private readonly CommonMapper _commonMapper; + private readonly CommonTreeNodeMapper _commonTreeNodeMapper; + private readonly MemberTabsAndPropertiesMapper _tabsAndPropertiesMapper; + private readonly IHttpContextAccessor _httpContextAccessor; + + public MemberMapDefinition(CommonMapper commonMapper, CommonTreeNodeMapper commonTreeNodeMapper, MemberTabsAndPropertiesMapper tabsAndPropertiesMapper, IHttpContextAccessor httpContextAccessor) + { + _commonMapper = commonMapper; + _commonTreeNodeMapper = commonTreeNodeMapper; + + _tabsAndPropertiesMapper = tabsAndPropertiesMapper; + _httpContextAccessor = httpContextAccessor; + } + + public void DefineMaps(UmbracoMapper mapper) + { + mapper.Define((source, context) => new MemberDisplay(), Map); + mapper.Define((source, context) => new MemberBasic(), Map); + mapper.Define((source, context) => new MemberGroupDisplay(), Map); + mapper.Define((source, context) => new ContentPropertyCollectionDto(), Map); + } + + // Umbraco.Code.MapAll -Properties -Errors -Edited -Updater -Alias -IsChildOfListView + // Umbraco.Code.MapAll -Trashed -IsContainer -VariesByCulture + private void Map(IMember source, MemberDisplay target, MapperContext context) + { + target.ContentApps = _commonMapper.GetContentApps(source); + target.ContentTypeId = source.ContentType.Id; + target.ContentTypeAlias = source.ContentType.Alias; + target.ContentTypeName = source.ContentType.Name; + target.CreateDate = source.CreateDate; + target.Email = source.Email; + target.Icon = source.ContentType.Icon; + target.Id = source.Id; + target.Key = source.Key; + target.Name = source.Name; + target.Owner = _commonMapper.GetOwner(source, context); + target.ParentId = source.ParentId; + target.Path = source.Path; + target.SortOrder = source.SortOrder; + target.State = null; + target.Tabs = _tabsAndPropertiesMapper.Map(source, context); + target.TreeNodeUrl = _commonTreeNodeMapper.GetTreeNodeUrl(source); + target.Udi = Udi.Create(Constants.UdiEntityType.Member, source.Key); + target.UpdateDate = source.UpdateDate; + target.Username = source.Username; + } + + // Umbraco.Code.MapAll -Trashed -Edited -Updater -Alias -VariesByCulture + private void Map(IMember source, MemberBasic target, MapperContext context) + { + target.ContentTypeId = source.ContentType.Id; + target.ContentTypeAlias = source.ContentType.Alias; + target.CreateDate = source.CreateDate; + target.Email = source.Email; + target.Icon = source.ContentType.Icon; + target.Id = int.MaxValue; + target.Key = source.Key; + target.Name = source.Name; + target.Owner = _commonMapper.GetOwner(source, context); + target.ParentId = source.ParentId; + target.Path = source.Path; + target.Properties = context.MapEnumerable(source.Properties); + target.SortOrder = source.SortOrder; + target.State = null; + target.Udi = Udi.Create(Constants.UdiEntityType.Member, source.Key); + target.UpdateDate = source.UpdateDate; + target.Username = source.Username; + } + + // Umbraco.Code.MapAll -Icon -Trashed -ParentId -Alias + private void Map(IMemberGroup source, MemberGroupDisplay target, MapperContext context) + { + target.Id = source.Id; + target.Key = source.Key; + target.Name = source.Name; + target.Path = $"-1,{source.Id}"; + target.Udi = Udi.Create(Constants.UdiEntityType.MemberGroup, source.Key); + } + + // Umbraco.Code.MapAll + private static void Map(IMember source, ContentPropertyCollectionDto target, MapperContext context) + { + target.Properties = context.MapEnumerable(source.Properties); + } + + + + } +} diff --git a/src/Umbraco.Web.BackOffice/Runtime/BackOfficeComposer.cs b/src/Umbraco.Web.BackOffice/Runtime/BackOfficeComposer.cs index 77c0e87eeb..3bd2635bc1 100644 --- a/src/Umbraco.Web.BackOffice/Runtime/BackOfficeComposer.cs +++ b/src/Umbraco.Web.BackOffice/Runtime/BackOfficeComposer.cs @@ -1,12 +1,16 @@ using System.Linq; using Umbraco.Core; using Umbraco.Core.Composing; +using Umbraco.Core.Hosting; +using Umbraco.Core.IO; +using Umbraco.Core.Logging; using Umbraco.Extensions; using Umbraco.Web.BackOffice.Controllers; using Umbraco.Web.BackOffice.Routing; using Umbraco.Web.BackOffice.Security; using Umbraco.Web.BackOffice.Trees; using Umbraco.Web.Common.Runtime; +using Umbraco.Web.Trees; namespace Umbraco.Web.BackOffice.Runtime { @@ -31,6 +35,16 @@ namespace Umbraco.Web.BackOffice.Runtime var umbracoApiControllerTypes = composition.TypeLoader.GetUmbracoApiControllers().ToList(); composition.Trees() .AddTreeControllers(umbracoApiControllerTypes.Where(x => typeof(TreeControllerBase).IsAssignableFrom(x))); + + + composition.ComposeWebMappingProfiles(); + + composition.RegisterUniqueFor(factory => + new PhysicalFileSystem( + factory.GetInstance(), + factory.GetInstance(), + factory.GetInstance(), + "~/")); } } } diff --git a/src/Umbraco.Web.BackOffice/Trees/ApplicationTreeController.cs b/src/Umbraco.Web.BackOffice/Trees/ApplicationTreeController.cs index 7728ee017a..c9bcf01fad 100644 --- a/src/Umbraco.Web.BackOffice/Trees/ApplicationTreeController.cs +++ b/src/Umbraco.Web.BackOffice/Trees/ApplicationTreeController.cs @@ -2,18 +2,15 @@ using System.Collections.Generic; using System.Linq; using System.Net; -using System.Net.Http; using System.Reflection; using System.Threading.Tasks; using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Mvc; -using Microsoft.AspNetCore.Mvc.Abstractions; using Microsoft.AspNetCore.Mvc.Controllers; using Microsoft.AspNetCore.Routing; using Microsoft.Extensions.Primitives; using Umbraco.Core; using Umbraco.Core.Services; -using Umbraco.Extensions; using Umbraco.Web.BackOffice.Controllers; using Umbraco.Web.BackOffice.Trees; using Umbraco.Web.Common.Attributes; diff --git a/src/Umbraco.Web/Trees/ContentBlueprintTreeController.cs b/src/Umbraco.Web.BackOffice/Trees/ContentBlueprintTreeController.cs similarity index 65% rename from src/Umbraco.Web/Trees/ContentBlueprintTreeController.cs rename to src/Umbraco.Web.BackOffice/Trees/ContentBlueprintTreeController.cs index 2218142b90..5b7ffd2e05 100644 --- a/src/Umbraco.Web/Trees/ContentBlueprintTreeController.cs +++ b/src/Umbraco.Web.BackOffice/Trees/ContentBlueprintTreeController.cs @@ -1,19 +1,16 @@ -using System.Linq; -using System.Net.Http.Formatting; +using System; +using System.Linq; +using Microsoft.AspNetCore.Http; using Umbraco.Core; -using Umbraco.Core.Cache; -using Umbraco.Core.Configuration; -using Umbraco.Core.Logging; -using Umbraco.Core.Mapping; using Umbraco.Core.Models; using Umbraco.Core.Models.Entities; -using Umbraco.Core.Persistence; using Umbraco.Core.Services; using Umbraco.Web.Actions; +using Umbraco.Web.BackOffice.Filters; +using Umbraco.Web.BackOffice.Trees; +using Umbraco.Web.Common.Attributes; using Umbraco.Web.Models.Trees; -using Umbraco.Web.Mvc; -using Umbraco.Web.Routing; -using Umbraco.Web.WebApi.Filters; +using Umbraco.Web.WebApi; using Constants = Umbraco.Core.Constants; namespace Umbraco.Web.Trees @@ -31,24 +28,26 @@ namespace Umbraco.Web.Trees public class ContentBlueprintTreeController : TreeController { private readonly IMenuItemCollectionFactory _menuItemCollectionFactory; + private readonly IContentService _contentService; + private readonly IContentTypeService _contentTypeService; + private readonly IEntityService _entityService; public ContentBlueprintTreeController( - IGlobalSettings globalSettings, - IUmbracoContextAccessor umbracoContextAccessor, - ISqlContext sqlContext, - ServiceContext services, - AppCaches appCaches, - IProfilingLogger logger, - IRuntimeState runtimeState, - UmbracoMapper umbracoMapper, - IPublishedUrlProvider publishedUrlProvider, - IMenuItemCollectionFactory menuItemCollectionFactory) - : base(globalSettings, umbracoContextAccessor, sqlContext, services, appCaches, logger, runtimeState, umbracoMapper, publishedUrlProvider) + ILocalizedTextService localizedTextService, + UmbracoApiControllerTypeCollection umbracoApiControllerTypeCollection, + IMenuItemCollectionFactory menuItemCollectionFactory, + IContentService contentService, + IContentTypeService contentTypeService, + IEntityService entityService) + : base(localizedTextService, umbracoApiControllerTypeCollection) { - _menuItemCollectionFactory = menuItemCollectionFactory; + _menuItemCollectionFactory = menuItemCollectionFactory ?? throw new ArgumentNullException(nameof(menuItemCollectionFactory)); + _contentService = contentService ?? throw new ArgumentNullException(nameof(contentService)); + _contentTypeService = contentTypeService ?? throw new ArgumentNullException(nameof(contentTypeService)); + _entityService = entityService ?? throw new ArgumentNullException(nameof(entityService)); } - protected override TreeNode CreateRootNode(FormDataCollection queryStrings) + protected override TreeNode CreateRootNode(FormCollection queryStrings) { var root = base.CreateRootNode(queryStrings); @@ -56,16 +55,16 @@ namespace Umbraco.Web.Trees root.RoutePath = $"{Constants.Applications.Settings}/{Constants.Trees.ContentBlueprints}/intro"; //check if there are any content blueprints - root.HasChildren = Services.ContentService.GetBlueprintsForContentTypes().Any(); + root.HasChildren = _contentService.GetBlueprintsForContentTypes().Any(); return root; } - protected override TreeNodeCollection GetTreeNodes(string id, FormDataCollection queryStrings) + protected override TreeNodeCollection GetTreeNodes(string id, FormCollection queryStrings) { var nodes = new TreeNodeCollection(); //get all blueprints - var entities = Services.EntityService.GetChildren(Constants.System.Root, UmbracoObjectTypes.DocumentBlueprint).ToArray(); + var entities = _entityService.GetChildren(Constants.System.Root, UmbracoObjectTypes.DocumentBlueprint).ToArray(); //check if we're rendering the root in which case we'll render the content types that have blueprints if (id == Constants.System.RootString) @@ -73,12 +72,12 @@ namespace Umbraco.Web.Trees //get all blueprint content types var contentTypeAliases = entities.Select(x => ((IContentEntitySlim) x).ContentTypeAlias).Distinct(); //get the ids - var contentTypeIds = Services.ContentTypeService.GetAllContentTypeIds(contentTypeAliases.ToArray()).ToArray(); + var contentTypeIds = _contentTypeService.GetAllContentTypeIds(contentTypeAliases.ToArray()).ToArray(); //now get the entities ... it's a bit round about but still smaller queries than getting all document types var docTypeEntities = contentTypeIds.Length == 0 ? new IUmbracoEntity[0] - : Services.EntityService.GetAll(UmbracoObjectTypes.DocumentType, contentTypeIds).ToArray(); + : _entityService.GetAll(UmbracoObjectTypes.DocumentType, contentTypeIds).ToArray(); nodes.AddRange(docTypeEntities .Select(entity => @@ -96,7 +95,7 @@ namespace Umbraco.Web.Trees var intId = id.TryConvertTo(); //Get the content type - var ct = Services.ContentTypeService.Get(intId.Result); + var ct = _contentTypeService.Get(intId.Result); if (ct == null) return nodes; var blueprintsForDocType = entities.Where(x => ct.Alias == ((IContentEntitySlim) x).ContentTypeAlias); @@ -111,31 +110,31 @@ namespace Umbraco.Web.Trees return nodes; } - protected override MenuItemCollection GetMenuForNode(string id, FormDataCollection queryStrings) + protected override MenuItemCollection GetMenuForNode(string id, FormCollection queryStrings) { var menu = _menuItemCollectionFactory.Create(); if (id == Constants.System.RootString) { // root actions - menu.Items.Add(Services.TextService, opensDialog: true); - menu.Items.Add(new RefreshNode(Services.TextService, true)); + menu.Items.Add(LocalizedTextService, opensDialog: true); + menu.Items.Add(new RefreshNode(LocalizedTextService, true)); return menu; } - var cte = Services.EntityService.Get(int.Parse(id), UmbracoObjectTypes.DocumentType); + var cte = _entityService.Get(int.Parse(id), UmbracoObjectTypes.DocumentType); //only refresh & create if it's a content type if (cte != null) { - var ct = Services.ContentTypeService.Get(cte.Id); - var createItem = menu.Items.Add(Services.TextService, opensDialog: true); + var ct = _contentTypeService.Get(cte.Id); + var createItem = menu.Items.Add(LocalizedTextService, opensDialog: true); createItem.NavigateToRoute("/settings/contentBlueprints/edit/-1?create=true&doctype=" + ct.Alias); - menu.Items.Add(new RefreshNode(Services.TextService, true)); + menu.Items.Add(new RefreshNode(LocalizedTextService, true)); return menu; } - menu.Items.Add(Services.TextService, opensDialog: true); + menu.Items.Add(LocalizedTextService, opensDialog: true); return menu; } diff --git a/src/Umbraco.Web/Trees/ContentTreeController.cs b/src/Umbraco.Web.BackOffice/Trees/ContentTreeController.cs similarity index 78% rename from src/Umbraco.Web/Trees/ContentTreeController.cs rename to src/Umbraco.Web.BackOffice/Trees/ContentTreeController.cs index a82d4faba6..0cc73af315 100644 --- a/src/Umbraco.Web/Trees/ContentTreeController.cs +++ b/src/Umbraco.Web.BackOffice/Trees/ContentTreeController.cs @@ -2,25 +2,24 @@ using System.Collections.Generic; using System.Linq; using System.Net; -using System.Net.Http.Formatting; -using System.Web.Http; +using Microsoft.AspNetCore.Http; using Umbraco.Core; using Umbraco.Core.Models; using Umbraco.Core.Models.Entities; using Umbraco.Core.Services; using Umbraco.Web.Actions; using Umbraco.Web.Models.Trees; -using Umbraco.Web.Mvc; -using Umbraco.Web.WebApi.Filters; using Umbraco.Web.Models.ContentEditing; using Umbraco.Web.Search; -using Umbraco.Core.Cache; using Umbraco.Core.Configuration; using Umbraco.Core.Logging; -using Umbraco.Core.Persistence; using Constants = Umbraco.Core.Constants; -using Umbraco.Core.Mapping; -using Umbraco.Web.Routing; +using Umbraco.Web.BackOffice.Filters; +using Umbraco.Web.BackOffice.Trees; +using Umbraco.Web.Common.Attributes; +using Umbraco.Web.Common.Exceptions; +using Umbraco.Web.Security; +using Umbraco.Web.WebApi; namespace Umbraco.Web.Trees { @@ -43,41 +42,59 @@ namespace Umbraco.Web.Trees private readonly ActionCollection _actions; private readonly IGlobalSettings _globalSettings; private readonly IMenuItemCollectionFactory _menuItemCollectionFactory; + private readonly IWebSecurity _webSecurity; + private readonly IContentService _contentService; + private readonly IEntityService _entityService; + private readonly IPublicAccessService _publicAccessService; + private readonly IUserService _userService; + private readonly ILocalizationService _localizationService; - protected override int RecycleBinId => Constants.System.RecycleBinContent; - - protected override bool RecycleBinSmells => Services.ContentService.RecycleBinSmells(); - - private int[] _userStartNodes; - - protected override int[] UserStartNodes - => _userStartNodes ?? (_userStartNodes = Security.CurrentUser.CalculateContentStartNodeIds(Services.EntityService)); public ContentTreeController( + ILocalizedTextService localizedTextService, + UmbracoApiControllerTypeCollection umbracoApiControllerTypeCollection, + IMenuItemCollectionFactory menuItemCollectionFactory, + IEntityService entityService, + IWebSecurity webSecurity, + ILogger logger, + ActionCollection actionCollection, + IUserService userService, + IDataTypeService dataTypeService, UmbracoTreeSearcher treeSearcher, ActionCollection actions, IGlobalSettings globalSettings, - IUmbracoContextAccessor umbracoContextAccessor, - ISqlContext sqlContext, - ServiceContext services, - AppCaches appCaches, - IProfilingLogger logger, - IRuntimeState runtimeState, - UmbracoMapper umbracoMapper, - IPublishedUrlProvider publishedUrlProvider, - IMenuItemCollectionFactory menuItemCollectionFactory) - : base(globalSettings, umbracoContextAccessor, sqlContext, services, appCaches, logger, runtimeState, umbracoMapper, publishedUrlProvider, menuItemCollectionFactory) + IContentService contentService, + IPublicAccessService publicAccessService, + ILocalizationService localizationService) + : base(localizedTextService, umbracoApiControllerTypeCollection, menuItemCollectionFactory, entityService, webSecurity, logger, actionCollection, userService, dataTypeService) { _treeSearcher = treeSearcher; _actions = actions; _globalSettings = globalSettings; _menuItemCollectionFactory = menuItemCollectionFactory; + _webSecurity = webSecurity; + _contentService = contentService; + _entityService = entityService; + _publicAccessService = publicAccessService; + _userService = userService; + _localizationService = localizationService; } + protected override int RecycleBinId => Constants.System.RecycleBinContent; + + protected override bool RecycleBinSmells => _contentService.RecycleBinSmells(); + + private int[] _userStartNodes; + + protected override int[] UserStartNodes + => _userStartNodes ?? (_userStartNodes = _webSecurity.CurrentUser.CalculateContentStartNodeIds(_entityService)); + + + /// - protected override TreeNode GetSingleTreeNode(IEntitySlim entity, string parentId, FormDataCollection queryStrings) + protected override TreeNode GetSingleTreeNode(IEntitySlim entity, string parentId, FormCollection queryStrings) { - var culture = queryStrings?["culture"]; + var culture = queryStrings?["culture"].ToString(); var allowedUserOptions = GetAllowedUserMenuItemsForNode(entity); if (CanUserAccessNode(entity, allowedUserOptions, culture)) @@ -122,7 +139,7 @@ namespace Umbraco.Web.Trees node.AdditionalData.Add("variesByCulture", documentEntity.Variations.VariesByCulture()); node.AdditionalData.Add("contentType", documentEntity.ContentTypeAlias); - if (Services.PublicAccessService.IsProtected(entity.Path)) + if (_publicAccessService.IsProtected(entity.Path)) node.SetProtectedStyle(); return node; @@ -131,7 +148,7 @@ namespace Umbraco.Web.Trees return null; } - protected override MenuItemCollection PerformGetMenuForNode(string id, FormDataCollection queryStrings) + protected override MenuItemCollection PerformGetMenuForNode(string id, FormCollection queryStrings) { if (id == Constants.System.RootString) { @@ -140,7 +157,7 @@ namespace Umbraco.Web.Trees // if the user's start node is not the root then the only menu item to display is refresh if (UserStartNodes.Contains(Constants.System.Root) == false) { - menu.Items.Add(new RefreshNode(Services.TextService, true)); + menu.Items.Add(new RefreshNode(LocalizedTextService, true)); return menu; } @@ -148,13 +165,13 @@ namespace Umbraco.Web.Trees menu.DefaultMenuAlias = ActionNew.ActionAlias; // we need to get the default permissions as you can't set permissions on the very root node - var permission = Services.UserService.GetPermissions(Security.CurrentUser, Constants.System.Root).First(); + var permission = _userService.GetPermissions(_webSecurity.CurrentUser, Constants.System.Root).First(); var nodeActions = _actions.FromEntityPermission(permission) .Select(x => new MenuItem(x)); //these two are the standard items - menu.Items.Add(Services.TextService, opensDialog: true); - menu.Items.Add(Services.TextService, true); + menu.Items.Add(LocalizedTextService, opensDialog: true); + menu.Items.Add(LocalizedTextService, true); //filter the standard items FilterUserAllowedMenuItems(menu, nodeActions); @@ -165,7 +182,7 @@ namespace Umbraco.Web.Trees } // add default actions for *all* users - menu.Items.Add(new RefreshNode(Services.TextService, true)); + menu.Items.Add(new RefreshNode(LocalizedTextService, true)); return menu; } @@ -177,17 +194,17 @@ namespace Umbraco.Web.Trees { throw new HttpResponseException(HttpStatusCode.NotFound); } - var item = Services.EntityService.Get(iid, UmbracoObjectTypes.Document); + var item = _entityService.Get(iid, UmbracoObjectTypes.Document); if (item == null) { throw new HttpResponseException(HttpStatusCode.NotFound); } //if the user has no path access for this node, all they can do is refresh - if (!Security.CurrentUser.HasContentPathAccess(item, Services.EntityService)) + if (!_webSecurity.CurrentUser.HasContentPathAccess(item, _entityService)) { var menu = _menuItemCollectionFactory.Create(); - menu.Items.Add(new RefreshNode(Services.TextService, true)); + menu.Items.Add(new RefreshNode(LocalizedTextService, true)); return menu; } @@ -219,19 +236,19 @@ namespace Umbraco.Web.Trees /// /// /// - protected override bool HasPathAccess(string id, FormDataCollection queryStrings) + protected override bool HasPathAccess(string id, FormCollection queryStrings) { var entity = GetEntityFromId(id); return HasPathAccess(entity, queryStrings); } - protected override IEnumerable GetChildEntities(string id, FormDataCollection queryStrings) + protected override IEnumerable GetChildEntities(string id, FormCollection queryStrings) { var result = base.GetChildEntities(id, queryStrings); var culture = queryStrings["culture"].TryConvertTo(); //if this is null we'll set it to the default. - var cultureVal = (culture.Success ? culture.Result : null) ?? Services.LocalizationService.GetDefaultLanguageIsoCode(); + var cultureVal = (culture.Success ? culture.Result : null) ?? _localizationService.GetDefaultLanguageIsoCode(); // set names according to variations foreach (var entity in result) @@ -261,7 +278,7 @@ namespace Umbraco.Web.Trees if (EmailSender.CanSendRequiredEmail(_globalSettings)) { - menu.Items.Add(new MenuItem("notify", Services.TextService) + menu.Items.Add(new MenuItem("notify", LocalizedTextService) { Icon = "megaphone", SeparatorBefore = true, @@ -271,7 +288,7 @@ namespace Umbraco.Web.Trees if((item is DocumentEntitySlim documentEntity && documentEntity.IsContainer) == false) { - menu.Items.Add(new RefreshNode(Services.TextService, true)); + menu.Items.Add(new RefreshNode(LocalizedTextService, true)); } return menu; @@ -285,11 +302,11 @@ namespace Umbraco.Web.Trees protected MenuItemCollection GetNodeMenuItemsForDeletedContent(IUmbracoEntity item) { var menu = _menuItemCollectionFactory.Create(); - menu.Items.Add(Services.TextService, opensDialog: true); - menu.Items.Add(Services.TextService, opensDialog: true); - menu.Items.Add(Services.TextService, opensDialog: true); + menu.Items.Add(LocalizedTextService, opensDialog: true); + menu.Items.Add(LocalizedTextService, opensDialog: true); + menu.Items.Add(LocalizedTextService, opensDialog: true); - menu.Items.Add(new RefreshNode(Services.TextService, true)); + menu.Items.Add(new RefreshNode(LocalizedTextService, true)); return menu; } @@ -342,7 +359,7 @@ namespace Umbraco.Web.Trees private void AddActionNode(IUmbracoEntity item, MenuItemCollection menu, bool hasSeparator = false, bool opensDialog = false) where TAction : IAction { - var menuItem = menu.Items.Add(Services.TextService, hasSeparator, opensDialog); + var menuItem = menu.Items.Add(LocalizedTextService, hasSeparator, opensDialog); } public IEnumerable Search(string query, int pageSize, long pageIndex, out long totalFound, string searchFrom = null) diff --git a/src/Umbraco.Web/Trees/ContentTreeControllerBase.cs b/src/Umbraco.Web.BackOffice/Trees/ContentTreeControllerBase.cs similarity index 83% rename from src/Umbraco.Web/Trees/ContentTreeControllerBase.cs rename to src/Umbraco.Web.BackOffice/Trees/ContentTreeControllerBase.cs index 43dedfbb22..e458e8754b 100644 --- a/src/Umbraco.Web/Trees/ContentTreeControllerBase.cs +++ b/src/Umbraco.Web.BackOffice/Trees/ContentTreeControllerBase.cs @@ -3,52 +3,58 @@ using System.Collections.Concurrent; using System.Collections.Generic; using System.Linq; using System.Net; -using System.Net.Http; -using System.Net.Http.Formatting; -using System.Web.Http; using Umbraco.Core; using Umbraco.Core.Services; using Umbraco.Core.Logging; using Umbraco.Core.Models; using Umbraco.Web.Models.Trees; -using Umbraco.Web.WebApi.Filters; using Umbraco.Core.Models.Entities; -using System.Web.Http.ModelBinding; +using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Mvc; using Umbraco.Web.Actions; -using Umbraco.Web.Composing; using Umbraco.Core.Security; -using Umbraco.Core.Cache; -using Umbraco.Core.Configuration; -using Umbraco.Core.Persistence; -using Umbraco.Core.Mapping; -using Umbraco.Web.Routing; +using Umbraco.Extensions; +using Umbraco.Web.BackOffice.Trees; +using Umbraco.Web.Common.Exceptions; +using Umbraco.Web.Common.ModelBinders; +using Umbraco.Web.Security; +using Umbraco.Web.WebApi; namespace Umbraco.Web.Trees { public abstract class ContentTreeControllerBase : TreeController, ITreeNodeController { + private readonly IEntityService _entityService; + private readonly IWebSecurity _webSecurity; + private readonly ILogger _logger; + private readonly ActionCollection _actionCollection; + private readonly IUserService _userService; + private readonly IDataTypeService _dataTypeService; public IMenuItemCollectionFactory MenuItemCollectionFactory { get; } protected ContentTreeControllerBase( - IGlobalSettings globalSettings, - IUmbracoContextAccessor umbracoContextAccessor, - ISqlContext sqlContext, - ServiceContext services, - AppCaches appCaches, - IProfilingLogger logger, - IRuntimeState runtimeState, - UmbracoMapper umbracoMapper, - IPublishedUrlProvider publishedUrlProvider, - IMenuItemCollectionFactory menuItemCollectionFactory) - : base(globalSettings, umbracoContextAccessor, sqlContext, services, appCaches, logger, runtimeState, umbracoMapper, publishedUrlProvider) + ILocalizedTextService localizedTextService, + UmbracoApiControllerTypeCollection umbracoApiControllerTypeCollection, + IMenuItemCollectionFactory menuItemCollectionFactory, + IEntityService entityService, + IWebSecurity webSecurity, + ILogger logger, + ActionCollection actionCollection, + IUserService userService, + IDataTypeService dataTypeService + ) + : base(localizedTextService, umbracoApiControllerTypeCollection) { + _entityService = entityService; + _webSecurity = webSecurity; + _logger = logger; + _actionCollection = actionCollection; + _userService = userService; + _dataTypeService = dataTypeService; MenuItemCollectionFactory = menuItemCollectionFactory; } - protected ContentTreeControllerBase() - { - } #region Actions @@ -58,7 +64,7 @@ namespace Umbraco.Web.Trees /// /// /// - public TreeNode GetTreeNode(string id, [ModelBinder(typeof(HttpQueryStringModelBinder))]FormDataCollection queryStrings) + public ActionResult GetTreeNode(string id, [ModelBinder(typeof(HttpQueryStringModelBinder))]FormCollection queryStrings) { int asInt; Guid asGuid = Guid.Empty; @@ -66,16 +72,16 @@ namespace Umbraco.Web.Trees { if (Guid.TryParse(id, out asGuid) == false) { - throw new HttpResponseException(Request.CreateResponse(HttpStatusCode.NotFound)); + return NotFound(); } } var entity = asGuid == Guid.Empty - ? Services.EntityService.Get(asInt, UmbracoObjectType) - : Services.EntityService.Get(asGuid, UmbracoObjectType); + ? _entityService.Get(asInt, UmbracoObjectType) + : _entityService.Get(asGuid, UmbracoObjectType); if (entity == null) { - throw new HttpResponseException(Request.CreateResponse(HttpStatusCode.NotFound)); + return NotFound(); } var node = GetSingleTreeNode(entity, entity.ParentId.ToInvariantString(), queryStrings); @@ -92,7 +98,7 @@ namespace Umbraco.Web.Trees /// /// /// - protected override TreeNode CreateRootNode(FormDataCollection queryStrings) + protected override TreeNode CreateRootNode(FormCollection queryStrings) { var node = base.CreateRootNode(queryStrings); @@ -104,7 +110,7 @@ namespace Umbraco.Web.Trees return node; } - protected abstract TreeNode GetSingleTreeNode(IEntitySlim entity, string parentId, FormDataCollection queryStrings); + protected abstract TreeNode GetSingleTreeNode(IEntitySlim entity, string parentId, FormCollection queryStrings); /// /// Returns a for the and @@ -114,7 +120,7 @@ namespace Umbraco.Web.Trees /// /// /// - internal TreeNode GetSingleTreeNodeWithAccessCheck(IEntitySlim e, string parentId, FormDataCollection queryStrings, + internal TreeNode GetSingleTreeNodeWithAccessCheck(IEntitySlim e, string parentId, FormCollection queryStrings, int[] startNodeIds, string[] startNodePaths) { var entityIsAncestorOfStartNodes = ContentPermissionsHelper.IsInBranchOfStartNode(e.Path, startNodeIds, startNodePaths, out var hasPathAccess); @@ -141,12 +147,12 @@ namespace Umbraco.Web.Trees switch (RecycleBinId) { case Constants.System.RecycleBinMedia: - startNodeIds = Security.CurrentUser.CalculateMediaStartNodeIds(Services.EntityService); - startNodePaths = Security.CurrentUser.GetMediaStartNodePaths(Services.EntityService); + startNodeIds = _webSecurity.CurrentUser.CalculateMediaStartNodeIds(_entityService); + startNodePaths = _webSecurity.CurrentUser.GetMediaStartNodePaths(_entityService); break; case Constants.System.RecycleBinContent: - startNodeIds = Security.CurrentUser.CalculateContentStartNodeIds(Services.EntityService); - startNodePaths = Security.CurrentUser.GetContentStartNodePaths(Services.EntityService); + startNodeIds = _webSecurity.CurrentUser.CalculateContentStartNodeIds(_entityService); + startNodePaths = _webSecurity.CurrentUser.GetContentStartNodePaths(_entityService); break; default: throw new NotSupportedException("Path access is only determined on content or media"); @@ -168,7 +174,7 @@ namespace Umbraco.Web.Trees /// protected abstract int[] UserStartNodes { get; } - protected virtual TreeNodeCollection PerformGetTreeNodes(string id, FormDataCollection queryStrings) + protected virtual TreeNodeCollection PerformGetTreeNodes(string id, FormCollection queryStrings) { var nodes = new TreeNodeCollection(); @@ -190,7 +196,7 @@ namespace Umbraco.Web.Trees // TODO: in the future we could return a validation statement so we can have some UI to notify the user they don't have access if (ignoreUserStartNodes == false && HasPathAccess(id, queryStrings) == false) { - Logger.Warn("User {Username} does not have access to node with id {Id}", Security.CurrentUser.Username, id); + _logger.Warn("User {Username} does not have access to node with id {Id}", _webSecurity.CurrentUser.Username, id); return nodes; } @@ -225,7 +231,7 @@ namespace Umbraco.Web.Trees var topNodeIds = entities.Except(topMostEntities).Select(GetTopNodeId).Where(x => x != 0).Distinct().ToArray(); if (topNodeIds.Length > 0) { - var topNodes = Services.EntityService.GetAll(UmbracoObjectType, topNodeIds.ToArray()); + var topNodes = _entityService.GetAll(UmbracoObjectType, topNodeIds.ToArray()); nodes.AddRange(topNodes.Select(x => GetSingleTreeNodeWithAccessCheck(x, id, queryStrings, userStartNodes, userStartNodePaths)).Where(x => x != null)); } } @@ -247,11 +253,11 @@ namespace Umbraco.Web.Trees return parts.Length >= 2 && int.TryParse(parts[1], out id) ? id : 0; } - protected abstract MenuItemCollection PerformGetMenuForNode(string id, FormDataCollection queryStrings); + protected abstract MenuItemCollection PerformGetMenuForNode(string id, FormCollection queryStrings); protected abstract UmbracoObjectTypes UmbracoObjectType { get; } - protected virtual IEnumerable GetChildEntities(string id, FormDataCollection queryStrings) + protected virtual IEnumerable GetChildEntities(string id, FormCollection queryStrings) { // try to parse id as an integer else use GetEntityFromId // which will grok Guids, Udis, etc and let use obtain the id @@ -273,7 +279,7 @@ namespace Umbraco.Web.Trees if (!ignoreUserStartNodes && entityId == Constants.System.Root && UserStartNodes.Contains(Constants.System.Root) == false) { result = UserStartNodes.Length > 0 - ? Services.EntityService.GetAll(UmbracoObjectType, UserStartNodes).ToArray() + ? _entityService.GetAll(UmbracoObjectType, UserStartNodes).ToArray() : Array.Empty(); } else @@ -285,7 +291,7 @@ namespace Umbraco.Web.Trees } private IEnumerable GetChildrenFromEntityService(int entityId) - => Services.EntityService.GetChildren(entityId, UmbracoObjectType).ToList(); + => _entityService.GetChildren(entityId, UmbracoObjectType).ToList(); /// /// Returns true or false if the current user has access to the node based on the user's allowed start node (path) access @@ -294,7 +300,7 @@ namespace Umbraco.Web.Trees /// /// //we should remove this in v8, it's now here for backwards compat only - protected abstract bool HasPathAccess(string id, FormDataCollection queryStrings); + protected abstract bool HasPathAccess(string id, FormCollection queryStrings); /// /// Returns true or false if the current user has access to the node based on the user's allowed start node (path) access @@ -302,12 +308,12 @@ namespace Umbraco.Web.Trees /// /// /// - protected bool HasPathAccess(IUmbracoEntity entity, FormDataCollection queryStrings) + protected bool HasPathAccess(IUmbracoEntity entity, FormCollection queryStrings) { if (entity == null) return false; return RecycleBinId == Constants.System.RecycleBinContent - ? Security.CurrentUser.HasContentPathAccess(entity, Services.EntityService) - : Security.CurrentUser.HasMediaPathAccess(entity, Services.EntityService); + ? _webSecurity.CurrentUser.HasContentPathAccess(entity, _entityService) + : _webSecurity.CurrentUser.HasMediaPathAccess(entity, _entityService); } /// @@ -319,7 +325,7 @@ namespace Umbraco.Web.Trees /// /// This method is overwritten strictly to render the recycle bin, it should serve no other purpose /// - protected sealed override TreeNodeCollection GetTreeNodes(string id, FormDataCollection queryStrings) + protected sealed override TreeNodeCollection GetTreeNodes(string id, FormCollection queryStrings) { //check if we're rendering the root if (id == Constants.System.RootString && UserStartNodes.Contains(Constants.System.Root)) @@ -339,14 +345,14 @@ namespace Umbraco.Web.Trees //only render the recycle bin if we are not in dialog and the start id is still the root //we need to check for the "application" key in the queryString because its value is required here, - //and for some reason when there are no dashboards, this parameter is missing + //and for some reason when there are no dashboards, this parameter is missing if (IsDialog(queryStrings) == false && id == Constants.System.RootString && queryStrings.HasKey("application")) { nodes.Add(CreateTreeNode( RecycleBinId.ToInvariantString(), id, queryStrings, - Services.TextService.Localize("general/recycleBin"), + LocalizedTextService.Localize("general/recycleBin"), "icon-trash", RecycleBinSmells, queryStrings.GetRequiredValue("application") + TreeAlias.EnsureStartsWith('/') + "/recyclebin")); @@ -378,7 +384,7 @@ namespace Umbraco.Web.Trees // of this container node. If that is true, the HasChildren must be true so that the tree node still renders even though this current node is a container/list view. if (isContainer && UserStartNodes.Length > 0 && UserStartNodes.Contains(Constants.System.Root) == false) { - var startNodes = Services.EntityService.GetAll(UmbracoObjectType, UserStartNodes); + var startNodes = _entityService.GetAll(UmbracoObjectType, UserStartNodes); //if any of these start nodes' parent is current, then we need to render children normally so we need to switch some logic and tell // the UI that this node does have children and that it isn't a container @@ -404,7 +410,7 @@ namespace Umbraco.Web.Trees /// /// Currently this just checks if it is a container type, if it is we cannot render children. In the future this might check for other things. /// - private TreeNodeCollection GetTreeNodesInternal(string id, FormDataCollection queryStrings) + private TreeNodeCollection GetTreeNodesInternal(string id, FormCollection queryStrings) { var current = GetEntityFromId(id); @@ -426,16 +432,16 @@ namespace Umbraco.Web.Trees /// /// /// - protected sealed override MenuItemCollection GetMenuForNode(string id, FormDataCollection queryStrings) + protected sealed override MenuItemCollection GetMenuForNode(string id, FormCollection queryStrings) { if (RecycleBinId.ToInvariantString() == id) { // get the default assigned permissions for this user var deleteAllowed = false; - var deleteAction = Current.Actions.FirstOrDefault(y => y.Letter == ActionDelete.ActionLetter); + var deleteAction = _actionCollection.FirstOrDefault(y => y.Letter == ActionDelete.ActionLetter); if (deleteAction != null) { - var perms = Security.CurrentUser.GetPermissions(Constants.System.RecycleBinContentString, Services.UserService); + var perms = _webSecurity.CurrentUser.GetPermissions(Constants.System.RecycleBinContentString, _userService); deleteAllowed = perms.FirstOrDefault(x => x.Contains(deleteAction.Letter)) != null; } @@ -443,12 +449,12 @@ namespace Umbraco.Web.Trees // only add empty recycle bin if the current user is allowed to delete by default if (deleteAllowed) { - menu.Items.Add(new MenuItem("emptyRecycleBin", Services.TextService) + menu.Items.Add(new MenuItem("emptyRecycleBin", LocalizedTextService) { Icon = "trash", OpensDialog = true }); - menu.Items.Add(new RefreshNode(Services.TextService, true)); + menu.Items.Add(new RefreshNode(LocalizedTextService, true)); } return menu; } @@ -486,8 +492,8 @@ namespace Umbraco.Web.Trees internal IEnumerable GetAllowedUserMenuItemsForNode(IUmbracoEntity dd) { - var permissionsForPath = Services.UserService.GetPermissionsForPath(Security.CurrentUser, dd.Path).GetAllPermissions(); - return Current.Actions.GetByLetters(permissionsForPath).Select(x => new MenuItem(x)); + var permissionsForPath = _userService.GetPermissionsForPath(_webSecurity.CurrentUser, dd.Path).GetAllPermissions(); + return _actionCollection.GetByLetters(permissionsForPath).Select(x => new MenuItem(x)); } /// @@ -549,16 +555,16 @@ namespace Umbraco.Web.Trees if (Guid.TryParse(s, out var idGuid)) { - entity = Services.EntityService.Get(idGuid, UmbracoObjectType); + entity = _entityService.Get(idGuid, UmbracoObjectType); } else if (int.TryParse(s, out var idInt)) { - entity = Services.EntityService.Get(idInt, UmbracoObjectType); + entity = _entityService.Get(idInt, UmbracoObjectType); } else if (UdiParser.TryParse(s, out var idUdi)) { var guidUdi = idUdi as GuidUdi; - entity = guidUdi != null ? Services.EntityService.Get(guidUdi.Guid, UmbracoObjectType) : null; + entity = guidUdi != null ? _entityService.Get(guidUdi.Guid, UmbracoObjectType) : null; } else { @@ -580,12 +586,12 @@ namespace Umbraco.Web.Trees /// /// /// - internal bool IgnoreUserStartNodes(FormDataCollection queryStrings) + internal bool IgnoreUserStartNodes(FormCollection queryStrings) { if (_ignoreUserStartNodes.HasValue) return _ignoreUserStartNodes.Value; var dataTypeKey = queryStrings.GetValue(TreeQueryStringParameters.DataTypeKey); - _ignoreUserStartNodes = dataTypeKey.HasValue && Services.DataTypeService.IsDataTypeIgnoringUserStartNodes(dataTypeKey.Value); + _ignoreUserStartNodes = dataTypeKey.HasValue && _dataTypeService.IsDataTypeIgnoringUserStartNodes(dataTypeKey.Value); return _ignoreUserStartNodes.Value; } diff --git a/src/Umbraco.Web/Trees/ContentTypeTreeController.cs b/src/Umbraco.Web.BackOffice/Trees/ContentTypeTreeController.cs similarity index 65% rename from src/Umbraco.Web/Trees/ContentTypeTreeController.cs rename to src/Umbraco.Web.BackOffice/Trees/ContentTypeTreeController.cs index e04bfab9c2..2ee5ef0b3f 100644 --- a/src/Umbraco.Web/Trees/ContentTypeTreeController.cs +++ b/src/Umbraco.Web.BackOffice/Trees/ContentTypeTreeController.cs @@ -1,61 +1,49 @@ using System; using System.Collections.Generic; using System.Linq; -using System.Net.Http.Formatting; +using Microsoft.AspNetCore.Http; using Umbraco.Core; -using Umbraco.Core.Cache; -using Umbraco.Core.Configuration; -using Umbraco.Core.Logging; -using Umbraco.Core.Mapping; using Umbraco.Core.Models; -using Umbraco.Core.Models.Entities; -using Umbraco.Core.Persistence; using Umbraco.Core.Services; using Umbraco.Web.Actions; +using Umbraco.Web.BackOffice.Filters; +using Umbraco.Web.BackOffice.Trees; +using Umbraco.Web.Common.Attributes; using Umbraco.Web.Models.ContentEditing; using Umbraco.Web.Models.Trees; -using Umbraco.Web.Routing; using Umbraco.Web.Search; -using Umbraco.Web.WebApi.Filters; +using Umbraco.Web.WebApi; namespace Umbraco.Web.Trees { [UmbracoTreeAuthorize(Constants.Trees.DocumentTypes)] [Tree(Constants.Applications.Settings, Constants.Trees.DocumentTypes, SortOrder = 0, TreeGroup = Constants.Trees.Groups.Settings)] - [Mvc.PluginController("UmbracoTrees")] + [PluginController("UmbracoTrees")] [CoreTree] public class ContentTypeTreeController : TreeController, ISearchableTree { private readonly UmbracoTreeSearcher _treeSearcher; private readonly IMenuItemCollectionFactory _menuItemCollectionFactory; + private readonly IContentTypeService _contentTypeService; + private readonly IEntityService _entityService; - public ContentTypeTreeController( - UmbracoTreeSearcher treeSearcher, - IGlobalSettings globalSettings, - IUmbracoContextAccessor umbracoContextAccessor, - ISqlContext sqlContext, - ServiceContext services, - AppCaches appCaches, - IProfilingLogger logger, - IRuntimeState runtimeState, - UmbracoMapper umbracoMapper, - IPublishedUrlProvider publishedUrlProvider, - IMenuItemCollectionFactory menuItemCollectionFactory) - : base(globalSettings, umbracoContextAccessor, sqlContext, services, appCaches, logger, runtimeState, umbracoMapper, publishedUrlProvider) + public ContentTypeTreeController(ILocalizedTextService localizedTextService, UmbracoApiControllerTypeCollection umbracoApiControllerTypeCollection, UmbracoTreeSearcher treeSearcher, IMenuItemCollectionFactory menuItemCollectionFactory, IContentTypeService contentTypeService, IEntityService entityService) : base(localizedTextService, umbracoApiControllerTypeCollection) { _treeSearcher = treeSearcher; _menuItemCollectionFactory = menuItemCollectionFactory; + _contentTypeService = contentTypeService; + _entityService = entityService; } - protected override TreeNode CreateRootNode(FormDataCollection queryStrings) + protected override TreeNode CreateRootNode(FormCollection queryStrings) { var root = base.CreateRootNode(queryStrings); //check if there are any types - root.HasChildren = Services.ContentTypeService.GetAll().Any(); + root.HasChildren = _contentTypeService.GetAll().Any(); return root; } - protected override TreeNodeCollection GetTreeNodes(string id, FormDataCollection queryStrings) + protected override TreeNodeCollection GetTreeNodes(string id, FormCollection queryStrings) { var intId = id.TryConvertTo(); if (intId == false) throw new InvalidOperationException("Id must be an integer"); @@ -63,7 +51,7 @@ namespace Umbraco.Web.Trees var nodes = new TreeNodeCollection(); nodes.AddRange( - Services.EntityService.GetChildren(intId.Result, UmbracoObjectTypes.DocumentTypeContainer) + _entityService.GetChildren(intId.Result, UmbracoObjectTypes.DocumentTypeContainer) .OrderBy(entity => entity.Name) .Select(dt => { @@ -76,10 +64,10 @@ namespace Umbraco.Web.Trees })); //if the request is for folders only then just return - if (queryStrings["foldersonly"].IsNullOrWhiteSpace() == false && queryStrings["foldersonly"] == "1") return nodes; + if (queryStrings["foldersonly"].ToString().IsNullOrWhiteSpace() == false && queryStrings["foldersonly"] == "1") return nodes; - var children = Services.EntityService.GetChildren(intId.Result, UmbracoObjectTypes.DocumentType).ToArray(); - var contentTypes = Services.ContentTypeService.GetAll(children.Select(c => c.Id).ToArray()).ToDictionary(c => c.Id); + var children = _entityService.GetChildren(intId.Result, UmbracoObjectTypes.DocumentType).ToArray(); + var contentTypes = _contentTypeService.GetAll(children.Select(c => c.Id).ToArray()).ToDictionary(c => c.Id); nodes.AddRange( children .OrderBy(entity => entity.Name) @@ -106,7 +94,7 @@ namespace Umbraco.Web.Trees return nodes; } - protected override MenuItemCollection GetMenuForNode(string id, FormDataCollection queryStrings) + protected override MenuItemCollection GetMenuForNode(string id, FormCollection queryStrings) { var menu = _menuItemCollectionFactory.Create(); @@ -116,27 +104,27 @@ namespace Umbraco.Web.Trees menu.DefaultMenuAlias = ActionNew.ActionAlias; // root actions - menu.Items.Add(Services.TextService, opensDialog: true); - menu.Items.Add(new MenuItem("importDocumentType", Services.TextService) + menu.Items.Add(LocalizedTextService, opensDialog: true); + menu.Items.Add(new MenuItem("importDocumentType", LocalizedTextService) { Icon = "page-up", SeparatorBefore = true, OpensDialog = true }); - menu.Items.Add(new RefreshNode(Services.TextService, true)); + menu.Items.Add(new RefreshNode(LocalizedTextService, true)); return menu; } - var container = Services.EntityService.Get(int.Parse(id), UmbracoObjectTypes.DocumentTypeContainer); + var container = _entityService.Get(int.Parse(id), UmbracoObjectTypes.DocumentTypeContainer); if (container != null) { //set the default to create menu.DefaultMenuAlias = ActionNew.ActionAlias; - menu.Items.Add(Services.TextService, opensDialog: true); + menu.Items.Add(LocalizedTextService, opensDialog: true); - menu.Items.Add(new MenuItem("rename", Services.TextService) + menu.Items.Add(new MenuItem("rename", LocalizedTextService) { Icon = "icon icon-edit" }); @@ -144,30 +132,30 @@ namespace Umbraco.Web.Trees if (container.HasChildren == false) { //can delete doc type - menu.Items.Add(Services.TextService, true, opensDialog: true); + menu.Items.Add(LocalizedTextService, true, opensDialog: true); } - menu.Items.Add(new RefreshNode(Services.TextService, true)); + menu.Items.Add(new RefreshNode(LocalizedTextService, true)); } else { - var ct = Services.ContentTypeService.Get(int.Parse(id)); - var parent = ct == null ? null : Services.ContentTypeService.Get(ct.ParentId); + var ct = _contentTypeService.Get(int.Parse(id)); + var parent = ct == null ? null : _contentTypeService.Get(ct.ParentId); - menu.Items.Add(Services.TextService, opensDialog: true); + menu.Items.Add(LocalizedTextService, opensDialog: true); //no move action if this is a child doc type if (parent == null) { - menu.Items.Add(Services.TextService, true, opensDialog: true); + menu.Items.Add(LocalizedTextService, true, opensDialog: true); } - menu.Items.Add(Services.TextService, opensDialog: true); - menu.Items.Add(new MenuItem("export", Services.TextService) + menu.Items.Add(LocalizedTextService, opensDialog: true); + menu.Items.Add(new MenuItem("export", LocalizedTextService) { Icon = "download-alt", SeparatorBefore = true, OpensDialog = true }); - menu.Items.Add(Services.TextService, true, opensDialog: true); - menu.Items.Add(new RefreshNode(Services.TextService, true)); + menu.Items.Add(LocalizedTextService, true, opensDialog: true); + menu.Items.Add(new RefreshNode(LocalizedTextService, true)); } diff --git a/src/Umbraco.Web/Trees/DataTypeTreeController.cs b/src/Umbraco.Web.BackOffice/Trees/DataTypeTreeController.cs similarity index 72% rename from src/Umbraco.Web/Trees/DataTypeTreeController.cs rename to src/Umbraco.Web.BackOffice/Trees/DataTypeTreeController.cs index 50882488f3..c68908c3dc 100644 --- a/src/Umbraco.Web/Trees/DataTypeTreeController.cs +++ b/src/Umbraco.Web.BackOffice/Trees/DataTypeTreeController.cs @@ -1,24 +1,19 @@ using System; using System.Collections.Generic; using System.Linq; -using System.Net.Http.Formatting; +using Microsoft.AspNetCore.Http; using Umbraco.Core; using Umbraco.Core.Models; -using Umbraco.Core.Models.Entities; using Umbraco.Web.Models.Trees; -using Umbraco.Web.Mvc; -using Umbraco.Web.WebApi.Filters; using Umbraco.Core.Services; using Umbraco.Web.Actions; using Umbraco.Web.Models.ContentEditing; -using Umbraco.Core.Cache; -using Umbraco.Core.Configuration; -using Umbraco.Core.Logging; -using Umbraco.Core.Persistence; using Umbraco.Web.Search; using Constants = Umbraco.Core.Constants; -using Umbraco.Core.Mapping; -using Umbraco.Web.Routing; +using Umbraco.Web.BackOffice.Filters; +using Umbraco.Web.BackOffice.Trees; +using Umbraco.Web.Common.Attributes; +using Umbraco.Web.WebApi; namespace Umbraco.Web.Trees { @@ -30,26 +25,19 @@ namespace Umbraco.Web.Trees { private readonly UmbracoTreeSearcher _treeSearcher; private readonly IMenuItemCollectionFactory _menuItemCollectionFactory; + private readonly IEntityService _entityService; + private readonly IDataTypeService _dataTypeService; - public DataTypeTreeController( - UmbracoTreeSearcher treeSearcher, - IGlobalSettings globalSettings, - IUmbracoContextAccessor umbracoContextAccessor, - ISqlContext sqlContext, - ServiceContext services, - AppCaches appCaches, - IProfilingLogger logger, - IRuntimeState runtimeState, - UmbracoMapper umbracoMapper, - IPublishedUrlProvider publishedUrlProvider, - IMenuItemCollectionFactory menuItemCollectionFactory) - : base(globalSettings, umbracoContextAccessor, sqlContext, services, appCaches, logger, runtimeState, umbracoMapper, publishedUrlProvider) + + public DataTypeTreeController(ILocalizedTextService localizedTextService, UmbracoApiControllerTypeCollection umbracoApiControllerTypeCollection, UmbracoTreeSearcher treeSearcher, IMenuItemCollectionFactory menuItemCollectionFactory, IEntityService entityService, IDataTypeService dataTypeService) : base(localizedTextService, umbracoApiControllerTypeCollection) { _treeSearcher = treeSearcher; _menuItemCollectionFactory = menuItemCollectionFactory; + _entityService = entityService; + _dataTypeService = dataTypeService; } - protected override TreeNodeCollection GetTreeNodes(string id, FormDataCollection queryStrings) + protected override TreeNodeCollection GetTreeNodes(string id, FormCollection queryStrings) { var intId = id.TryConvertTo(); if (intId == false) throw new InvalidOperationException("Id must be an integer"); @@ -58,7 +46,7 @@ namespace Umbraco.Web.Trees //Folders first nodes.AddRange( - Services.EntityService.GetChildren(intId.Result, UmbracoObjectTypes.DataTypeContainer) + _entityService.GetChildren(intId.Result, UmbracoObjectTypes.DataTypeContainer) .OrderBy(entity => entity.Name) .Select(dt => { @@ -71,13 +59,13 @@ namespace Umbraco.Web.Trees })); //if the request is for folders only then just return - if (queryStrings["foldersonly"].IsNullOrWhiteSpace() == false && queryStrings["foldersonly"] == "1") return nodes; + if (queryStrings["foldersonly"].ToString().IsNullOrWhiteSpace() == false && queryStrings["foldersonly"] == "1") return nodes; //System ListView nodes var systemListViewDataTypeIds = GetNonDeletableSystemListViewDataTypeIds(); - var children = Services.EntityService.GetChildren(intId.Result, UmbracoObjectTypes.DataType).ToArray(); - var dataTypes = Services.DataTypeService.GetAll(children.Select(c => c.Id).ToArray()).ToDictionary(dt => dt.Id); + var children = _entityService.GetChildren(intId.Result, UmbracoObjectTypes.DataType).ToArray(); + var dataTypes = _dataTypeService.GetAll(children.Select(c => c.Id).ToArray()).ToDictionary(dt => dt.Id); nodes.AddRange( children @@ -128,7 +116,7 @@ namespace Umbraco.Web.Trees }; } - protected override MenuItemCollection GetMenuForNode(string id, FormDataCollection queryStrings) + protected override MenuItemCollection GetMenuForNode(string id, FormCollection queryStrings) { var menu = _menuItemCollectionFactory.Create(); @@ -138,20 +126,20 @@ namespace Umbraco.Web.Trees menu.DefaultMenuAlias = ActionNew.ActionAlias; // root actions - menu.Items.Add(Services.TextService, opensDialog: true); - menu.Items.Add(new RefreshNode(Services.TextService, true)); + menu.Items.Add(LocalizedTextService, opensDialog: true); + menu.Items.Add(new RefreshNode(LocalizedTextService, true)); return menu; } - var container = Services.EntityService.Get(int.Parse(id), UmbracoObjectTypes.DataTypeContainer); + var container = _entityService.Get(int.Parse(id), UmbracoObjectTypes.DataTypeContainer); if (container != null) { //set the default to create menu.DefaultMenuAlias = ActionNew.ActionAlias; - menu.Items.Add(Services.TextService, opensDialog: true); + menu.Items.Add(LocalizedTextService, opensDialog: true); - menu.Items.Add(new MenuItem("rename", Services.TextService.Localize("actions/rename")) + menu.Items.Add(new MenuItem("rename", LocalizedTextService.Localize("actions/rename")) { Icon = "icon icon-edit" }); @@ -159,18 +147,18 @@ namespace Umbraco.Web.Trees if (container.HasChildren == false) { //can delete data type - menu.Items.Add(Services.TextService, opensDialog: true); + menu.Items.Add(LocalizedTextService, opensDialog: true); } - menu.Items.Add(new RefreshNode(Services.TextService, true)); + menu.Items.Add(new RefreshNode(LocalizedTextService, true)); } else { var nonDeletableSystemDataTypeIds = GetNonDeletableSystemDataTypeIds(); if (nonDeletableSystemDataTypeIds.Contains(int.Parse(id)) == false) - menu.Items.Add(Services.TextService, opensDialog: true); + menu.Items.Add(LocalizedTextService, opensDialog: true); - menu.Items.Add(Services.TextService, hasSeparator: true, opensDialog: true); + menu.Items.Add(LocalizedTextService, hasSeparator: true, opensDialog: true); } return menu; diff --git a/src/Umbraco.Web/Trees/DictionaryTreeController.cs b/src/Umbraco.Web.BackOffice/Trees/DictionaryTreeController.cs similarity index 67% rename from src/Umbraco.Web/Trees/DictionaryTreeController.cs rename to src/Umbraco.Web.BackOffice/Trees/DictionaryTreeController.cs index 8c60532c76..d92ca0e6c7 100644 --- a/src/Umbraco.Web/Trees/DictionaryTreeController.cs +++ b/src/Umbraco.Web.BackOffice/Trees/DictionaryTreeController.cs @@ -1,18 +1,15 @@ using System; using System.Linq; -using System.Net.Http.Formatting; +using Microsoft.AspNetCore.Http; using Umbraco.Core; -using Umbraco.Core.Cache; -using Umbraco.Core.Configuration; -using Umbraco.Core.Logging; -using Umbraco.Core.Mapping; using Umbraco.Core.Models; -using Umbraco.Core.Persistence; using Umbraco.Core.Services; using Umbraco.Web.Actions; +using Umbraco.Web.BackOffice.Filters; +using Umbraco.Web.BackOffice.Trees; +using Umbraco.Web.Common.Attributes; using Umbraco.Web.Models.Trees; -using Umbraco.Web.Routing; -using Umbraco.Web.WebApi.Filters; +using Umbraco.Web.WebApi; namespace Umbraco.Web.Trees { @@ -23,37 +20,28 @@ namespace Umbraco.Web.Trees // We are allowed to see the dictionary tree, if we are allowed to manage templates, such that se can use the // dictionary items in templates, even when we dont have authorization to manage the dictionary items )] - [Mvc.PluginController("UmbracoTrees")] + [PluginController("UmbracoTrees")] [CoreTree] [Tree(Constants.Applications.Translation, Constants.Trees.Dictionary, TreeGroup = Constants.Trees.Groups.Settings)] public class DictionaryTreeController : TreeController { private readonly IMenuItemCollectionFactory _menuItemCollectionFactory; + private readonly ILocalizationService _localizationService; - public DictionaryTreeController( - IGlobalSettings globalSettings, - IUmbracoContextAccessor umbracoContextAccessor, - ISqlContext sqlContext, - ServiceContext services, - AppCaches appCaches, - IProfilingLogger logger, - IRuntimeState runtimeState, - UmbracoMapper umbracoMapper, - IPublishedUrlProvider publishedUrlProvider, - IMenuItemCollectionFactory menuItemCollectionFactory) - : base(globalSettings, umbracoContextAccessor, sqlContext, services, appCaches, logger, runtimeState, umbracoMapper, publishedUrlProvider) + public DictionaryTreeController(ILocalizedTextService localizedTextService, UmbracoApiControllerTypeCollection umbracoApiControllerTypeCollection, IMenuItemCollectionFactory menuItemCollectionFactory, ILocalizationService localizationService) : base(localizedTextService, umbracoApiControllerTypeCollection) { _menuItemCollectionFactory = menuItemCollectionFactory; + _localizationService = localizationService; } - protected override TreeNode CreateRootNode(FormDataCollection queryStrings) + protected override TreeNode CreateRootNode(FormCollection queryStrings) { var root = base.CreateRootNode(queryStrings); // the default section is settings, falling back to this if we can't // figure out where we are from the querystring parameters var section = Constants.Applications.Translation; - if (queryStrings["application"] != null) + if (!queryStrings["application"].ToString().IsNullOrWhiteSpace()) section = queryStrings["application"]; // this will load in a custom UI instead of the dashboard for the root node @@ -73,7 +61,7 @@ namespace Umbraco.Web.Trees /// We are allowing an arbitrary number of query strings to be passed in so that developers are able to persist custom data from the front-end /// to the back end to be used in the query for model data. /// - protected override TreeNodeCollection GetTreeNodes(string id, FormDataCollection queryStrings) + protected override TreeNodeCollection GetTreeNodes(string id, FormCollection queryStrings) { var intId = id.TryConvertTo(); if (intId == false) @@ -86,30 +74,30 @@ namespace Umbraco.Web.Trees if (id == Constants.System.RootString) { nodes.AddRange( - Services.LocalizationService.GetRootDictionaryItems().OrderBy(ItemSort()).Select( + _localizationService.GetRootDictionaryItems().OrderBy(ItemSort()).Select( x => CreateTreeNode( x.Id.ToInvariantString(), id, queryStrings, x.ItemKey, "icon-book-alt", - Services.LocalizationService.GetDictionaryItemChildren(x.Key).Any()))); + _localizationService.GetDictionaryItemChildren(x.Key).Any()))); } else { // maybe we should use the guid as url param to avoid the extra call for getting dictionary item - var parentDictionary = Services.LocalizationService.GetDictionaryItemById(intId.Result); + var parentDictionary = _localizationService.GetDictionaryItemById(intId.Result); if (parentDictionary == null) return nodes; - nodes.AddRange(Services.LocalizationService.GetDictionaryItemChildren(parentDictionary.Key).ToList().OrderBy(ItemSort()).Select( + nodes.AddRange(_localizationService.GetDictionaryItemChildren(parentDictionary.Key).ToList().OrderBy(ItemSort()).Select( x => CreateTreeNode( x.Id.ToInvariantString(), id, queryStrings, x.ItemKey, "icon-book-alt", - Services.LocalizationService.GetDictionaryItemChildren(x.Key).Any()))); + _localizationService.GetDictionaryItemChildren(x.Key).Any()))); } return nodes; @@ -123,16 +111,16 @@ namespace Umbraco.Web.Trees /// All of the query string parameters passed from jsTree /// /// - protected override MenuItemCollection GetMenuForNode(string id, FormDataCollection queryStrings) + protected override MenuItemCollection GetMenuForNode(string id, FormCollection queryStrings) { var menu = _menuItemCollectionFactory.Create(); - menu.Items.Add(Services.TextService, opensDialog: true); + menu.Items.Add(LocalizedTextService, opensDialog: true); if (id != Constants.System.RootString) - menu.Items.Add(Services.TextService, true, opensDialog: true); + menu.Items.Add(LocalizedTextService, true, opensDialog: true); - menu.Items.Add(new RefreshNode(Services.TextService, true)); + menu.Items.Add(new RefreshNode(LocalizedTextService, true)); return menu; } diff --git a/src/Umbraco.Web/Trees/FileSystemTreeController.cs b/src/Umbraco.Web.BackOffice/Trees/FileSystemTreeController.cs similarity index 78% rename from src/Umbraco.Web/Trees/FileSystemTreeController.cs rename to src/Umbraco.Web.BackOffice/Trees/FileSystemTreeController.cs index eb13daea29..c9bde4818f 100644 --- a/src/Umbraco.Web/Trees/FileSystemTreeController.cs +++ b/src/Umbraco.Web.BackOffice/Trees/FileSystemTreeController.cs @@ -1,42 +1,26 @@ using System; using System.IO; using System.Linq; -using System.Net.Http.Formatting; using System.Web; +using Microsoft.AspNetCore.Http; using Umbraco.Core; -using Umbraco.Core.Cache; -using Umbraco.Core.Configuration; using Umbraco.Core.IO; -using Umbraco.Core.Logging; -using Umbraco.Core.Mapping; -using Umbraco.Core.Persistence; using Umbraco.Core.Services; using Umbraco.Web.Actions; -using Umbraco.Web.Composing; using Umbraco.Web.Models.Trees; -using Umbraco.Web.Routing; +using Umbraco.Web.Trees; +using Umbraco.Web.WebApi; -namespace Umbraco.Web.Trees +namespace Umbraco.Web.BackOffice.Trees { public abstract class FileSystemTreeController : TreeController { - protected FileSystemTreeController() - { - MenuItemCollectionFactory = Current.MenuItemCollectionFactory; - } - protected FileSystemTreeController( - IGlobalSettings globalSettings, - IUmbracoContextAccessor umbracoContextAccessor, - ISqlContext sqlContext, - ServiceContext services, - AppCaches appCaches, - IProfilingLogger logger, - IRuntimeState runtimeState, - UmbracoMapper umbracoMapper, - IPublishedUrlProvider publishedUrlProvider, - IMenuItemCollectionFactory menuItemCollectionFactory) - : base(globalSettings, umbracoContextAccessor, sqlContext, services, appCaches, logger, runtimeState, umbracoMapper, publishedUrlProvider) + ILocalizedTextService localizedTextService, + UmbracoApiControllerTypeCollection umbracoApiControllerTypeCollection, + IMenuItemCollectionFactory menuItemCollectionFactory + ) + : base(localizedTextService, umbracoApiControllerTypeCollection) { MenuItemCollectionFactory = menuItemCollectionFactory; } @@ -61,7 +45,7 @@ namespace Umbraco.Web.Trees treeNode.AdditionalData["jsClickCallback"] = "javascript:void(0);"; } - protected override TreeNodeCollection GetTreeNodes(string id, FormDataCollection queryStrings) + protected override TreeNodeCollection GetTreeNodes(string id, FormCollection queryStrings) { var path = string.IsNullOrEmpty(id) == false && id != Constants.System.RootString ? HttpUtility.UrlDecode(id).TrimStart("/") @@ -108,7 +92,7 @@ namespace Umbraco.Web.Trees return nodes; } - protected override TreeNode CreateRootNode(FormDataCollection queryStrings) + protected override TreeNode CreateRootNode(FormCollection queryStrings) { var root = base.CreateRootNode(queryStrings); //check if there are any children @@ -116,28 +100,28 @@ namespace Umbraco.Web.Trees return root; } - protected virtual MenuItemCollection GetMenuForRootNode(FormDataCollection queryStrings) + protected virtual MenuItemCollection GetMenuForRootNode(FormCollection queryStrings) { var menu = MenuItemCollectionFactory.Create(); //set the default to create menu.DefaultMenuAlias = ActionNew.ActionAlias; //create action - menu.Items.Add(Services.TextService, opensDialog: true); + menu.Items.Add(LocalizedTextService, opensDialog: true); //refresh action - menu.Items.Add(new RefreshNode(Services.TextService, true)); + menu.Items.Add(new RefreshNode(LocalizedTextService, true)); return menu; } - protected virtual MenuItemCollection GetMenuForFolder(string path, FormDataCollection queryStrings) + protected virtual MenuItemCollection GetMenuForFolder(string path, FormCollection queryStrings) { var menu = MenuItemCollectionFactory.Create(); //set the default to create menu.DefaultMenuAlias = ActionNew.ActionAlias; //create action - menu.Items.Add(Services.TextService, opensDialog: true); + menu.Items.Add(LocalizedTextService, opensDialog: true); var hasChildren = FileSystem.GetFiles(path).Any() || FileSystem.GetDirectories(path).Any(); @@ -145,26 +129,26 @@ namespace Umbraco.Web.Trees if (hasChildren == false) { //delete action - menu.Items.Add(Services.TextService, true, opensDialog: true); + menu.Items.Add(LocalizedTextService, true, opensDialog: true); } //refresh action - menu.Items.Add(new RefreshNode(Services.TextService, true)); + menu.Items.Add(new RefreshNode(LocalizedTextService, true)); return menu; } - protected virtual MenuItemCollection GetMenuForFile(string path, FormDataCollection queryStrings) + protected virtual MenuItemCollection GetMenuForFile(string path, FormCollection queryStrings) { var menu = MenuItemCollectionFactory.Create(); //if it's not a directory then we only allow to delete the item - menu.Items.Add(Services.TextService, opensDialog: true); + menu.Items.Add(LocalizedTextService, opensDialog: true); return menu; } - protected override MenuItemCollection GetMenuForNode(string id, FormDataCollection queryStrings) + protected override MenuItemCollection GetMenuForNode(string id, FormCollection queryStrings) { //if root node no need to visit the filesystem so lets just create the menu and return it if (id == Constants.System.RootString) diff --git a/src/Umbraco.Web.BackOffice/Trees/FilesTreeController.cs b/src/Umbraco.Web.BackOffice/Trees/FilesTreeController.cs new file mode 100644 index 0000000000..59fc9739d1 --- /dev/null +++ b/src/Umbraco.Web.BackOffice/Trees/FilesTreeController.cs @@ -0,0 +1,33 @@ +using Umbraco.Core; +using Umbraco.Core.Hosting; +using Umbraco.Core.IO; +using Umbraco.Core.Logging; +using Umbraco.Core.Services; +using Umbraco.Web.BackOffice.Trees; +using Umbraco.Web.WebApi; + +namespace Umbraco.Web.Trees +{ + [Tree(Constants.Applications.Settings, "files", TreeTitle = "Files", TreeUse = TreeUse.Dialog)] + [CoreTree] + public class FilesTreeController : FileSystemTreeController + { + protected override IFileSystem FileSystem { get; } + + private static readonly string[] ExtensionsStatic = { "*" }; + + public FilesTreeController( + ILocalizedTextService localizedTextService, + UmbracoApiControllerTypeCollection umbracoApiControllerTypeCollection, + IMenuItemCollectionFactory menuItemCollectionFactory, + IFileSystem fileSystem) + : base(localizedTextService, umbracoApiControllerTypeCollection, menuItemCollectionFactory) + { + FileSystem = fileSystem; + } + + protected override string[] Extensions => ExtensionsStatic; + + protected override string FileIcon => Constants.Icons.MediaFile; + } +} diff --git a/src/Umbraco.Web.BackOffice/Trees/ITreeNodeController.cs b/src/Umbraco.Web.BackOffice/Trees/ITreeNodeController.cs new file mode 100644 index 0000000000..ecdc7b781d --- /dev/null +++ b/src/Umbraco.Web.BackOffice/Trees/ITreeNodeController.cs @@ -0,0 +1,24 @@ +using Umbraco.Web.Models.Trees; +using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Mvc; +using Umbraco.Web.Common.ModelBinders; + +namespace Umbraco.Web.Trees +{ + /// + /// Represents an TreeNodeController + /// + public interface ITreeNodeController + { + /// + /// Gets an individual tree node + /// + /// + /// + /// + ActionResult GetTreeNode( + string id, + [ModelBinder(typeof(HttpQueryStringModelBinder))] FormCollection queryStrings + ); + } +} diff --git a/src/Umbraco.Web/Trees/LogViewerTreeController.cs b/src/Umbraco.Web.BackOffice/Trees/LogViewerTreeController.cs similarity index 69% rename from src/Umbraco.Web/Trees/LogViewerTreeController.cs rename to src/Umbraco.Web.BackOffice/Trees/LogViewerTreeController.cs index 6f274babeb..e9fe918c52 100644 --- a/src/Umbraco.Web/Trees/LogViewerTreeController.cs +++ b/src/Umbraco.Web.BackOffice/Trees/LogViewerTreeController.cs @@ -1,8 +1,10 @@ -using System.Net.Http.Formatting; -using Umbraco.Core; +using Microsoft.AspNetCore.Http; +using Umbraco.Core.Services; +using Umbraco.Web.BackOffice.Filters; +using Umbraco.Web.BackOffice.Trees; +using Umbraco.Web.Common.Attributes; using Umbraco.Web.Models.Trees; -using Umbraco.Web.Mvc; -using Umbraco.Web.WebApi.Filters; +using Umbraco.Web.WebApi; using Constants = Umbraco.Core.Constants; namespace Umbraco.Web.Trees @@ -13,13 +15,20 @@ namespace Umbraco.Web.Trees [CoreTree] public class LogViewerTreeController : TreeController { - protected override TreeNodeCollection GetTreeNodes(string id, FormDataCollection queryStrings) + public LogViewerTreeController( + ILocalizedTextService localizedTextService, + UmbracoApiControllerTypeCollection umbracoApiControllerTypeCollection) + : base(localizedTextService, umbracoApiControllerTypeCollection) + { + } + + protected override TreeNodeCollection GetTreeNodes(string id, FormCollection queryStrings) { //We don't have any child nodes & only use the root node to load a custom UI return new TreeNodeCollection(); } - protected override MenuItemCollection GetMenuForNode(string id, FormDataCollection queryStrings) + protected override MenuItemCollection GetMenuForNode(string id, FormCollection queryStrings) { //We don't have any menu item options (such as create/delete/reload) & only use the root node to load a custom UI return null; @@ -29,7 +38,7 @@ namespace Umbraco.Web.Trees /// Helper method to create a root model for a tree /// /// - protected override TreeNode CreateRootNode(FormDataCollection queryStrings) + protected override TreeNode CreateRootNode(FormCollection queryStrings) { var root = base.CreateRootNode(queryStrings); diff --git a/src/Umbraco.Web/Trees/MacrosTreeController.cs b/src/Umbraco.Web.BackOffice/Trees/MacrosTreeController.cs similarity index 55% rename from src/Umbraco.Web/Trees/MacrosTreeController.cs rename to src/Umbraco.Web.BackOffice/Trees/MacrosTreeController.cs index 217298a7eb..c3d15996d5 100644 --- a/src/Umbraco.Web/Trees/MacrosTreeController.cs +++ b/src/Umbraco.Web.BackOffice/Trees/MacrosTreeController.cs @@ -1,17 +1,12 @@ using System.Linq; -using System.Net.Http.Formatting; -using Umbraco.Core; -using Umbraco.Core.Cache; -using Umbraco.Core.Configuration; -using Umbraco.Core.Logging; -using Umbraco.Core.Mapping; -using Umbraco.Core.Persistence; +using Microsoft.AspNetCore.Http; using Umbraco.Core.Services; using Umbraco.Web.Models.Trees; -using Umbraco.Web.Mvc; -using Umbraco.Web.WebApi.Filters; using Umbraco.Web.Actions; -using Umbraco.Web.Routing; +using Umbraco.Web.BackOffice.Filters; +using Umbraco.Web.BackOffice.Trees; +using Umbraco.Web.Common.Attributes; +using Umbraco.Web.WebApi; using Constants = Umbraco.Core.Constants; namespace Umbraco.Web.Trees @@ -23,38 +18,29 @@ namespace Umbraco.Web.Trees public class MacrosTreeController : TreeController { private readonly IMenuItemCollectionFactory _menuItemCollectionFactory; + private readonly IMacroService _macroService; - public MacrosTreeController( - IGlobalSettings globalSettings, - IUmbracoContextAccessor umbracoContextAccessor, - ISqlContext sqlContext, - ServiceContext services, - AppCaches appCaches, - IProfilingLogger logger, - IRuntimeState runtimeState, - UmbracoMapper umbracoMapper, - IPublishedUrlProvider publishedUrlProvider, - IMenuItemCollectionFactory menuItemCollectionFactory) - : base(globalSettings, umbracoContextAccessor, sqlContext, services, appCaches, logger, runtimeState, umbracoMapper, publishedUrlProvider) + public MacrosTreeController(ILocalizedTextService localizedTextService, UmbracoApiControllerTypeCollection umbracoApiControllerTypeCollection, IMenuItemCollectionFactory menuItemCollectionFactory, IMacroService macroService) : base(localizedTextService, umbracoApiControllerTypeCollection) { _menuItemCollectionFactory = menuItemCollectionFactory; + _macroService = macroService; } - protected override TreeNode CreateRootNode(FormDataCollection queryStrings) + protected override TreeNode CreateRootNode(FormCollection queryStrings) { var root = base.CreateRootNode(queryStrings); //check if there are any macros - root.HasChildren = Services.MacroService.GetAll().Any(); + root.HasChildren = _macroService.GetAll().Any(); return root; } - protected override TreeNodeCollection GetTreeNodes(string id, FormDataCollection queryStrings) + protected override TreeNodeCollection GetTreeNodes(string id, FormCollection queryStrings) { var nodes = new TreeNodeCollection(); if (id == Constants.System.RootString) { - foreach (var macro in Services.MacroService.GetAll().OrderBy(m => m.Name)) + foreach (var macro in _macroService.GetAll().OrderBy(m => m.Name)) { nodes.Add(CreateTreeNode( macro.Id.ToString(), @@ -69,26 +55,26 @@ namespace Umbraco.Web.Trees return nodes; } - protected override MenuItemCollection GetMenuForNode(string id, FormDataCollection queryStrings) + protected override MenuItemCollection GetMenuForNode(string id, FormCollection queryStrings) { var menu = _menuItemCollectionFactory.Create(); if (id == Constants.System.RootString) { //Create the normal create action - menu.Items.Add(Services.TextService); + menu.Items.Add(LocalizedTextService); //refresh action - menu.Items.Add(new RefreshNode(Services.TextService, true)); + menu.Items.Add(new RefreshNode(LocalizedTextService, true)); return menu; } - var macro = Services.MacroService.GetById(int.Parse(id)); + var macro = _macroService.GetById(int.Parse(id)); if (macro == null) return menu; //add delete option for all macros - menu.Items.Add(Services.TextService, opensDialog: true); + menu.Items.Add(LocalizedTextService, opensDialog: true); return menu; } diff --git a/src/Umbraco.Web/Trees/MediaTreeController.cs b/src/Umbraco.Web.BackOffice/Trees/MediaTreeController.cs similarity index 67% rename from src/Umbraco.Web/Trees/MediaTreeController.cs rename to src/Umbraco.Web.BackOffice/Trees/MediaTreeController.cs index 37f0c8dead..46ef45e85d 100644 --- a/src/Umbraco.Web/Trees/MediaTreeController.cs +++ b/src/Umbraco.Web.BackOffice/Trees/MediaTreeController.cs @@ -2,26 +2,23 @@ using System.Collections.Generic; using System.Linq; using System.Net; -using System.Net.Http.Formatting; -using System.Web.Http; +using Microsoft.AspNetCore.Http; using Umbraco.Core; using Umbraco.Core.Models; using Umbraco.Core.Models.Entities; using Umbraco.Core.Services; using Umbraco.Web.Actions; using Umbraco.Web.Models.Trees; -using Umbraco.Web.Mvc; -using Umbraco.Web.WebApi.Filters; using Umbraco.Web.Models.ContentEditing; using Umbraco.Web.Search; -using Umbraco.Core.Services.Implement; -using Umbraco.Core.Cache; -using Umbraco.Core.Configuration; using Umbraco.Core.Logging; -using Umbraco.Core.Persistence; using Constants = Umbraco.Core.Constants; -using Umbraco.Core.Mapping; -using Umbraco.Web.Routing; +using Umbraco.Web.BackOffice.Filters; +using Umbraco.Web.BackOffice.Trees; +using Umbraco.Web.Common.Attributes; +using Umbraco.Web.Common.Exceptions; +using Umbraco.Web.Security; +using Umbraco.Web.WebApi; namespace Umbraco.Web.Trees { @@ -40,31 +37,37 @@ namespace Umbraco.Web.Trees public class MediaTreeController : ContentTreeControllerBase, ISearchableTree, ITreeNodeController { private readonly UmbracoTreeSearcher _treeSearcher; + private readonly IMediaService _mediaService; + private readonly IEntityService _entityService; + private readonly IWebSecurity _webSecurity; public MediaTreeController( + ILocalizedTextService localizedTextService, + UmbracoApiControllerTypeCollection umbracoApiControllerTypeCollection, + IMenuItemCollectionFactory menuItemCollectionFactory, + IEntityService entityService, + IWebSecurity webSecurity, + ILogger logger, + ActionCollection actionCollection, + IUserService userService, + IDataTypeService dataTypeService, UmbracoTreeSearcher treeSearcher, - IGlobalSettings globalSettings, - IUmbracoContextAccessor umbracoContextAccessor, - ISqlContext sqlContext, - ServiceContext services, - AppCaches appCaches, - IProfilingLogger logger, - IRuntimeState runtimeState, - UmbracoMapper umbracoMapper, - IPublishedUrlProvider publishedUrlProvider, - IMenuItemCollectionFactory menuItemCollectionFactory) - : base(globalSettings, umbracoContextAccessor, sqlContext, services, appCaches, logger, runtimeState, umbracoMapper, publishedUrlProvider, menuItemCollectionFactory) + IMediaService mediaService) + : base(localizedTextService, umbracoApiControllerTypeCollection, menuItemCollectionFactory, entityService, webSecurity, logger, actionCollection, userService, dataTypeService) { _treeSearcher = treeSearcher; + _mediaService = mediaService; + _entityService = entityService; + _webSecurity = webSecurity; } protected override int RecycleBinId => Constants.System.RecycleBinMedia; - protected override bool RecycleBinSmells => Services.MediaService.RecycleBinSmells(); + protected override bool RecycleBinSmells => _mediaService.RecycleBinSmells(); private int[] _userStartNodes; protected override int[] UserStartNodes - => _userStartNodes ?? (_userStartNodes = Security.CurrentUser.CalculateMediaStartNodeIds(Services.EntityService)); + => _userStartNodes ?? (_userStartNodes = _webSecurity.CurrentUser.CalculateMediaStartNodeIds(_entityService)); /// /// Creates a tree node for a content item based on an UmbracoEntity @@ -73,7 +76,7 @@ namespace Umbraco.Web.Trees /// /// /// - protected override TreeNode GetSingleTreeNode(IEntitySlim entity, string parentId, FormDataCollection queryStrings) + protected override TreeNode GetSingleTreeNode(IEntitySlim entity, string parentId, FormCollection queryStrings) { var node = CreateTreeNode( entity, @@ -97,7 +100,7 @@ namespace Umbraco.Web.Trees return node; } - protected override MenuItemCollection PerformGetMenuForNode(string id, FormDataCollection queryStrings) + protected override MenuItemCollection PerformGetMenuForNode(string id, FormCollection queryStrings) { var menu = MenuItemCollectionFactory.Create(); @@ -109,14 +112,14 @@ namespace Umbraco.Web.Trees // if the user's start node is not the root then the only menu item to display is refresh if (UserStartNodes.Contains(Constants.System.Root) == false) { - menu.Items.Add(new RefreshNode(Services.TextService, true)); + menu.Items.Add(new RefreshNode(LocalizedTextService, true)); return menu; } // root actions - menu.Items.Add(Services.TextService, opensDialog: true); - menu.Items.Add(Services.TextService, true); - menu.Items.Add(new RefreshNode(Services.TextService, true)); + menu.Items.Add(LocalizedTextService, opensDialog: true); + menu.Items.Add(LocalizedTextService, true); + menu.Items.Add(new RefreshNode(LocalizedTextService, true)); return menu; } @@ -124,16 +127,16 @@ namespace Umbraco.Web.Trees { throw new HttpResponseException(HttpStatusCode.NotFound); } - var item = Services.EntityService.Get(iid, UmbracoObjectTypes.Media); + var item = _entityService.Get(iid, UmbracoObjectTypes.Media); if (item == null) { throw new HttpResponseException(HttpStatusCode.NotFound); } //if the user has no path access for this node, all they can do is refresh - if (!Security.CurrentUser.HasMediaPathAccess(item, Services.EntityService)) + if (!_webSecurity.CurrentUser.HasMediaPathAccess(item, _entityService)) { - menu.Items.Add(new RefreshNode(Services.TextService, true)); + menu.Items.Add(new RefreshNode(LocalizedTextService, true)); return menu; } @@ -141,10 +144,10 @@ namespace Umbraco.Web.Trees //if the media item is in the recycle bin, we don't have a default menu and we need to show a limited menu if (item.Path.Split(new[] {','}, StringSplitOptions.RemoveEmptyEntries).Contains(RecycleBinId.ToInvariantString())) { - menu.Items.Add(Services.TextService, opensDialog: true); - menu.Items.Add(Services.TextService, opensDialog: true); - menu.Items.Add(Services.TextService, opensDialog: true); - menu.Items.Add(new RefreshNode(Services.TextService, true)); + menu.Items.Add(LocalizedTextService, opensDialog: true); + menu.Items.Add(LocalizedTextService, opensDialog: true); + menu.Items.Add(LocalizedTextService, opensDialog: true); + menu.Items.Add(new RefreshNode(LocalizedTextService, true)); menu.DefaultMenuAlias = null; @@ -152,11 +155,11 @@ namespace Umbraco.Web.Trees else { //return a normal node menu: - menu.Items.Add(Services.TextService, opensDialog: true); - menu.Items.Add(Services.TextService, opensDialog: true); - menu.Items.Add(Services.TextService, opensDialog: true); - menu.Items.Add(Services.TextService); - menu.Items.Add(new RefreshNode(Services.TextService, true)); + menu.Items.Add(LocalizedTextService, opensDialog: true); + menu.Items.Add(LocalizedTextService, opensDialog: true); + menu.Items.Add(LocalizedTextService, opensDialog: true); + menu.Items.Add(LocalizedTextService); + menu.Items.Add(new RefreshNode(LocalizedTextService, true)); //set the default to create menu.DefaultMenuAlias = ActionNew.ActionAlias; @@ -173,7 +176,7 @@ namespace Umbraco.Web.Trees /// /// /// - protected override bool HasPathAccess(string id, FormDataCollection queryStrings) + protected override bool HasPathAccess(string id, FormCollection queryStrings) { var entity = GetEntityFromId(id); diff --git a/src/Umbraco.Web/Trees/MediaTypeTreeController.cs b/src/Umbraco.Web.BackOffice/Trees/MediaTypeTreeController.cs similarity index 64% rename from src/Umbraco.Web/Trees/MediaTypeTreeController.cs rename to src/Umbraco.Web.BackOffice/Trees/MediaTypeTreeController.cs index 4677b251f3..27f4f8f77e 100644 --- a/src/Umbraco.Web/Trees/MediaTypeTreeController.cs +++ b/src/Umbraco.Web.BackOffice/Trees/MediaTypeTreeController.cs @@ -1,55 +1,41 @@ using System; using System.Collections.Generic; using System.Linq; -using System.Net.Http.Formatting; +using Microsoft.AspNetCore.Http; using Umbraco.Core; using Umbraco.Core.Models; using Umbraco.Web.Models.Trees; -using Umbraco.Web.WebApi.Filters; using Umbraco.Core.Services; using Umbraco.Web.Actions; using Umbraco.Web.Models.ContentEditing; -using Umbraco.Core.Cache; -using Umbraco.Core.Configuration; -using Umbraco.Core.Logging; -using Umbraco.Core.Persistence; using Umbraco.Web.Search; -using Umbraco.Core.Mapping; -using Umbraco.Web.Routing; +using Umbraco.Web.BackOffice.Filters; +using Umbraco.Web.BackOffice.Trees; +using Umbraco.Web.Common.Attributes; +using Umbraco.Web.WebApi; namespace Umbraco.Web.Trees { [UmbracoTreeAuthorize(Constants.Trees.MediaTypes)] [Tree(Constants.Applications.Settings, Constants.Trees.MediaTypes, SortOrder = 1, TreeGroup = Constants.Trees.Groups.Settings)] - [Mvc.PluginController("UmbracoTrees")] + [PluginController("UmbracoTrees")] [CoreTree] public class MediaTypeTreeController : TreeController, ISearchableTree { private readonly UmbracoTreeSearcher _treeSearcher; private readonly IMenuItemCollectionFactory _menuItemCollectionFactory; private readonly IMediaTypeService _mediaTypeService; + private readonly IEntityService _entityService; - public MediaTypeTreeController( - UmbracoTreeSearcher treeSearcher, - IGlobalSettings globalSettings, - IUmbracoContextAccessor umbracoContextAccessor, - ISqlContext sqlContext, - ServiceContext services, - AppCaches appCaches, - IProfilingLogger logger, - IRuntimeState runtimeState, - UmbracoMapper umbracoMapper, - IPublishedUrlProvider publishedUrlProvider, - IMenuItemCollectionFactory menuItemCollectionFactory, - IMediaTypeService mediaTypeService) - : base(globalSettings, umbracoContextAccessor, sqlContext, services, appCaches, logger, runtimeState, umbracoMapper, publishedUrlProvider) + public MediaTypeTreeController(ILocalizedTextService localizedTextService, UmbracoApiControllerTypeCollection umbracoApiControllerTypeCollection, UmbracoTreeSearcher treeSearcher, IMenuItemCollectionFactory menuItemCollectionFactory, IMediaTypeService mediaTypeService, IEntityService entityService) : base(localizedTextService, umbracoApiControllerTypeCollection) { _treeSearcher = treeSearcher; _menuItemCollectionFactory = menuItemCollectionFactory; _mediaTypeService = mediaTypeService; + _entityService = entityService; } - protected override TreeNodeCollection GetTreeNodes(string id, FormDataCollection queryStrings) + protected override TreeNodeCollection GetTreeNodes(string id, FormCollection queryStrings) { var intId = id.TryConvertTo(); if (intId == false) throw new InvalidOperationException("Id must be an integer"); @@ -57,7 +43,7 @@ namespace Umbraco.Web.Trees var nodes = new TreeNodeCollection(); nodes.AddRange( - Services.EntityService.GetChildren(intId.Result, UmbracoObjectTypes.MediaTypeContainer) + _entityService.GetChildren(intId.Result, UmbracoObjectTypes.MediaTypeContainer) .OrderBy(entity => entity.Name) .Select(dt => { @@ -70,12 +56,12 @@ namespace Umbraco.Web.Trees })); // if the request is for folders only then just return - if (queryStrings["foldersonly"].IsNullOrWhiteSpace() == false && queryStrings["foldersonly"] == "1") return nodes; + if (queryStrings["foldersonly"].ToString().IsNullOrWhiteSpace() == false && queryStrings["foldersonly"].ToString() == "1") return nodes; var mediaTypes = _mediaTypeService.GetAll(); nodes.AddRange( - Services.EntityService.GetChildren(intId.Result, UmbracoObjectTypes.MediaType) + _entityService.GetChildren(intId.Result, UmbracoObjectTypes.MediaType) .OrderBy(entity => entity.Name) .Select(dt => { @@ -92,7 +78,7 @@ namespace Umbraco.Web.Trees return nodes; } - protected override MenuItemCollection GetMenuForNode(string id, FormDataCollection queryStrings) + protected override MenuItemCollection GetMenuForNode(string id, FormCollection queryStrings) { var menu = _menuItemCollectionFactory.Create(); @@ -102,20 +88,20 @@ namespace Umbraco.Web.Trees menu.DefaultMenuAlias = ActionNew.ActionAlias; // root actions - menu.Items.Add(Services.TextService, opensDialog: true); - menu.Items.Add(new RefreshNode(Services.TextService)); + menu.Items.Add(LocalizedTextService, opensDialog: true); + menu.Items.Add(new RefreshNode(LocalizedTextService)); return menu; } - var container = Services.EntityService.Get(int.Parse(id), UmbracoObjectTypes.MediaTypeContainer); + var container = _entityService.Get(int.Parse(id), UmbracoObjectTypes.MediaTypeContainer); if (container != null) { // set the default to create menu.DefaultMenuAlias = ActionNew.ActionAlias; - menu.Items.Add(Services.TextService, opensDialog: true); + menu.Items.Add(LocalizedTextService, opensDialog: true); - menu.Items.Add(new MenuItem("rename", Services.TextService.Localize("actions/rename")) + menu.Items.Add(new MenuItem("rename", LocalizedTextService.Localize("actions/rename")) { Icon = "icon icon-edit" }); @@ -123,29 +109,29 @@ namespace Umbraco.Web.Trees if (container.HasChildren == false) { // can delete doc type - menu.Items.Add(Services.TextService, opensDialog: true); + menu.Items.Add(LocalizedTextService, opensDialog: true); } - menu.Items.Add(new RefreshNode(Services.TextService, true)); + menu.Items.Add(new RefreshNode(LocalizedTextService, true)); } else { - var ct = Services.MediaTypeService.Get(int.Parse(id)); - var parent = ct == null ? null : Services.MediaTypeService.Get(ct.ParentId); + var ct = _mediaTypeService.Get(int.Parse(id)); + var parent = ct == null ? null : _mediaTypeService.Get(ct.ParentId); - menu.Items.Add(Services.TextService, opensDialog: true); + menu.Items.Add(LocalizedTextService, opensDialog: true); // no move action if this is a child doc type if (parent == null) { - menu.Items.Add(Services.TextService, true, opensDialog: true); + menu.Items.Add(LocalizedTextService, true, opensDialog: true); } - menu.Items.Add(Services.TextService, opensDialog: true); + menu.Items.Add(LocalizedTextService, opensDialog: true); if(ct.IsSystemMediaType() == false) { - menu.Items.Add(Services.TextService, opensDialog: true); + menu.Items.Add(LocalizedTextService, opensDialog: true); } - menu.Items.Add(new RefreshNode(Services.TextService, true)); + menu.Items.Add(new RefreshNode(LocalizedTextService, true)); } diff --git a/src/Umbraco.Web.BackOffice/Trees/MemberGroupTreeController.cs b/src/Umbraco.Web.BackOffice/Trees/MemberGroupTreeController.cs new file mode 100644 index 0000000000..06bd355b7d --- /dev/null +++ b/src/Umbraco.Web.BackOffice/Trees/MemberGroupTreeController.cs @@ -0,0 +1,47 @@ +using System.Collections.Generic; +using System.Linq; +using Microsoft.AspNetCore.Http; +using Umbraco.Core; +using Umbraco.Core.Services; +using Umbraco.Web.BackOffice.Filters; +using Umbraco.Web.BackOffice.Trees; +using Umbraco.Web.Common.Attributes; +using Umbraco.Web.Models.Trees; +using Umbraco.Web.WebApi; + +namespace Umbraco.Web.Trees +{ + [UmbracoTreeAuthorize(Constants.Trees.MemberGroups)] + [Tree(Constants.Applications.Members, Constants.Trees.MemberGroups, SortOrder = 1)] + [PluginController("UmbracoTrees")] + [CoreTree] + public class MemberGroupTreeController : MemberTypeAndGroupTreeControllerBase + { + private readonly IMemberGroupService _memberGroupService; + + public MemberGroupTreeController( + ILocalizedTextService localizedTextService, + UmbracoApiControllerTypeCollection umbracoApiControllerTypeCollection, + IMenuItemCollectionFactory menuItemCollectionFactory, + IMemberGroupService memberGroupService) + : base(localizedTextService, umbracoApiControllerTypeCollection, menuItemCollectionFactory) + { + _memberGroupService = memberGroupService; + } + + protected override IEnumerable GetTreeNodesFromService(string id, FormCollection queryStrings) + { + return _memberGroupService.GetAll() + .OrderBy(x => x.Name) + .Select(dt => CreateTreeNode(dt.Id.ToString(), id, queryStrings, dt.Name, Constants.Icons.MemberGroup, false)); + } + + protected override TreeNode CreateRootNode(FormCollection queryStrings) + { + var root = base.CreateRootNode(queryStrings); + //check if there are any groups + root.HasChildren = _memberGroupService.GetAll().Any(); + return root; + } + } +} diff --git a/src/Umbraco.Web/Trees/MemberTreeController.cs b/src/Umbraco.Web.BackOffice/Trees/MemberTreeController.cs similarity index 70% rename from src/Umbraco.Web/Trees/MemberTreeController.cs rename to src/Umbraco.Web.BackOffice/Trees/MemberTreeController.cs index b4efc27b24..967e4f22fc 100644 --- a/src/Umbraco.Web/Trees/MemberTreeController.cs +++ b/src/Umbraco.Web.BackOffice/Trees/MemberTreeController.cs @@ -1,29 +1,23 @@ using System; using System.Collections.Generic; using System.Linq; -using System.Net; -using System.Net.Http; -using System.Net.Http.Formatting; -using System.Web.Http; -using System.Web.Http.ModelBinding; +using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Mvc; using Umbraco.Core; -using Umbraco.Core.Cache; -using Umbraco.Core.Configuration; -using Umbraco.Core.Logging; -using Umbraco.Core.Mapping; using Umbraco.Core.Models; -using Umbraco.Core.Persistence; using Umbraco.Core.Services; -using Umbraco.Core.Security; +using Umbraco.Extensions; using Umbraco.Web.Actions; +using Umbraco.Web.BackOffice.Filters; +using Umbraco.Web.BackOffice.Trees; +using Umbraco.Web.Common.Attributes; +using Umbraco.Web.Common.ModelBinders; using Umbraco.Web.Models.Trees; -using Umbraco.Web.Mvc; -using Umbraco.Web.WebApi.Filters; using Umbraco.Web.Models.ContentEditing; -using Umbraco.Web.Routing; using Umbraco.Web.Search; using Constants = Umbraco.Core.Constants; using Umbraco.Web.Security; +using Umbraco.Web.WebApi; namespace Umbraco.Web.Trees { @@ -39,27 +33,27 @@ namespace Umbraco.Web.Trees [SearchableTree("searchResultFormatter", "configureMemberResult")] public class MemberTreeController : TreeController, ISearchableTree, ITreeNodeController { - - private readonly UmbracoTreeSearcher _treeSearcher; private readonly IMenuItemCollectionFactory _menuItemCollectionFactory; + private readonly IMemberService _memberService; + private readonly IMemberTypeService _memberTypeService; + private readonly IWebSecurity _webSecurity; public MemberTreeController( - IGlobalSettings globalSettings, - IUmbracoContextAccessor umbracoContextAccessor, - ISqlContext sqlContext, - ServiceContext services, - AppCaches appCaches, - IProfilingLogger logger, - IRuntimeState runtimeState, - UmbracoMapper umbracoMapper, - IPublishedUrlProvider publishedUrlProvider, + ILocalizedTextService localizedTextService, + UmbracoApiControllerTypeCollection umbracoApiControllerTypeCollection, UmbracoTreeSearcher treeSearcher, - IMenuItemCollectionFactory menuItemCollectionFactory) - : base(globalSettings, umbracoContextAccessor, sqlContext, services, appCaches, logger, runtimeState, umbracoMapper, publishedUrlProvider) + IMenuItemCollectionFactory menuItemCollectionFactory, + IMemberService memberService, + IMemberTypeService memberTypeService, + IWebSecurity webSecurity) + : base(localizedTextService, umbracoApiControllerTypeCollection) { _treeSearcher = treeSearcher; _menuItemCollectionFactory = menuItemCollectionFactory; + _memberService = memberService; + _memberTypeService = memberTypeService; + _webSecurity = webSecurity; } /// @@ -68,27 +62,27 @@ namespace Umbraco.Web.Trees /// /// /// - public TreeNode GetTreeNode(string id, [ModelBinder(typeof(HttpQueryStringModelBinder))]FormDataCollection queryStrings) + public ActionResult GetTreeNode(string id, [ModelBinder(typeof(HttpQueryStringModelBinder))]FormCollection queryStrings) { var node = GetSingleTreeNode(id, queryStrings); //add the tree alias to the node since it is standalone (has no root for which this normally belongs) - node.AdditionalData["treeAlias"] = TreeAlias; + node.Value.AdditionalData["treeAlias"] = TreeAlias; return node; } - protected TreeNode GetSingleTreeNode(string id, FormDataCollection queryStrings) + protected ActionResult GetSingleTreeNode(string id, FormCollection queryStrings) { Guid asGuid; if (Guid.TryParse(id, out asGuid) == false) { - throw new HttpResponseException(Request.CreateResponse(HttpStatusCode.NotFound)); + return NotFound(); } - var member = Services.MemberService.GetByKey(asGuid); + var member = _memberService.GetByKey(asGuid); if (member == null) { - throw new HttpResponseException(Request.CreateResponse(HttpStatusCode.NotFound)); + return NotFound(); } var node = CreateTreeNode( @@ -107,17 +101,17 @@ namespace Umbraco.Web.Trees return node; } - protected override TreeNodeCollection GetTreeNodes(string id, FormDataCollection queryStrings) + protected override TreeNodeCollection GetTreeNodes(string id, FormCollection queryStrings) { var nodes = new TreeNodeCollection(); if (id == Constants.System.RootString) { nodes.Add( - CreateTreeNode(Constants.Conventions.MemberTypes.AllMembersListId, id, queryStrings, Services.TextService.Localize("member/allMembers"), Constants.Icons.MemberType, true, + CreateTreeNode(Constants.Conventions.MemberTypes.AllMembersListId, id, queryStrings, LocalizedTextService.Localize("member/allMembers"), Constants.Icons.MemberType, true, queryStrings.GetRequiredValue("application") + TreeAlias.EnsureStartsWith('/') + "/list/" + Constants.Conventions.MemberTypes.AllMembersListId)); - nodes.AddRange(Services.MemberTypeService.GetAll() + nodes.AddRange(_memberTypeService.GetAll() .Select(memberType => CreateTreeNode(memberType.Alias, id, queryStrings, memberType.Name, memberType.Icon.IfNullOrWhiteSpace(Constants.Icons.Member), true, queryStrings.GetRequiredValue("application") + TreeAlias.EnsureStartsWith('/') + "/list/" + memberType.Alias))); @@ -131,7 +125,7 @@ namespace Umbraco.Web.Trees return nodes; } - protected override MenuItemCollection GetMenuForNode(string id, FormDataCollection queryStrings) + protected override MenuItemCollection GetMenuForNode(string id, FormCollection queryStrings) { var menu = _menuItemCollectionFactory.Create(); @@ -142,18 +136,18 @@ namespace Umbraco.Web.Trees menu.DefaultMenuAlias = ActionNew.ActionAlias; //Create the normal create action - menu.Items.Add(Services.TextService, opensDialog: true); + menu.Items.Add(LocalizedTextService, opensDialog: true); - menu.Items.Add(new RefreshNode(Services.TextService, true)); + menu.Items.Add(new RefreshNode(LocalizedTextService, true)); return menu; } //add delete option for all members - menu.Items.Add(Services.TextService, opensDialog: true); + menu.Items.Add(LocalizedTextService, opensDialog: true); - if (Security.CurrentUser.HasAccessToSensitiveData()) + if (_webSecurity.CurrentUser.HasAccessToSensitiveData()) { - menu.Items.Add(new ExportMember(Services.TextService)); + menu.Items.Add(new ExportMember(LocalizedTextService)); } return menu; diff --git a/src/Umbraco.Web/Trees/MemberTypeAndGroupTreeControllerBase.cs b/src/Umbraco.Web.BackOffice/Trees/MemberTypeAndGroupTreeControllerBase.cs similarity index 50% rename from src/Umbraco.Web/Trees/MemberTypeAndGroupTreeControllerBase.cs rename to src/Umbraco.Web.BackOffice/Trees/MemberTypeAndGroupTreeControllerBase.cs index 258a2aea5f..882ef6def3 100644 --- a/src/Umbraco.Web/Trees/MemberTypeAndGroupTreeControllerBase.cs +++ b/src/Umbraco.Web.BackOffice/Trees/MemberTypeAndGroupTreeControllerBase.cs @@ -1,73 +1,57 @@ using System.Collections.Generic; -using System.Net.Http.Formatting; +using Microsoft.AspNetCore.Http; using Umbraco.Core; -using Umbraco.Core.Cache; -using Umbraco.Core.Configuration; -using Umbraco.Core.Logging; -using Umbraco.Core.Mapping; -using Umbraco.Core.Persistence; using Umbraco.Core.Services; using Umbraco.Web.Actions; -using Umbraco.Web.Composing; +using Umbraco.Web.BackOffice.Trees; +using Umbraco.Web.Common.Attributes; using Umbraco.Web.Models.Trees; -using Umbraco.Web.Routing; +using Umbraco.Web.WebApi; namespace Umbraco.Web.Trees { - [Mvc.PluginController("UmbracoTrees")] + [PluginController("UmbracoTrees")] [CoreTree] public abstract class MemberTypeAndGroupTreeControllerBase : TreeController { public IMenuItemCollectionFactory MenuItemCollectionFactory { get; } - protected MemberTypeAndGroupTreeControllerBase() - { - MenuItemCollectionFactory = Current.MenuItemCollectionFactory; - } - protected MemberTypeAndGroupTreeControllerBase( - IGlobalSettings globalSettings, - IUmbracoContextAccessor umbracoContextAccessor, - ISqlContext sqlContext, - ServiceContext services, - AppCaches appCaches, - IProfilingLogger logger, - IRuntimeState runtimeState, - UmbracoMapper umbracoMapper, - IPublishedUrlProvider publishedUrlProvider, + ILocalizedTextService localizedTextService, + UmbracoApiControllerTypeCollection umbracoApiControllerTypeCollection, IMenuItemCollectionFactory menuItemCollectionFactory) - : base(globalSettings, umbracoContextAccessor, sqlContext, services, appCaches, logger, runtimeState, umbracoMapper, publishedUrlProvider) + : base(localizedTextService, umbracoApiControllerTypeCollection) { MenuItemCollectionFactory = menuItemCollectionFactory; } - protected override TreeNodeCollection GetTreeNodes(string id, FormDataCollection queryStrings) + protected override TreeNodeCollection GetTreeNodes(string id, FormCollection queryStrings) { var nodes = new TreeNodeCollection(); nodes.AddRange(GetTreeNodesFromService(id, queryStrings)); return nodes; } - protected override MenuItemCollection GetMenuForNode(string id, FormDataCollection queryStrings) + protected override MenuItemCollection GetMenuForNode(string id, FormCollection queryStrings) { var menu = MenuItemCollectionFactory.Create(); if (id == Constants.System.RootString) { // root actions - menu.Items.Add(new CreateChildEntity(Services.TextService)); - menu.Items.Add(new RefreshNode(Services.TextService, true)); + menu.Items.Add(new CreateChildEntity(LocalizedTextService)); + menu.Items.Add(new RefreshNode(LocalizedTextService, true)); return menu; } else { //delete member type/group - menu.Items.Add(Services.TextService, opensDialog: true); + menu.Items.Add(LocalizedTextService, opensDialog: true); } return menu; } - protected abstract IEnumerable GetTreeNodesFromService(string id, FormDataCollection queryStrings); + protected abstract IEnumerable GetTreeNodesFromService(string id, FormCollection queryStrings); } } diff --git a/src/Umbraco.Web/Trees/MemberTypeTreeController.cs b/src/Umbraco.Web.BackOffice/Trees/MemberTypeTreeController.cs similarity index 58% rename from src/Umbraco.Web/Trees/MemberTypeTreeController.cs rename to src/Umbraco.Web.BackOffice/Trees/MemberTypeTreeController.cs index 5db9088f20..169689897a 100644 --- a/src/Umbraco.Web/Trees/MemberTypeTreeController.cs +++ b/src/Umbraco.Web.BackOffice/Trees/MemberTypeTreeController.cs @@ -1,12 +1,15 @@ using System.Collections.Generic; using System.Linq; -using System.Net.Http.Formatting; +using Microsoft.AspNetCore.Http; using Umbraco.Core; using Umbraco.Core.Models; +using Umbraco.Core.Services; +using Umbraco.Web.BackOffice.Filters; +using Umbraco.Web.BackOffice.Trees; using Umbraco.Web.Models.ContentEditing; using Umbraco.Web.Models.Trees; using Umbraco.Web.Search; -using Umbraco.Web.WebApi.Filters; +using Umbraco.Web.WebApi; namespace Umbraco.Web.Trees { @@ -16,22 +19,31 @@ namespace Umbraco.Web.Trees public class MemberTypeTreeController : MemberTypeAndGroupTreeControllerBase, ISearchableTree { private readonly UmbracoTreeSearcher _treeSearcher; + private readonly IMemberTypeService _memberTypeService; - public MemberTypeTreeController(UmbracoTreeSearcher treeSearcher) + public MemberTypeTreeController( + ILocalizedTextService localizedTextService, + UmbracoApiControllerTypeCollection umbracoApiControllerTypeCollection, + IMenuItemCollectionFactory menuItemCollectionFactory, + UmbracoTreeSearcher treeSearcher, + IMemberTypeService memberTypeService) + : base(localizedTextService, umbracoApiControllerTypeCollection, menuItemCollectionFactory) { _treeSearcher = treeSearcher; + _memberTypeService = memberTypeService; } - protected override TreeNode CreateRootNode(FormDataCollection queryStrings) + + protected override TreeNode CreateRootNode(FormCollection queryStrings) { var root = base.CreateRootNode(queryStrings); //check if there are any member types - root.HasChildren = Services.MemberTypeService.GetAll().Any(); + root.HasChildren = _memberTypeService.GetAll().Any(); return root; } - protected override IEnumerable GetTreeNodesFromService(string id, FormDataCollection queryStrings) + protected override IEnumerable GetTreeNodesFromService(string id, FormCollection queryStrings) { - return Services.MemberTypeService.GetAll() + return _memberTypeService.GetAll() .OrderBy(x => x.Name) .Select(dt => CreateTreeNode(dt, Constants.ObjectTypes.MemberType, id, queryStrings, dt?.Icon ?? Constants.Icons.MemberType, false)); } diff --git a/src/Umbraco.Web/Trees/PackagesTreeController.cs b/src/Umbraco.Web.BackOffice/Trees/PackagesTreeController.cs similarity index 61% rename from src/Umbraco.Web/Trees/PackagesTreeController.cs rename to src/Umbraco.Web.BackOffice/Trees/PackagesTreeController.cs index 022e33750a..f58b822f1c 100644 --- a/src/Umbraco.Web/Trees/PackagesTreeController.cs +++ b/src/Umbraco.Web.BackOffice/Trees/PackagesTreeController.cs @@ -1,15 +1,10 @@ -using System.Net.Http.Formatting; -using Umbraco.Core; -using Umbraco.Core.Cache; -using Umbraco.Core.Configuration; -using Umbraco.Core.Logging; -using Umbraco.Core.Mapping; -using Umbraco.Core.Persistence; +using Microsoft.AspNetCore.Http; using Umbraco.Core.Services; +using Umbraco.Web.BackOffice.Filters; +using Umbraco.Web.BackOffice.Trees; +using Umbraco.Web.Common.Attributes; using Umbraco.Web.Models.Trees; -using Umbraco.Web.Mvc; -using Umbraco.Web.Routing; -using Umbraco.Web.WebApi.Filters; +using Umbraco.Web.WebApi; using Constants = Umbraco.Core.Constants; namespace Umbraco.Web.Trees @@ -23,26 +18,20 @@ namespace Umbraco.Web.Trees private readonly IMenuItemCollectionFactory _menuItemCollectionFactory; public PackagesTreeController( - IGlobalSettings globalSettings, - IUmbracoContextAccessor umbracoContextAccessor, - ISqlContext sqlContext, - ServiceContext services, - AppCaches appCaches, - IProfilingLogger logger, - IRuntimeState runtimeState, - UmbracoMapper umbracoMapper, - IPublishedUrlProvider publishedUrlProvider, + ILocalizedTextService localizedTextService, + UmbracoApiControllerTypeCollection umbracoApiControllerTypeCollection, IMenuItemCollectionFactory menuItemCollectionFactory) - : base(globalSettings, umbracoContextAccessor, sqlContext, services, appCaches, logger, runtimeState, umbracoMapper, publishedUrlProvider) + : base(localizedTextService, umbracoApiControllerTypeCollection) { _menuItemCollectionFactory = menuItemCollectionFactory; } + /// /// Helper method to create a root model for a tree /// /// - protected override TreeNode CreateRootNode(FormDataCollection queryStrings) + protected override TreeNode CreateRootNode(FormCollection queryStrings) { var root = base.CreateRootNode(queryStrings); @@ -55,13 +44,13 @@ namespace Umbraco.Web.Trees } - protected override TreeNodeCollection GetTreeNodes(string id, FormDataCollection queryStrings) + protected override TreeNodeCollection GetTreeNodes(string id, FormCollection queryStrings) { //full screen app without tree nodes return TreeNodeCollection.Empty; } - protected override MenuItemCollection GetMenuForNode(string id, FormDataCollection queryStrings) + protected override MenuItemCollection GetMenuForNode(string id, FormCollection queryStrings) { //doesn't have a menu, this is a full screen app without tree nodes return _menuItemCollectionFactory.Create(); diff --git a/src/Umbraco.Web/Trees/PartialViewMacrosTreeController.cs b/src/Umbraco.Web.BackOffice/Trees/PartialViewMacrosTreeController.cs similarity index 50% rename from src/Umbraco.Web/Trees/PartialViewMacrosTreeController.cs rename to src/Umbraco.Web.BackOffice/Trees/PartialViewMacrosTreeController.cs index 41fecefef3..612b59ca4a 100644 --- a/src/Umbraco.Web/Trees/PartialViewMacrosTreeController.cs +++ b/src/Umbraco.Web.BackOffice/Trees/PartialViewMacrosTreeController.cs @@ -1,9 +1,10 @@ -using Umbraco.Core; +using Umbraco.Composing; using Umbraco.Core.IO; -using Umbraco.Web.Composing; -using Umbraco.Web.Models.Trees; -using Umbraco.Web.Mvc; -using Umbraco.Web.WebApi.Filters; +using Umbraco.Core.Services; +using Umbraco.Web.BackOffice.Filters; +using Umbraco.Web.BackOffice.Trees; +using Umbraco.Web.Common.Attributes; +using Umbraco.Web.WebApi; using Constants = Umbraco.Core.Constants; namespace Umbraco.Web.Trees @@ -17,12 +18,22 @@ namespace Umbraco.Web.Trees [CoreTree] public class PartialViewMacrosTreeController : PartialViewsTreeController { - protected override IFileSystem FileSystem => Current.FileSystems.MacroPartialsFileSystem; + protected override IFileSystem FileSystem { get; } private static readonly string[] ExtensionsStatic = {"cshtml"}; protected override string[] Extensions => ExtensionsStatic; protected override string FileIcon => "icon-article"; + + public PartialViewMacrosTreeController( + ILocalizedTextService localizedTextService, + UmbracoApiControllerTypeCollection umbracoApiControllerTypeCollection, + IMenuItemCollectionFactory menuItemCollectionFactory, + IFileSystems fileSystems) + : base(localizedTextService, umbracoApiControllerTypeCollection, menuItemCollectionFactory, fileSystems) + { + FileSystem = fileSystems.MacroPartialsFileSystem; + } } } diff --git a/src/Umbraco.Web/Trees/PartialViewsTreeController.cs b/src/Umbraco.Web.BackOffice/Trees/PartialViewsTreeController.cs similarity index 51% rename from src/Umbraco.Web/Trees/PartialViewsTreeController.cs rename to src/Umbraco.Web.BackOffice/Trees/PartialViewsTreeController.cs index e1e848df76..afe720fde9 100644 --- a/src/Umbraco.Web/Trees/PartialViewsTreeController.cs +++ b/src/Umbraco.Web.BackOffice/Trees/PartialViewsTreeController.cs @@ -1,6 +1,12 @@ -using Umbraco.Core.IO; +using Umbraco.Composing; +using Umbraco.Core.IO; +using Umbraco.Core.Services; +using Umbraco.Web.BackOffice.Filters; +using Umbraco.Web.BackOffice.Trees; +using Umbraco.Web.Common.Attributes; using Umbraco.Web.Composing; using Umbraco.Web.Mvc; +using Umbraco.Web.WebApi; using Umbraco.Web.WebApi.Filters; using Constants = Umbraco.Core.Constants; @@ -15,12 +21,22 @@ namespace Umbraco.Web.Trees [CoreTree] public class PartialViewsTreeController : FileSystemTreeController { - protected override IFileSystem FileSystem => Current.FileSystems.PartialViewsFileSystem; + protected override IFileSystem FileSystem { get; } private static readonly string[] ExtensionsStatic = {"cshtml"}; protected override string[] Extensions => ExtensionsStatic; protected override string FileIcon => "icon-article"; + + public PartialViewsTreeController( + ILocalizedTextService localizedTextService, + UmbracoApiControllerTypeCollection umbracoApiControllerTypeCollection, + IMenuItemCollectionFactory menuItemCollectionFactory, + IFileSystems fileSystems) + : base(localizedTextService, umbracoApiControllerTypeCollection, menuItemCollectionFactory) + { + FileSystem = fileSystems.PartialViewsFileSystem; + } } } diff --git a/src/Umbraco.Web/Trees/RelationTypeTreeController.cs b/src/Umbraco.Web.BackOffice/Trees/RelationTypeTreeController.cs similarity index 56% rename from src/Umbraco.Web/Trees/RelationTypeTreeController.cs rename to src/Umbraco.Web.BackOffice/Trees/RelationTypeTreeController.cs index 48a0f6b84c..46c6f004c6 100644 --- a/src/Umbraco.Web/Trees/RelationTypeTreeController.cs +++ b/src/Umbraco.Web.BackOffice/Trees/RelationTypeTreeController.cs @@ -1,77 +1,70 @@ using System.Linq; -using System.Net.Http.Formatting; +using Microsoft.AspNetCore.Http; using Umbraco.Web.Models.Trees; -using Umbraco.Web.WebApi.Filters; using Umbraco.Core; -using Umbraco.Core.Cache; -using Umbraco.Core.Configuration; -using Umbraco.Core.Logging; -using Umbraco.Core.Mapping; -using Umbraco.Core.Persistence; +using Umbraco.Core.Models; using Umbraco.Core.Services; using Umbraco.Web.Actions; -using Umbraco.Web.Routing; -using Umbraco.Core.Models; +using Umbraco.Web.BackOffice.Filters; +using Umbraco.Web.BackOffice.Trees; +using Umbraco.Web.Common.Attributes; +using Umbraco.Web.WebApi; namespace Umbraco.Web.Trees { [UmbracoTreeAuthorize(Constants.Trees.RelationTypes)] [Tree(Constants.Applications.Settings, Constants.Trees.RelationTypes, SortOrder = 5, TreeGroup = Constants.Trees.Groups.Settings)] - [Mvc.PluginController("UmbracoTrees")] + [PluginController("UmbracoTrees")] [CoreTree] public class RelationTypeTreeController : TreeController { private readonly IMenuItemCollectionFactory _menuItemCollectionFactory; + private readonly IRelationService _relationService; public RelationTypeTreeController( - IGlobalSettings globalSettings, - IUmbracoContextAccessor umbracoContextAccessor, - ISqlContext sqlContext, - ServiceContext services, - AppCaches appCaches, - IProfilingLogger logger, - IRuntimeState runtimeState, - UmbracoMapper umbracoMapper, - IPublishedUrlProvider publishedUrlProvider, - IMenuItemCollectionFactory menuItemCollectionFactory) - : base(globalSettings, umbracoContextAccessor, sqlContext, services, appCaches, logger, runtimeState, umbracoMapper, publishedUrlProvider) + ILocalizedTextService localizedTextService, + UmbracoApiControllerTypeCollection umbracoApiControllerTypeCollection, + IMenuItemCollectionFactory menuItemCollectionFactory, + IRelationService relationService) + : base(localizedTextService, umbracoApiControllerTypeCollection) { _menuItemCollectionFactory = menuItemCollectionFactory; + _relationService = relationService; } - protected override MenuItemCollection GetMenuForNode(string id, FormDataCollection queryStrings) + protected override MenuItemCollection GetMenuForNode(string id, FormCollection queryStrings) { var menu = _menuItemCollectionFactory.Create(); if (id == Constants.System.RootString) { //Create the normal create action - menu.Items.Add(Services.TextService); + menu.Items.Add(LocalizedTextService); //refresh action - menu.Items.Add(new RefreshNode(Services.TextService, true)); + menu.Items.Add(new RefreshNode(LocalizedTextService, true)); return menu; } - var relationType = Services.RelationService.GetRelationTypeById(int.Parse(id)); + var relationType = _relationService.GetRelationTypeById(int.Parse(id)); if (relationType == null) return menu; if (relationType.IsSystemRelationType() == false) { - menu.Items.Add(Services.TextService); + menu.Items.Add(LocalizedTextService); } return menu; } - protected override TreeNodeCollection GetTreeNodes(string id, FormDataCollection queryStrings) + protected override TreeNodeCollection GetTreeNodes(string id, FormCollection queryStrings) { var nodes = new TreeNodeCollection(); if (id == Constants.System.RootString) { - nodes.AddRange(Services.RelationService.GetAllRelationTypes() + nodes.AddRange(_relationService.GetAllRelationTypes() .Select(rt => CreateTreeNode(rt.Id.ToString(), id, queryStrings, rt.Name, "icon-trafic", false))); } diff --git a/src/Umbraco.Web.BackOffice/Trees/ScriptsTreeController.cs b/src/Umbraco.Web.BackOffice/Trees/ScriptsTreeController.cs new file mode 100644 index 0000000000..8a3b8a1299 --- /dev/null +++ b/src/Umbraco.Web.BackOffice/Trees/ScriptsTreeController.cs @@ -0,0 +1,31 @@ +using Umbraco.Core; +using Umbraco.Core.IO; +using Umbraco.Core.Services; +using Umbraco.Web.BackOffice.Trees; +using Umbraco.Web.WebApi; + +namespace Umbraco.Web.Trees +{ + [CoreTree] + [Tree(Constants.Applications.Settings, Constants.Trees.Scripts, TreeTitle = "Scripts", SortOrder = 10, TreeGroup = Constants.Trees.Groups.Templating)] + public class ScriptsTreeController : FileSystemTreeController + { + protected override IFileSystem FileSystem { get; } + + private static readonly string[] ExtensionsStatic = { "js" }; + + protected override string[] Extensions => ExtensionsStatic; + + protected override string FileIcon => "icon-script"; + + public ScriptsTreeController( + ILocalizedTextService localizedTextService, + UmbracoApiControllerTypeCollection umbracoApiControllerTypeCollection, + IMenuItemCollectionFactory menuItemCollectionFactory, + IFileSystems fileSystems) + : base(localizedTextService, umbracoApiControllerTypeCollection, menuItemCollectionFactory) + { + FileSystem = fileSystems.ScriptsFileSystem; + } + } +} diff --git a/src/Umbraco.Web.BackOffice/Trees/StylesheetsTreeController.cs b/src/Umbraco.Web.BackOffice/Trees/StylesheetsTreeController.cs new file mode 100644 index 0000000000..4e88e60b4e --- /dev/null +++ b/src/Umbraco.Web.BackOffice/Trees/StylesheetsTreeController.cs @@ -0,0 +1,31 @@ +using Umbraco.Core; +using Umbraco.Core.IO; +using Umbraco.Core.Services; +using Umbraco.Web.BackOffice.Trees; +using Umbraco.Web.WebApi; + +namespace Umbraco.Web.Trees +{ + [CoreTree] + [Tree(Constants.Applications.Settings, Constants.Trees.Stylesheets, TreeTitle = "Stylesheets", SortOrder = 9, TreeGroup = Constants.Trees.Groups.Templating)] + public class StylesheetsTreeController : FileSystemTreeController + { + protected override IFileSystem FileSystem { get; } + + private static readonly string[] ExtensionsStatic = { "css" }; + + protected override string[] Extensions => ExtensionsStatic; + + protected override string FileIcon => "icon-brackets"; + + public StylesheetsTreeController( + ILocalizedTextService localizedTextService, + UmbracoApiControllerTypeCollection umbracoApiControllerTypeCollection, + IMenuItemCollectionFactory menuItemCollectionFactory, + IFileSystems fileSystems) + : base(localizedTextService, umbracoApiControllerTypeCollection, menuItemCollectionFactory) + { + FileSystem = fileSystems.StylesheetsFileSystem; + } + } +} diff --git a/src/Umbraco.Web/Trees/TemplatesTreeController.cs b/src/Umbraco.Web.BackOffice/Trees/TemplatesTreeController.cs similarity index 75% rename from src/Umbraco.Web/Trees/TemplatesTreeController.cs rename to src/Umbraco.Web.BackOffice/Trees/TemplatesTreeController.cs index 4745b4b172..fca6d7beb7 100644 --- a/src/Umbraco.Web/Trees/TemplatesTreeController.cs +++ b/src/Umbraco.Web.BackOffice/Trees/TemplatesTreeController.cs @@ -1,23 +1,20 @@ using System.Collections.Generic; using System.Globalization; using System.Linq; -using System.Net.Http.Formatting; +using Microsoft.AspNetCore.Http; using Umbraco.Core; -using Umbraco.Core.Cache; -using Umbraco.Core.Configuration; -using Umbraco.Core.Logging; -using Umbraco.Core.Mapping; using Umbraco.Core.Models; using Umbraco.Core.Models.Entities; -using Umbraco.Core.Persistence; using Umbraco.Core.Services; +using Umbraco.Extensions; using Umbraco.Web.Actions; +using Umbraco.Web.BackOffice.Filters; +using Umbraco.Web.BackOffice.Trees; +using Umbraco.Web.Common.Attributes; using Umbraco.Web.Models.ContentEditing; using Umbraco.Web.Models.Trees; -using Umbraco.Web.Mvc; -using Umbraco.Web.Routing; using Umbraco.Web.Search; -using Umbraco.Web.WebApi.Filters; +using Umbraco.Web.WebApi; using Constants = Umbraco.Core.Constants; namespace Umbraco.Web.Trees @@ -30,30 +27,26 @@ namespace Umbraco.Web.Trees { private readonly UmbracoTreeSearcher _treeSearcher; private readonly IMenuItemCollectionFactory _menuItemCollectionFactory; + private readonly IFileService _fileService; public TemplatesTreeController( UmbracoTreeSearcher treeSearcher, - IGlobalSettings globalSettings, - IUmbracoContextAccessor umbracoContextAccessor, - ISqlContext sqlContext, - ServiceContext services, - AppCaches appCaches, - IProfilingLogger logger, - IRuntimeState runtimeState, - UmbracoMapper umbracoMapper, - IPublishedUrlProvider publishedUrlProvider, - IMenuItemCollectionFactory menuItemCollectionFactory) - : base(globalSettings, umbracoContextAccessor, sqlContext, services, appCaches, logger, runtimeState, umbracoMapper, publishedUrlProvider) + IMenuItemCollectionFactory menuItemCollectionFactory, + ILocalizedTextService localizedTextService, + UmbracoApiControllerTypeCollection umbracoApiControllerTypeCollection, + IFileService fileService + ) : base(localizedTextService, umbracoApiControllerTypeCollection) { _treeSearcher = treeSearcher; _menuItemCollectionFactory = menuItemCollectionFactory; + _fileService = fileService; } - protected override TreeNode CreateRootNode(FormDataCollection queryStrings) + protected override TreeNode CreateRootNode(FormCollection queryStrings) { var root = base.CreateRootNode(queryStrings); //check if there are any templates - root.HasChildren = Services.FileService.GetTemplates(-1).Any(); + root.HasChildren = _fileService.GetTemplates(-1).Any(); return root; } @@ -68,13 +61,13 @@ namespace Umbraco.Web.Trees /// We are allowing an arbitrary number of query strings to be pased in so that developers are able to persist custom data from the front-end /// to the back end to be used in the query for model data. /// - protected override TreeNodeCollection GetTreeNodes(string id, FormDataCollection queryStrings) + protected override TreeNodeCollection GetTreeNodes(string id, FormCollection queryStrings) { var nodes = new TreeNodeCollection(); var found = id == Constants.System.RootString - ? Services.FileService.GetTemplates(-1) - : Services.FileService.GetTemplates(int.Parse(id)); + ? _fileService.GetTemplates(-1) + : _fileService.GetTemplates(int.Parse(id)); nodes.AddRange(found.Select(template => CreateTreeNode( template.Id.ToString(CultureInfo.InvariantCulture), @@ -97,23 +90,23 @@ namespace Umbraco.Web.Trees /// /// /// - protected override MenuItemCollection GetMenuForNode(string id, FormDataCollection queryStrings) + protected override MenuItemCollection GetMenuForNode(string id, FormCollection queryStrings) { var menu = _menuItemCollectionFactory.Create(); //Create the normal create action - var item = menu.Items.Add(Services.TextService, opensDialog: true); + var item = menu.Items.Add(LocalizedTextService, opensDialog: true); item.NavigateToRoute($"{queryStrings.GetRequiredValue("application")}/templates/edit/{id}?create=true"); if (id == Constants.System.RootString) { //refresh action - menu.Items.Add(new RefreshNode(Services.TextService, true)); + menu.Items.Add(new RefreshNode(LocalizedTextService, true)); return menu; } - var template = Services.FileService.GetTemplate(int.Parse(id)); + var template = _fileService.GetTemplate(int.Parse(id)); if (template == null) return menu; var entity = FromTemplate(template); @@ -121,11 +114,11 @@ namespace Umbraco.Web.Trees if (template.IsMasterTemplate == false) { //add delete option if it doesn't have children - menu.Items.Add(Services.TextService, true, opensDialog: true); + menu.Items.Add(LocalizedTextService, true, opensDialog: true); } //add refresh - menu.Items.Add(new RefreshNode(Services.TextService, true)); + menu.Items.Add(new RefreshNode(LocalizedTextService, true)); return menu; diff --git a/src/Umbraco.Web.BackOffice/Trees/TreeController.cs b/src/Umbraco.Web.BackOffice/Trees/TreeController.cs index 9a342f5519..1132b9bd5f 100644 --- a/src/Umbraco.Web.BackOffice/Trees/TreeController.cs +++ b/src/Umbraco.Web.BackOffice/Trees/TreeController.cs @@ -1,6 +1,5 @@ using System; using System.Collections.Concurrent; -using Microsoft.Extensions.DependencyInjection; using Umbraco.Core; using Umbraco.Core.Services; using Umbraco.Web.Trees; @@ -17,17 +16,17 @@ namespace Umbraco.Web.BackOffice.Trees private readonly TreeAttribute _treeAttribute; - private readonly ILocalizedTextService _textService; + protected ILocalizedTextService LocalizedTextService { get; } - protected TreeController(ILocalizedTextService textService, UmbracoApiControllerTypeCollection umbracoApiControllerTypeCollection) + protected TreeController(ILocalizedTextService localizedTextService, UmbracoApiControllerTypeCollection umbracoApiControllerTypeCollection) : base(umbracoApiControllerTypeCollection) { - _textService = textService ?? throw new ArgumentNullException(nameof(textService)); + LocalizedTextService = localizedTextService ?? throw new ArgumentNullException(nameof(localizedTextService)); _treeAttribute = GetTreeAttribute(); } /// - public override string RootNodeDisplayName => Tree.GetRootNodeDisplayName(this, _textService); + public override string RootNodeDisplayName => Tree.GetRootNodeDisplayName(this, LocalizedTextService); /// public override string TreeGroup => _treeAttribute.TreeGroup; diff --git a/src/Umbraco.Web/Trees/UserTreeController.cs b/src/Umbraco.Web.BackOffice/Trees/UserTreeController.cs similarity index 69% rename from src/Umbraco.Web/Trees/UserTreeController.cs rename to src/Umbraco.Web.BackOffice/Trees/UserTreeController.cs index 4d97be511d..de7cb6c33c 100644 --- a/src/Umbraco.Web/Trees/UserTreeController.cs +++ b/src/Umbraco.Web.BackOffice/Trees/UserTreeController.cs @@ -1,4 +1,4 @@ -using System.Net.Http.Formatting; +using Microsoft.AspNetCore.Http; using Umbraco.Core; using Umbraco.Core.Cache; using Umbraco.Core.Configuration; @@ -6,10 +6,12 @@ using Umbraco.Core.Logging; using Umbraco.Core.Mapping; using Umbraco.Core.Persistence; using Umbraco.Core.Services; +using Umbraco.Web.BackOffice.Filters; +using Umbraco.Web.BackOffice.Trees; +using Umbraco.Web.Common.Attributes; using Umbraco.Web.Models.Trees; -using Umbraco.Web.Mvc; using Umbraco.Web.Routing; -using Umbraco.Web.WebApi.Filters; +using Umbraco.Web.WebApi; using Constants = Umbraco.Core.Constants; namespace Umbraco.Web.Trees @@ -23,17 +25,10 @@ namespace Umbraco.Web.Trees private readonly IMenuItemCollectionFactory _menuItemCollectionFactory; public UserTreeController( - IGlobalSettings globalSettings, - IUmbracoContextAccessor umbracoContextAccessor, - ISqlContext sqlContext, - ServiceContext services, - AppCaches appCaches, - IProfilingLogger logger, - IRuntimeState runtimeState, - UmbracoMapper umbracoMapper, - IPublishedUrlProvider publishedUrlProvider, - IMenuItemCollectionFactory menuItemCollectionFactory) - : base(globalSettings, umbracoContextAccessor, sqlContext, services, appCaches, logger, runtimeState, umbracoMapper, publishedUrlProvider) + IMenuItemCollectionFactory menuItemCollectionFactory, + ILocalizedTextService localizedTextService, + UmbracoApiControllerTypeCollection umbracoApiControllerTypeCollection + ) : base(localizedTextService, umbracoApiControllerTypeCollection) { _menuItemCollectionFactory = menuItemCollectionFactory; } @@ -42,7 +37,7 @@ namespace Umbraco.Web.Trees /// Helper method to create a root model for a tree /// /// - protected override TreeNode CreateRootNode(FormDataCollection queryStrings) + protected override TreeNode CreateRootNode(FormCollection queryStrings) { var root = base.CreateRootNode(queryStrings); @@ -54,13 +49,13 @@ namespace Umbraco.Web.Trees return root; } - protected override TreeNodeCollection GetTreeNodes(string id, FormDataCollection queryStrings) + protected override TreeNodeCollection GetTreeNodes(string id, FormCollection queryStrings) { //full screen app without tree nodes return TreeNodeCollection.Empty; } - protected override MenuItemCollection GetMenuForNode(string id, FormDataCollection queryStrings) + protected override MenuItemCollection GetMenuForNode(string id, FormCollection queryStrings) { //doesn't have a menu, this is a full screen app without tree nodes return _menuItemCollectionFactory.Create(); diff --git a/src/Umbraco.Web.Common/Extensions/LinkGeneratorExtensions.cs b/src/Umbraco.Web.Common/Extensions/LinkGeneratorExtensions.cs index 5d51305ea1..0ce314c6d3 100644 --- a/src/Umbraco.Web.Common/Extensions/LinkGeneratorExtensions.cs +++ b/src/Umbraco.Web.Common/Extensions/LinkGeneratorExtensions.cs @@ -1,4 +1,5 @@ using System; +using System.Linq; using Umbraco.Core; using Microsoft.AspNetCore.Routing; using System.Reflection; @@ -58,22 +59,7 @@ namespace Umbraco.Extensions return linkGenerator.GetUmbracoApiService(actionName, typeof(T), id); } - public static string GetUmbracoApiService(this LinkGenerator url, Expression> methodSelector) - where T : UmbracoApiControllerBase - { - var method = ExpressionHelper.GetMethodInfo(methodSelector); - var methodParams = ExpressionHelper.GetMethodParams(methodSelector); - if (method == null) - { - throw new MissingMethodException("Could not find the method " + methodSelector + " on type " + typeof(T) + " or the result "); - } - if (methodParams.Any() == false) - { - return url.GetUmbracoApiService(method.Name); - } - return url.GetUmbracoApiService(method.Name, methodParams.Values.First()); - } public static string GetUmbracoApiServiceBaseUrl(this LinkGenerator linkGenerator, Expression> methodSelector) where T : UmbracoApiControllerBase @@ -153,5 +139,23 @@ namespace Umbraco.Extensions } return linkGenerator.GetUmbracoApiService(actionName, ControllerExtensions.GetControllerName(apiControllerType), area, id); } + + public static string GetUmbracoApiService(this LinkGenerator linkGenerator, Expression> methodSelector) + where T : UmbracoApiController + { + var method = ExpressionHelper.GetMethodInfo(methodSelector); + var methodParams = ExpressionHelper.GetMethodParams(methodSelector); + if (method == null) + { + throw new MissingMethodException( + $"Could not find the method {methodSelector} on type {typeof(T)} or the result "); + } + + if (methodParams.Any() == false) + { + return linkGenerator.GetUmbracoApiService(method.Name); + } + return linkGenerator.GetUmbracoApiService(method.Name, methodParams.Values.First()); + } } } diff --git a/src/Umbraco.Web.Common/Runtime/AspNetCoreComposer.cs b/src/Umbraco.Web.Common/Runtime/AspNetCoreComposer.cs index b16763f139..7a1d907520 100644 --- a/src/Umbraco.Web.Common/Runtime/AspNetCoreComposer.cs +++ b/src/Umbraco.Web.Common/Runtime/AspNetCoreComposer.cs @@ -22,6 +22,7 @@ using Umbraco.Web.Common.Middleware; using Umbraco.Web.Common.ModelBinding; using Umbraco.Web.Common.Routing; using Umbraco.Web.Common.Templates; +using Umbraco.Web.Common.Security; using Umbraco.Web.Security; using Umbraco.Web.Templates; @@ -72,7 +73,7 @@ namespace Umbraco.Web.Common.Runtime // register the umbraco context factory composition.RegisterUnique(); - composition.RegisterUnique(factory => factory.GetInstance().GetRequiredUmbracoContext().Security); + composition.RegisterUnique(); //register the install components //NOTE: i tried to not have these registered if we weren't installing or upgrading but post install when the site restarts diff --git a/src/Umbraco.Web.Common/UmbracoContext/UmbracoContextFactory.cs b/src/Umbraco.Web.Common/UmbracoContext/UmbracoContextFactory.cs index 7fde583523..3c771a1668 100644 --- a/src/Umbraco.Web.Common/UmbracoContext/UmbracoContextFactory.cs +++ b/src/Umbraco.Web.Common/UmbracoContext/UmbracoContextFactory.cs @@ -28,6 +28,7 @@ namespace Umbraco.Web private readonly IHttpContextAccessor _httpContextAccessor; private readonly ICookieManager _cookieManager; private readonly IRequestAccessor _requestAccessor; + private readonly IWebSecurity _webSecurity; private readonly UriUtility _uriUtility; /// @@ -44,7 +45,8 @@ namespace Umbraco.Web UriUtility uriUtility, IHttpContextAccessor httpContextAccessor, ICookieManager cookieManager, - IRequestAccessor requestAccessor) + IRequestAccessor requestAccessor, + IWebSecurity webSecurity) { _umbracoContextAccessor = umbracoContextAccessor ?? throw new ArgumentNullException(nameof(umbracoContextAccessor)); _publishedSnapshotService = publishedSnapshotService ?? throw new ArgumentNullException(nameof(publishedSnapshotService)); @@ -57,6 +59,7 @@ namespace Umbraco.Web _httpContextAccessor = httpContextAccessor ?? throw new ArgumentNullException(nameof(httpContextAccessor)); _cookieManager = cookieManager ?? throw new ArgumentNullException(nameof(cookieManager)); _requestAccessor = requestAccessor ?? throw new ArgumentNullException(nameof(requestAccessor)); + _webSecurity = webSecurity ?? throw new ArgumentNullException(nameof(webSecurity)); } private IUmbracoContext CreateUmbracoContext() @@ -72,11 +75,9 @@ namespace Umbraco.Web _variationContextAccessor.VariationContext = new VariationContext(_defaultCultureAccessor.DefaultCulture); } - IWebSecurity webSecurity = new WebSecurity(_userService, _globalSettings, _hostingEnvironment, _httpContextAccessor); - return new UmbracoContext( _publishedSnapshotService, - webSecurity, + _webSecurity, _globalSettings, _hostingEnvironment, _variationContextAccessor, diff --git a/src/Umbraco.Web/Composing/CompositionExtensions/WebMappingProfiles.cs b/src/Umbraco.Web/Composing/CompositionExtensions/WebMappingProfiles.cs index 8ef601a290..c1520f367c 100644 --- a/src/Umbraco.Web/Composing/CompositionExtensions/WebMappingProfiles.cs +++ b/src/Umbraco.Web/Composing/CompositionExtensions/WebMappingProfiles.cs @@ -14,25 +14,10 @@ namespace Umbraco.Web.Composing.CompositionExtensions // definitions to be moved to core composition.WithCollectionBuilder() - .Add() - .Add() .Add() - .Add() - .Add() - .Add() - .Add() - .Add() - .Add() .Add() .Add() - .Add() - .Add() - .Add() - .Add() - .Add() - .Add() - .Add() - .Add(); + ; composition.Register(); composition.Register(); diff --git a/src/Umbraco.Web/Editors/BackOfficeServerVariables.cs b/src/Umbraco.Web/Editors/BackOfficeServerVariables.cs index d25d9528ad..9799c18651 100644 --- a/src/Umbraco.Web/Editors/BackOfficeServerVariables.cs +++ b/src/Umbraco.Web/Editors/BackOfficeServerVariables.cs @@ -239,18 +239,18 @@ namespace Umbraco.Web.Editors // "templateApiBaseUrl", _urlHelper.GetUmbracoApiServiceBaseUrl( // controller => controller.GetById(0)) // }, - { - "memberTreeBaseUrl", _urlHelper.GetUmbracoApiServiceBaseUrl( - controller => controller.GetNodes("-1", null)) - }, - { - "mediaTreeBaseUrl", _urlHelper.GetUmbracoApiServiceBaseUrl( - controller => controller.GetNodes("-1", null)) - }, - { - "contentTreeBaseUrl", _urlHelper.GetUmbracoApiServiceBaseUrl( - controller => controller.GetNodes("-1", null)) - }, + // { + // "memberTreeBaseUrl", _urlHelper.GetUmbracoApiServiceBaseUrl( + // controller => controller.GetNodes("-1", null)) + // }, + // { + // "mediaTreeBaseUrl", _urlHelper.GetUmbracoApiServiceBaseUrl( + // controller => controller.GetNodes("-1", null)) + // }, + // { + // "contentTreeBaseUrl", _urlHelper.GetUmbracoApiServiceBaseUrl( + // controller => controller.GetNodes("-1", null)) + // }, // { // "tagsDataBaseUrl", _urlHelper.GetUmbracoApiServiceBaseUrl( // controller => controller.GetTags("", "", null)) diff --git a/src/Umbraco.Web/Models/Mapping/CommonTreeNodeMapper.cs b/src/Umbraco.Web/Models/Mapping/CommonTreeNodeMapper.cs index aed779683f..dedf1b3664 100644 --- a/src/Umbraco.Web/Models/Mapping/CommonTreeNodeMapper.cs +++ b/src/Umbraco.Web/Models/Mapping/CommonTreeNodeMapper.cs @@ -2,7 +2,7 @@ using Umbraco.Core.Models; using Umbraco.Web.Trees; using Umbraco.Web.WebApi; - +//Migrated to .NET CORE namespace Umbraco.Web.Models.Mapping { public class CommonTreeNodeMapper diff --git a/src/Umbraco.Web/Models/Mapping/ContentMapDefinition.cs b/src/Umbraco.Web/Models/Mapping/ContentMapDefinition.cs index aa3730f54f..ec7fd4ae59 100644 --- a/src/Umbraco.Web/Models/Mapping/ContentMapDefinition.cs +++ b/src/Umbraco.Web/Models/Mapping/ContentMapDefinition.cs @@ -13,6 +13,7 @@ using Umbraco.Web.Models.ContentEditing; using Umbraco.Web.Routing; using Umbraco.Web.Trees; +//Migrated to .NET CORE namespace Umbraco.Web.Models.Mapping { /// @@ -83,7 +84,7 @@ namespace Umbraco.Web.Models.Mapping target.Properties = context.MapEnumerable(source.Properties); } - // Umbraco.Code.MapAll -AllowPreview -Errors -PersistedContent + // Umbraco.Code.MapAll -AllowPreview -Errors -PersistedContent -TreeNodeUrl private void Map(IContent source, ContentItemDisplay target, MapperContext context) { target.AllowedActions = GetActions(source); @@ -107,7 +108,7 @@ namespace Umbraco.Web.Models.Mapping target.TemplateAlias = GetDefaultTemplate(source); target.TemplateId = source.TemplateId ?? default; target.Trashed = source.Trashed; - target.TreeNodeUrl = _commonTreeNodeMapper.GetTreeNodeUrl(source); + // target.TreeNodeUrl = _commonTreeNodeMapper.GetTreeNodeUrl(source); target.Udi = Udi.Create(source.Blueprint ? Constants.UdiEntityType.DocumentBlueprint : Constants.UdiEntityType.Document, source.Key); target.UpdateDate = source.UpdateDate; target.Updater = _commonMapper.GetCreator(source, context); diff --git a/src/Umbraco.Web/Models/Mapping/MediaMapDefinition.cs b/src/Umbraco.Web/Models/Mapping/MediaMapDefinition.cs index 0a7bdb0026..b39c2f7f30 100644 --- a/src/Umbraco.Web/Models/Mapping/MediaMapDefinition.cs +++ b/src/Umbraco.Web/Models/Mapping/MediaMapDefinition.cs @@ -9,7 +9,7 @@ using Umbraco.Web.Models.ContentEditing; using Umbraco.Web.Trees; using Umbraco.Core.Configuration.UmbracoSettings; using System; - +//Migrated to .NET CORE namespace Umbraco.Web.Models.Mapping { /// @@ -51,7 +51,7 @@ namespace Umbraco.Web.Models.Mapping target.Properties = context.MapEnumerable(source.Properties); } - // Umbraco.Code.MapAll -Properties -Errors -Edited -Updater -Alias -IsContainer + // Umbraco.Code.MapAll -Properties -Errors -Edited -Updater -Alias -IsContainer -TreeNodeUrl private void Map(IMedia source, MediaItemDisplay target, MapperContext context) { target.ContentApps = _commonMapper.GetContentApps(source); @@ -73,7 +73,7 @@ namespace Umbraco.Web.Models.Mapping target.State = null; target.Tabs = _tabsAndPropertiesMapper.Map(source, context); target.Trashed = source.Trashed; - target.TreeNodeUrl = _commonTreeNodeMapper.GetTreeNodeUrl(source); + //target.TreeNodeUrl = _commonTreeNodeMapper.GetTreeNodeUrl(source); target.Udi = Udi.Create(Constants.UdiEntityType.Media, source.Key); target.UpdateDate = source.UpdateDate; target.VariesByCulture = source.ContentType.VariesByCulture(); diff --git a/src/Umbraco.Web/Models/Mapping/MemberMapDefinition.cs b/src/Umbraco.Web/Models/Mapping/MemberMapDefinition.cs index 5fc443f692..02bea9479c 100644 --- a/src/Umbraco.Web/Models/Mapping/MemberMapDefinition.cs +++ b/src/Umbraco.Web/Models/Mapping/MemberMapDefinition.cs @@ -3,7 +3,7 @@ using Umbraco.Core.Mapping; using Umbraco.Core.Models; using Umbraco.Web.Models.ContentEditing; using Umbraco.Web.Trees; - +//Migrated to .NET CORE namespace Umbraco.Web.Models.Mapping { /// @@ -34,7 +34,7 @@ namespace Umbraco.Web.Models.Mapping } // Umbraco.Code.MapAll -Properties -Errors -Edited -Updater -Alias -IsChildOfListView - // Umbraco.Code.MapAll -Trashed -IsContainer -VariesByCulture + // Umbraco.Code.MapAll -Trashed -IsContainer -VariesByCulture -TreeNodeUrl private void Map(IMember source, MemberDisplay target, MapperContext context) { target.ContentApps = _commonMapper.GetContentApps(source); @@ -53,7 +53,7 @@ namespace Umbraco.Web.Models.Mapping target.SortOrder = source.SortOrder; target.State = null; target.Tabs = _tabsAndPropertiesMapper.Map(source, context); - target.TreeNodeUrl = _commonTreeNodeMapper.GetTreeNodeUrl(source); + //target.TreeNodeUrl = _commonTreeNodeMapper.GetTreeNodeUrl(source); target.Udi = Udi.Create(Constants.UdiEntityType.Member, source.Key); target.UpdateDate = source.UpdateDate; target.Username = source.Username; diff --git a/src/Umbraco.Web/Trees/FilesTreeController.cs b/src/Umbraco.Web/Trees/FilesTreeController.cs deleted file mode 100644 index 56ff8fa007..0000000000 --- a/src/Umbraco.Web/Trees/FilesTreeController.cs +++ /dev/null @@ -1,27 +0,0 @@ -using Umbraco.Core; -using Umbraco.Core.Hosting; -using Umbraco.Core.IO; -using Umbraco.Core.Logging; - -namespace Umbraco.Web.Trees -{ - [Tree(Constants.Applications.Settings, "files", TreeTitle = "Files", TreeUse = TreeUse.Dialog)] - [CoreTree] - public class FilesTreeController : FileSystemTreeController - { - private readonly IFileSystem _fileSystem; - - protected override IFileSystem FileSystem => _fileSystem; - - private static readonly string[] ExtensionsStatic = { "*" }; - - public FilesTreeController(IIOHelper ioHelper, IHostingEnvironment hostingEnvironment, ILogger logger) - { - _fileSystem = new PhysicalFileSystem(ioHelper, hostingEnvironment, logger, "~/"); - } - - protected override string[] Extensions => ExtensionsStatic; - - protected override string FileIcon => Constants.Icons.MediaFile; - } -} diff --git a/src/Umbraco.Web/Trees/ITreeNodeController.cs b/src/Umbraco.Web/Trees/ITreeNodeController.cs index a8c22f38bd..8def2f19c4 100644 --- a/src/Umbraco.Web/Trees/ITreeNodeController.cs +++ b/src/Umbraco.Web/Trees/ITreeNodeController.cs @@ -3,6 +3,7 @@ using Umbraco.Web.Models.Trees; using Umbraco.Web.WebApi.Filters; using System.Web.Http.ModelBinding; +//Migrated to .NET CORE namespace Umbraco.Web.Trees { /// diff --git a/src/Umbraco.Web/Trees/MemberGroupTreeController.cs b/src/Umbraco.Web/Trees/MemberGroupTreeController.cs deleted file mode 100644 index 54c499d717..0000000000 --- a/src/Umbraco.Web/Trees/MemberGroupTreeController.cs +++ /dev/null @@ -1,31 +0,0 @@ -using System.Collections.Generic; -using System.Linq; -using System.Net.Http.Formatting; -using Umbraco.Core; -using Umbraco.Web.Models.Trees; -using Umbraco.Web.WebApi.Filters; - -namespace Umbraco.Web.Trees -{ - [UmbracoTreeAuthorize(Constants.Trees.MemberGroups)] - [Tree(Constants.Applications.Members, Constants.Trees.MemberGroups, SortOrder = 1)] - [Mvc.PluginController("UmbracoTrees")] - [CoreTree] - public class MemberGroupTreeController : MemberTypeAndGroupTreeControllerBase - { - protected override IEnumerable GetTreeNodesFromService(string id, FormDataCollection queryStrings) - { - return Services.MemberGroupService.GetAll() - .OrderBy(x => x.Name) - .Select(dt => CreateTreeNode(dt.Id.ToString(), id, queryStrings, dt.Name, Constants.Icons.MemberGroup, false)); - } - - protected override TreeNode CreateRootNode(FormDataCollection queryStrings) - { - var root = base.CreateRootNode(queryStrings); - //check if there are any groups - root.HasChildren = Services.MemberGroupService.GetAll().Any(); - return root; - } - } -} diff --git a/src/Umbraco.Web/Trees/MenuRenderingEventArgs.cs b/src/Umbraco.Web/Trees/MenuRenderingEventArgs.cs index bb7c43dcdb..3b1a632696 100644 --- a/src/Umbraco.Web/Trees/MenuRenderingEventArgs.cs +++ b/src/Umbraco.Web/Trees/MenuRenderingEventArgs.cs @@ -1,4 +1,4 @@ -using System.Net.Http.Formatting; +using System.Net.Http.Formatting; using Umbraco.Web.Models.Trees; namespace Umbraco.Web.Trees diff --git a/src/Umbraco.Web/Trees/ScriptsTreeController.cs b/src/Umbraco.Web/Trees/ScriptsTreeController.cs deleted file mode 100644 index 7c00d085b7..0000000000 --- a/src/Umbraco.Web/Trees/ScriptsTreeController.cs +++ /dev/null @@ -1,20 +0,0 @@ -using Umbraco.Core; -using Umbraco.Core.IO; -using Umbraco.Web.Composing; -using Umbraco.Web.Models.Trees; - -namespace Umbraco.Web.Trees -{ - [CoreTree] - [Tree(Constants.Applications.Settings, Constants.Trees.Scripts, TreeTitle = "Scripts", SortOrder = 10, TreeGroup = Constants.Trees.Groups.Templating)] - public class ScriptsTreeController : FileSystemTreeController - { - protected override IFileSystem FileSystem => Current.FileSystems.ScriptsFileSystem; // TODO: inject - - private static readonly string[] ExtensionsStatic = { "js" }; - - protected override string[] Extensions => ExtensionsStatic; - - protected override string FileIcon => "icon-script"; - } -} diff --git a/src/Umbraco.Web/Trees/StylesheetsTreeController.cs b/src/Umbraco.Web/Trees/StylesheetsTreeController.cs deleted file mode 100644 index f96a83018d..0000000000 --- a/src/Umbraco.Web/Trees/StylesheetsTreeController.cs +++ /dev/null @@ -1,19 +0,0 @@ -using Umbraco.Core; -using Umbraco.Core.IO; -using Umbraco.Web.Composing; - -namespace Umbraco.Web.Trees -{ - [CoreTree] - [Tree(Constants.Applications.Settings, Constants.Trees.Stylesheets, TreeTitle = "Stylesheets", SortOrder = 9, TreeGroup = Constants.Trees.Groups.Templating)] - public class StylesheetsTreeController : FileSystemTreeController - { - protected override IFileSystem FileSystem => Current.FileSystems.StylesheetsFileSystem; // TODO: inject - - private static readonly string[] ExtensionsStatic = { "css" }; - - protected override string[] Extensions => ExtensionsStatic; - - protected override string FileIcon => "icon-brackets"; - } -} diff --git a/src/Umbraco.Web/Trees/TreeAttribute.cs b/src/Umbraco.Web/Trees/TreeAttribute.cs index 1170de5cfa..2fe8b53a56 100644 --- a/src/Umbraco.Web/Trees/TreeAttribute.cs +++ b/src/Umbraco.Web/Trees/TreeAttribute.cs @@ -1,4 +1,4 @@ -using System; +using System; namespace Umbraco.Web.Trees { @@ -42,7 +42,7 @@ namespace Umbraco.Web.Trees /// Gets the usage of the tree. /// public TreeUse TreeUse { get; set; } = TreeUse.Main | TreeUse.Dialog; - + /// /// Gets or sets the tree sort order. /// diff --git a/src/Umbraco.Web/Trees/TreeController.cs b/src/Umbraco.Web/Trees/TreeController.cs index 730fd04bf2..0858956c2b 100644 --- a/src/Umbraco.Web/Trees/TreeController.cs +++ b/src/Umbraco.Web/Trees/TreeController.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Collections.Concurrent; using Umbraco.Core; using Umbraco.Core.Cache; diff --git a/src/Umbraco.Web/Trees/TreeControllerBase.cs b/src/Umbraco.Web/Trees/TreeControllerBase.cs index 18cb25c912..d4d4612f59 100644 --- a/src/Umbraco.Web/Trees/TreeControllerBase.cs +++ b/src/Umbraco.Web/Trees/TreeControllerBase.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Globalization; using System.Linq; using System.Net.Http.Formatting; diff --git a/src/Umbraco.Web/Trees/TreeNodeRenderingEventArgs.cs b/src/Umbraco.Web/Trees/TreeNodeRenderingEventArgs.cs index 1914d427e9..795694c675 100644 --- a/src/Umbraco.Web/Trees/TreeNodeRenderingEventArgs.cs +++ b/src/Umbraco.Web/Trees/TreeNodeRenderingEventArgs.cs @@ -1,4 +1,4 @@ -using System.Net.Http.Formatting; +using System.Net.Http.Formatting; using Umbraco.Web.Models.Trees; namespace Umbraco.Web.Trees diff --git a/src/Umbraco.Web/Trees/TreeNodesRenderingEventArgs.cs b/src/Umbraco.Web/Trees/TreeNodesRenderingEventArgs.cs index 753e727b05..bdd723b5de 100644 --- a/src/Umbraco.Web/Trees/TreeNodesRenderingEventArgs.cs +++ b/src/Umbraco.Web/Trees/TreeNodesRenderingEventArgs.cs @@ -1,4 +1,4 @@ -using System.Net.Http.Formatting; +using System.Net.Http.Formatting; using Umbraco.Web.Models.Trees; namespace Umbraco.Web.Trees diff --git a/src/Umbraco.Web/Trees/TreeQueryStringParameters.cs b/src/Umbraco.Web/Trees/TreeQueryStringParameters.cs index 130f4c2486..9e95c74541 100644 --- a/src/Umbraco.Web/Trees/TreeQueryStringParameters.cs +++ b/src/Umbraco.Web/Trees/TreeQueryStringParameters.cs @@ -1,4 +1,4 @@ -namespace Umbraco.Web.Trees +namespace Umbraco.Web.Trees { /// /// Common query string parameters used for tree query strings diff --git a/src/Umbraco.Web/Trees/TreeRenderingEventArgs.cs b/src/Umbraco.Web/Trees/TreeRenderingEventArgs.cs index 3f26c8cf50..d93c74e583 100644 --- a/src/Umbraco.Web/Trees/TreeRenderingEventArgs.cs +++ b/src/Umbraco.Web/Trees/TreeRenderingEventArgs.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Net.Http.Formatting; namespace Umbraco.Web.Trees diff --git a/src/Umbraco.Web/Trees/UrlHelperExtensions.cs b/src/Umbraco.Web/Trees/UrlHelperExtensions.cs index 52f7668aef..cf725e98ce 100644 --- a/src/Umbraco.Web/Trees/UrlHelperExtensions.cs +++ b/src/Umbraco.Web/Trees/UrlHelperExtensions.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Linq; using System.Net.Http.Formatting; using System.Text; diff --git a/src/Umbraco.Web/Umbraco.Web.csproj b/src/Umbraco.Web/Umbraco.Web.csproj index d1b833b21f..e582cff00d 100755 --- a/src/Umbraco.Web/Umbraco.Web.csproj +++ b/src/Umbraco.Web/Umbraco.Web.csproj @@ -145,14 +145,20 @@ + + + + + + @@ -168,10 +174,6 @@ - - - - @@ -199,7 +201,6 @@ - @@ -216,12 +217,10 @@ - - @@ -240,7 +239,6 @@ - @@ -256,15 +254,6 @@ - - - - - - - - - @@ -294,10 +283,6 @@ - - - - @@ -331,11 +316,7 @@ - - - - @@ -363,8 +344,6 @@ - - @@ -373,7 +352,6 @@ - @@ -433,8 +411,6 @@ - -