From 355ac09d90f435f96a217c32ce9dbe93852a85bb Mon Sep 17 00:00:00 2001 From: Shannon Date: Thu, 17 Jan 2019 13:20:19 +1100 Subject: [PATCH 01/11] WIP - moved out the tree and section service from Core, these are web only things, removes their xml parsing, fixes base controller ctor params with UmbracoContext, need to implement tree/section collections taking into account controllers and not scanning so much --- .../Composing/Composers/ServicesComposer.cs | 4 - src/Umbraco.Core/Models/ApplicationTree.cs | 170 ---- src/Umbraco.Core/Models/Section.cs | 22 - src/Umbraco.Core/Services/ISectionService.cs | 114 --- src/Umbraco.Core/Services/ServiceContext.cs | 20 +- src/Umbraco.Core/Umbraco.Core.csproj | 4 - .../Cache/DistributedCacheBinderTests.cs | 7 - .../Packages/Document_Type_Picker_1.1.zip | Bin 0 -> 6147 bytes .../Services/SectionServiceTests.cs | 17 +- .../TestControllerActivatorBase.cs | 3 +- .../TestHelpers/TestObjects-Mocks.cs | 2 - src/Umbraco.Tests/TestHelpers/TestObjects.cs | 6 +- .../TreesAndSections/ApplicationTreeTest.cs | 724 ++++++++--------- .../TreesAndSections/SectionTests.cs | 454 +++++------ .../Cache/ApplicationTreeCacheRefresher.cs | 68 +- .../Cache/DistributedCacheBinder_Handlers.cs | 72 +- .../Cache/DistributedCacheExtensions.cs | 24 +- .../{ => Controllers}/TagsController.cs | 6 +- .../Editors/AuthenticationController.cs | 4 +- .../Editors/BackOfficeServerVariables.cs | 4 +- .../Editors/ContentTypeController.cs | 4 +- .../Editors/ContentTypeControllerBase.cs | 3 +- .../Editors/DashboardController.cs | 4 +- src/Umbraco.Web/Editors/DashboardSecurity.cs | 1 + src/Umbraco.Web/Editors/Dashboards.cs | 1 + src/Umbraco.Web/Editors/EntityController.cs | 16 +- .../Editors/MediaTypeController.cs | 3 +- .../Editors/MemberTypeController.cs | 3 +- .../Editors/PackageInstallController.cs | 4 +- src/Umbraco.Web/Editors/SectionController.cs | 30 +- .../UmbracoAuthorizedJsonController.cs | 4 +- .../Models/ContentEditing/ApplicationTree.cs | 177 +++++ .../ContentEditing/IBackOfficeSection.cs | 15 + .../Models/Mapping/SectionMapperProfile.cs | 3 +- .../Models/Mapping/UserMapperProfile.cs | 1 + .../Models/Trees/ApplicationAttribute.cs | 30 - .../Models/Trees/ApplicationDefinitions.cs | 90 ++- src/Umbraco.Web/Models/Trees/IApplication.cs | 10 - .../Mvc/SurfaceControllerTypeCollection.cs | 2 + .../Runtime/WebRuntimeComponent.cs | 2 + src/Umbraco.Web/Runtime/WebRuntimeComposer.cs | 11 + .../Search/SearchableTreeCollection.cs | 1 + .../Services/ApplicationTreeService.cs | 747 +++++++++--------- .../Services/IApplicationTreeService.cs | 121 +-- src/Umbraco.Web/Services/ISectionService.cs | 116 +++ src/Umbraco.Web/Services/SectionService.cs | 443 +++++------ .../Trees/ApplicationTreeController.cs | 33 +- .../Trees/BackOfficeSectionCollection.cs | 21 + src/Umbraco.Web/Trees/TreeCollection.cs | 27 + src/Umbraco.Web/Trees/TreeController.cs | 34 +- src/Umbraco.Web/Trees/TreeControllerBase.cs | 98 +-- ...xtensions.cs => TreeControllerResolver.cs} | 106 ++- .../UI/Pages/UmbracoEnsuredPage.cs | 14 +- src/Umbraco.Web/Umbraco.Web.csproj | 13 +- src/Umbraco.Web/UrlHelperExtensions.cs | 1 - .../Filters/LegacyTreeAuthorizeAttribute.cs | 29 - .../Filters/UmbracoTreeAuthorizeAttribute.cs | 23 +- .../WebApi/UmbracoApiController.cs | 4 +- .../WebApi/UmbracoApiControllerBase.cs | 11 +- .../UmbracoApiControllerTypeCollection.cs | 2 + .../WebApi/UmbracoAuthorizedApiController.cs | 4 +- .../_Legacy/PackageActions/addApplication.cs | 106 +-- 62 files changed, 2043 insertions(+), 2050 deletions(-) delete mode 100644 src/Umbraco.Core/Models/ApplicationTree.cs delete mode 100644 src/Umbraco.Core/Models/Section.cs delete mode 100644 src/Umbraco.Core/Services/ISectionService.cs create mode 100644 src/Umbraco.Tests/Packaging/Packages/Document_Type_Picker_1.1.zip rename src/Umbraco.Web/{ => Controllers}/TagsController.cs (89%) create mode 100644 src/Umbraco.Web/Models/ContentEditing/ApplicationTree.cs create mode 100644 src/Umbraco.Web/Models/ContentEditing/IBackOfficeSection.cs delete mode 100644 src/Umbraco.Web/Models/Trees/ApplicationAttribute.cs delete mode 100644 src/Umbraco.Web/Models/Trees/IApplication.cs rename src/{Umbraco.Core => Umbraco.Web}/Services/IApplicationTreeService.cs (52%) create mode 100644 src/Umbraco.Web/Services/ISectionService.cs create mode 100644 src/Umbraco.Web/Trees/BackOfficeSectionCollection.cs create mode 100644 src/Umbraco.Web/Trees/TreeCollection.cs rename src/Umbraco.Web/Trees/{ApplicationTreeExtensions.cs => TreeControllerResolver.cs} (56%) delete mode 100644 src/Umbraco.Web/WebApi/Filters/LegacyTreeAuthorizeAttribute.cs diff --git a/src/Umbraco.Core/Composing/Composers/ServicesComposer.cs b/src/Umbraco.Core/Composing/Composers/ServicesComposer.cs index 8c9ccd1088..0b83373d99 100644 --- a/src/Umbraco.Core/Composing/Composers/ServicesComposer.cs +++ b/src/Umbraco.Core/Composing/Composers/ServicesComposer.cs @@ -73,10 +73,6 @@ namespace Umbraco.Core.Composing.Composers factory.GetInstance(), factory.GetInstance(), new DirectoryInfo(IOHelper.GetRootDirectorySafe()))); - //TODO: These are replaced in the web project - we need to declare them so that - // something is wired up, just not sure this is very nice but will work for now. - composition.RegisterUnique(); - composition.RegisterUnique(); return composition; } diff --git a/src/Umbraco.Core/Models/ApplicationTree.cs b/src/Umbraco.Core/Models/ApplicationTree.cs deleted file mode 100644 index ccdebea724..0000000000 --- a/src/Umbraco.Core/Models/ApplicationTree.cs +++ /dev/null @@ -1,170 +0,0 @@ -using System; -using System.Collections.Concurrent; -using System.Diagnostics; -using Umbraco.Core.Services; - -namespace Umbraco.Core.Models -{ - [DebuggerDisplay("Tree - {Title} ({ApplicationAlias})")] - public class ApplicationTree - { - private static readonly ConcurrentDictionary ResolvedTypes = new ConcurrentDictionary(); - - /// - /// Initializes a new instance of the class. - /// - public ApplicationTree() { } - - /// - /// Initializes a new instance of the class. - /// - /// if set to true [initialize]. - /// The sort order. - /// The application alias. - /// The tree alias. - /// The tree title. - /// The icon closed. - /// The icon opened. - /// The tree type. - public ApplicationTree(bool initialize, int sortOrder, string applicationAlias, string alias, string title, string iconClosed, string iconOpened, string type) - { - Initialize = initialize; - SortOrder = sortOrder; - ApplicationAlias = applicationAlias; - Alias = alias; - Title = title; - IconClosed = iconClosed; - IconOpened = iconOpened; - Type = type; - - } - - /// - /// Gets or sets a value indicating whether this should initialize. - /// - /// true if initialize; otherwise, false. - public bool Initialize { get; set; } - - /// - /// Gets or sets the sort order. - /// - /// The sort order. - public int SortOrder { get; set; } - - /// - /// Gets the application alias. - /// - /// The application alias. - public string ApplicationAlias { get; } - - /// - /// Gets the tree alias. - /// - /// The alias. - public string Alias { get; } - - /// - /// Gets or sets the tree title. - /// - /// The title. - public string Title { get; set; } - - /// - /// Gets or sets the icon closed. - /// - /// The icon closed. - public string IconClosed { get; set; } - - /// - /// Gets or sets the icon opened. - /// - /// The icon opened. - public string IconOpened { get; set; } - - /// - /// Gets or sets the tree type assembly name. - /// - /// The type. - public string Type { get; set; } - - /// - /// Returns the localized root node display name - /// - /// - /// - public string GetRootNodeDisplayName(ILocalizedTextService textService) - { - var label = $"[{Alias}]"; - - // try to look up a the localized tree header matching the tree alias - var localizedLabel = textService.Localize("treeHeaders/" + Alias); - - // if the localizedLabel returns [alias] then return the title attribute from the trees.config file, if it's defined - if (localizedLabel != null && localizedLabel.Equals(label, StringComparison.InvariantCultureIgnoreCase)) - { - if (string.IsNullOrEmpty(Title) == false) - label = Title; - } - else - { - // the localizedLabel translated into something that's not just [alias], so use the translation - label = localizedLabel; - } - - return label; - } - - private Type _runtimeType; - - /// - /// Returns the CLR type based on it's assembly name stored in the config - /// - /// - public Type GetRuntimeType() - { - return _runtimeType ?? (_runtimeType = System.Type.GetType(Type)); - } - - /// - /// Used to try to get and cache the tree type - /// - /// - /// - internal static Type TryGetType(string type) - { - try - { - return ResolvedTypes.GetOrAdd(type, s => - { - var result = System.Type.GetType(type); - if (result != null) - { - return result; - } - - //we need to implement a bit of a hack here due to some trees being renamed and backwards compat - var parts = type.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries); - if (parts.Length != 2) - throw new InvalidOperationException("Could not resolve type"); - if (parts[1].Trim() != "Umbraco.Web" || parts[0].StartsWith("Umbraco.Web.Trees") == false || parts[0].EndsWith("Controller")) - throw new InvalidOperationException("Could not resolve type"); - - //if it's one of our controllers but it's not suffixed with "Controller" then add it and try again - var tempType = parts[0] + "Controller, Umbraco.Web"; - - result = System.Type.GetType(tempType); - if (result != null) - return result; - - throw new InvalidOperationException("Could not resolve type"); - }); - } - catch (InvalidOperationException) - { - //swallow, this is our own exception, couldn't find the type - // fixme bad use of exceptions here! - return null; - } - } - } -} diff --git a/src/Umbraco.Core/Models/Section.cs b/src/Umbraco.Core/Models/Section.cs deleted file mode 100644 index 4b7f8309dd..0000000000 --- a/src/Umbraco.Core/Models/Section.cs +++ /dev/null @@ -1,22 +0,0 @@ -namespace Umbraco.Core.Models -{ - /// - /// Represents a section defined in the app.config file. - /// - public class Section - { - public Section(string name, string @alias, int sortOrder) - { - Name = name; - Alias = alias; - SortOrder = sortOrder; - } - - public Section() - { } - - public string Name { get; set; } - public string Alias { get; set; } - public int SortOrder { get; set; } - } -} diff --git a/src/Umbraco.Core/Services/ISectionService.cs b/src/Umbraco.Core/Services/ISectionService.cs deleted file mode 100644 index 899ae78245..0000000000 --- a/src/Umbraco.Core/Services/ISectionService.cs +++ /dev/null @@ -1,114 +0,0 @@ -using System.Collections.Generic; -using Umbraco.Core.Models; - -namespace Umbraco.Core.Services -{ - public interface ISectionService - { - /// - /// The cache storage for all applications - /// - IEnumerable
GetSections(); - - /// - /// Get the user group's allowed sections - /// - /// - /// - IEnumerable
GetAllowedSections(int userId); - - /// - /// Gets the application by its alias. - /// - /// The application alias. - /// - Section GetByAlias(string appAlias); - - /// - /// Creates a new applcation if no application with the specified alias is found. - /// - /// The application name. - /// The application alias. - /// The application icon, which has to be located in umbraco/images/tray folder. - void MakeNew(string name, string alias, string icon); - - /// - /// Makes the new. - /// - /// The name. - /// The alias. - /// The icon. - /// The sort order. - void MakeNew(string name, string alias, string icon, int sortOrder); - - /// - /// Deletes the section - /// - void DeleteSection(Section section); - } - - /// - /// Purely used to allow a service context to create the default services - /// - internal class EmptySectionService : ISectionService - { - /// - /// The cache storage for all applications - /// - public IEnumerable
GetSections() - { - throw new System.NotImplementedException(); - } - - /// - /// Get the user's allowed sections - /// - /// - /// - public IEnumerable
GetAllowedSections(int userId) - { - throw new System.NotImplementedException(); - } - - /// - /// Gets the application by its alias. - /// - /// The application alias. - /// - public Section GetByAlias(string appAlias) - { - throw new System.NotImplementedException(); - } - - /// - /// Creates a new applcation if no application with the specified alias is found. - /// - /// The application name. - /// The application alias. - /// The application icon, which has to be located in umbraco/images/tray folder. - public void MakeNew(string name, string alias, string icon) - { - throw new System.NotImplementedException(); - } - - /// - /// Makes the new. - /// - /// The name. - /// The alias. - /// The icon. - /// The sort order. - public void MakeNew(string name, string alias, string icon, int sortOrder) - { - throw new System.NotImplementedException(); - } - - /// - /// Deletes the section - /// - public void DeleteSection(Section section) - { - throw new System.NotImplementedException(); - } - } -} diff --git a/src/Umbraco.Core/Services/ServiceContext.cs b/src/Umbraco.Core/Services/ServiceContext.cs index 731d3a58c6..6d7ac8a5e7 100644 --- a/src/Umbraco.Core/Services/ServiceContext.cs +++ b/src/Umbraco.Core/Services/ServiceContext.cs @@ -25,8 +25,6 @@ namespace Umbraco.Core.Services private readonly Lazy _serverRegistrationService; private readonly Lazy _entityService; private readonly Lazy _relationService; - private readonly Lazy _treeService; - private readonly Lazy _sectionService; private readonly Lazy _macroService; private readonly Lazy _memberTypeService; private readonly Lazy _memberGroupService; @@ -38,7 +36,7 @@ namespace Umbraco.Core.Services /// /// Initializes a new instance of the class with lazy services. /// - public ServiceContext(Lazy publicAccessService, Lazy domainService, Lazy auditService, Lazy localizedTextService, Lazy tagService, Lazy contentService, Lazy userService, Lazy memberService, Lazy mediaService, Lazy contentTypeService, Lazy mediaTypeService, Lazy dataTypeService, Lazy fileService, Lazy localizationService, Lazy packagingService, Lazy serverRegistrationService, Lazy entityService, Lazy relationService, Lazy treeService, Lazy sectionService, Lazy macroService, Lazy memberTypeService, Lazy memberGroupService, Lazy notificationService, Lazy externalLoginService, Lazy redirectUrlService, Lazy consentService) + public ServiceContext(Lazy publicAccessService, Lazy domainService, Lazy auditService, Lazy localizedTextService, Lazy tagService, Lazy contentService, Lazy userService, Lazy memberService, Lazy mediaService, Lazy contentTypeService, Lazy mediaTypeService, Lazy dataTypeService, Lazy fileService, Lazy localizationService, Lazy packagingService, Lazy serverRegistrationService, Lazy entityService, Lazy relationService, Lazy macroService, Lazy memberTypeService, Lazy memberGroupService, Lazy notificationService, Lazy externalLoginService, Lazy redirectUrlService, Lazy consentService) { _publicAccessService = publicAccessService; _domainService = domainService; @@ -58,8 +56,6 @@ namespace Umbraco.Core.Services _serverRegistrationService = serverRegistrationService; _entityService = entityService; _relationService = relationService; - _treeService = treeService; - _sectionService = sectionService; _macroService = macroService; _memberTypeService = memberTypeService; _memberGroupService = memberGroupService; @@ -90,8 +86,6 @@ namespace Umbraco.Core.Services IMemberTypeService memberTypeService = null, IMemberService memberService = null, IUserService userService = null, - ISectionService sectionService = null, - IApplicationTreeService treeService = null, ITagService tagService = null, INotificationService notificationService = null, ILocalizedTextService localizedTextService = null, @@ -125,8 +119,6 @@ namespace Umbraco.Core.Services Lazy(serverRegistrationService), Lazy(entityService), Lazy(relationService), - Lazy(treeService), - Lazy(sectionService), Lazy(macroService), Lazy(memberTypeService), Lazy(memberGroupService), @@ -236,16 +228,6 @@ namespace Umbraco.Core.Services /// public IMemberService MemberService => _memberService.Value; - /// - /// Gets the - /// - public ISectionService SectionService => _sectionService.Value; - - /// - /// Gets the - /// - public IApplicationTreeService ApplicationTreeService => _treeService.Value; - /// /// Gets the MemberTypeService /// diff --git a/src/Umbraco.Core/Umbraco.Core.csproj b/src/Umbraco.Core/Umbraco.Core.csproj index 2236854351..8395dd9cb8 100755 --- a/src/Umbraco.Core/Umbraco.Core.csproj +++ b/src/Umbraco.Core/Umbraco.Core.csproj @@ -678,7 +678,6 @@ - @@ -875,7 +874,6 @@ - @@ -1390,7 +1388,6 @@ - @@ -1420,7 +1417,6 @@ - diff --git a/src/Umbraco.Tests/Cache/DistributedCacheBinderTests.cs b/src/Umbraco.Tests/Cache/DistributedCacheBinderTests.cs index 50b27da89f..3532a11c63 100644 --- a/src/Umbraco.Tests/Cache/DistributedCacheBinderTests.cs +++ b/src/Umbraco.Tests/Cache/DistributedCacheBinderTests.cs @@ -47,13 +47,6 @@ namespace Umbraco.Tests.Cache //Permission.Deleted += PermissionDeleted; //PermissionRepository.AssignedPermissions += CacheRefresherEventHandler_AssignedPermissions; - new EventDefinition(null, serviceContext.ApplicationTreeService, new EventArgs(), "Deleted"), - new EventDefinition(null, serviceContext.ApplicationTreeService, new EventArgs(), "Updated"), - new EventDefinition(null, serviceContext.ApplicationTreeService, new EventArgs(), "New"), - - new EventDefinition(null, serviceContext.SectionService, new EventArgs(), "Deleted"), - new EventDefinition(null, serviceContext.SectionService, new EventArgs(), "New"), - new EventDefinition>(null, serviceContext.UserService, new SaveEventArgs(Enumerable.Empty())), new EventDefinition>(null, serviceContext.UserService, new DeleteEventArgs(Enumerable.Empty())), new EventDefinition>(null, serviceContext.UserService, new SaveEventArgs(Enumerable.Empty())), diff --git a/src/Umbraco.Tests/Packaging/Packages/Document_Type_Picker_1.1.zip b/src/Umbraco.Tests/Packaging/Packages/Document_Type_Picker_1.1.zip new file mode 100644 index 0000000000000000000000000000000000000000..18449bd3735870c98e711525a7ea9883941e321f GIT binary patch literal 6147 zcma)=RZJWVl!bAp6qn)@DHL~ich`a9GDv|U9o*dqXP~$j8>HwIcc+6CcZxg3_Ww7V z%_f^o_TGmt_vYr@m-BSARFP4L5D*YB5dOwu%SOrHjmG{vav>nF{0m`zTP^`UD|RbO zJ{xvEJ{}u(VJ6 z>RqIdc64-an*}K5AZ-UAemx4uIqk2~WIP~j*f$8$!If+UInR2e$q(g!=FuH-F4L-4 z9dYM91Y;{#CsPV><>WPb+O>B}bWg&$d6f8SWagJ$DRHjNnOwXeRSe4r{pSursKP2+ z5*!Csj==m?xdmqNt(gZb?I}|u@T-17dXyRCfw)Zm+V*Ay#4LOW7g^5bn$2t^_RxbI zb~nFqnEJIPe82VAW1vgLGN5?NciA2C@u8*RO#64`l1El`KGb^eq{hBl4d;)_RN9|h z;2vSvnrG6N7_BRX3JZ;r19(S{2)`5E;kr~#Mr_~Kl~nJtaO8z|tn0FriIPLEk-0X6 zvkrodN)M#{Ib62%^qF1q_<~==kbKIOK6YgSp`>(Lk|N2qo8u_hSPg*eGz2WtsELJg z&i!U|fb7dz**KzB*2#Yx-xvl~W{KI5olssKlTbSoK4HwQbkz%LRT0Zs&^mDvdZM^f zaJ6-Hs!Z$PJ3v>ei2UT60fWv}du)Y_hI){-2L5Ct%oxT=k6UZvoJj>&I^!)jbKH&Z zn`AY%?Dat5!Xs-{1DBUi;|eN+y0ooBU9<+W zXtE^aR5vrFAIN4;N9Ijz8F;tVH*fW17b6FKG25!*j&7OkS`7Kf{_6PgnqvHT(@?hk zLv`$3uPtrWhuOD|xBV3K-Z=x^L*J84#xI&3h8UoEF81qz>!y#mJLY5D1@>wIkH3r( zKD4hMlFtyiV)%T#VfSo7!H3Sox<$um(_bE!wiwmw%hWWmIl0OA#aZY==|=ILqn824 zdZOgHV!5W3XWn)GHS;s9Br+0=)89}`$X;b0zt|G{kaO!YVoO;^U|9U?4*?C z!%|*r>zZj^}+;2PT53CIGVe$h&mj**Cis2A- z`8%{XPB83WbizI%%r;n-d1*hl?rK}yc6^H~msEv1`WhYfE;4vHO~yK60KQbPy+H~& z`rp(kJ4~kAZ*nz~nKy2r#MMU^21S{qW`tix;>?ZXUT`dLZ6bRY-q$g#o^Br|Ldz)_ zDg*O{d2CY7!@cjB=Op+FYx~N>fq<(Ap`nroe+W26+&nUTGK}0iDtO^=(%MYj)iRO# z?oT?0ZWTHZ_P``(^9-`JtTQyLdIA#NI|)c0!3Dc?);nWKZ{Cszq-_5F9y*io>5Hs_ zAnWq_~2s-hqXHNdHM>xV6h`*qRK!=$MrB=hXz+vHdBI$$LU=ggLL z^jO=a$aVtKjpt#M5lUhlQ9Qx@QXkS}vB$}6U~xu4-=rlJC}joEaE7=&(6 z-FR1gL)Z7leecjH^`_wsAd@Ib5u$uuuP82a*C4daRl_d$88oY z?qOz0+t3y^;Qp(6uXXmoj0;jop*I%skt<_q-YP(blUACHztsDilz|0Jd@ULU$sc+RLK@h*@r?;B}v z5IR{Rml=D#;)V+nRmdHtzuv~~FmDRVv)(rn+fk1Yzhcp14yw3Di#tW^85Hq1ZQVh1EGVb^Pax`C0-tS*wo!YH)*C?b4l>Vd)h$bQvM zNSz2P#E`kRXV;MRxn)F7ARMWiXcSQ(iu@Eq6X`bGc#i~zADH>Am4e1_OzOkKBI!m< z5joA{8()ep_|OZrSOWD$LqRZUQF*|}qFR(&V0a?+IQvVvdeiP8IhwTVglv`-h2`=uZ zwI0SrzXM<)cRy#(T3;a9U#glApBlWuG3yBb(Dk~5p$5_3H;wnI@2XOw=YrfS{!*7u z!a)pbk#MBP%1@F8K3KPxe-~fzp(YrDTIB`9&np ztMlJ}{Q*|$yDUgbRY&CGkDxUh_5?3`NWEGwS7;n+Y6(spup!c*h{@AP*SUfef@0ej zlCCAABKL2mkX~}vCOp`U((16TP~2 zxKU*Dd2$2VNmPQMwt~1_3Aj|k8m7@uWe7mq1%nXTy!oGrE^CkEty^Pbnro5D>Aspl ziUt=k7gWZqNu}1Qa&_*oo?Z2$e^eRLTjSg3$omYe6;Z8!i9pU+Of8oM{Iqvl_}wkRr_ix0&v0i6~@8!2pJC z0?yO1Lt}PzprseZS^620EvXAmX#;6|$gCV5aw66pHHh;7pohN53HJUgym11h0jGT- znJ#Tb$S;1B9Xh0Q7{kcJ_icsw*?<*Go{dAqDRdLD{m}#B1gZm$H28~O^a20@7UFd; z^36^G%h6?Y1+qrj_`+%8r5B+Oov?kBJsBZ})OR8HZny>6jN6V{zL7h7RpcaO z5gO`zz>0is7z+KjO(6iDFK#}CfU5I7l!)6=*Ub>G`aIq+tQvmPydGtaCD@oHL7j90pUrRf%j^&T{Jpd~)}G*FsWLG6xG|$2-QLDh zs_|#`jtveNrTh3?w*S(#Uy?=#qbF-XKV_X`86NIM@j3^XQuIuxS==-_^47lWv$vJq zAS-P47_7Qm>CT+iJm*k8G{$l8J-3y)##sctTD3kLG_*=!qr&g1_QQB(#59Eb%crLV zyB0Zy2en_nt@k~(T!~f6Jdu38;wfg|vSD{Jz{iU_vPH+URQobavCM`S`ojBP9;v#WL= z>Z>yLbwtLvJL$L%%hHAtZ)_WxxdjDH?IaWh#|7-DgT4f|^*0Mk?5N0h@9(^Ql#GIQ zIPZo_?1=li8lhhfl>D5VUi_o>5u6|BkcdlML!dv$Kug0CZ>N#VXU~Vj14NKiemoKL z8^EUPT9E^p7+)OUXJn4d@ETz@+s$N&yHVJsIlvm?kZ-d?&o2WH?C?`O%u(#MA9=o$ zFRG_EyMLUP8e&~#83rVlo?X{NHswSt)xi)PQDuT0WK_FkPNI*INOd%XY!yZvU(ZCP zliy@uGXh7|XauM@$j8aYgvj>o&U@JHj=HIZDP;bHTs~l z#J%r#h;A3H8V{i4hs=?{$rrsAJ!&sZf`nK1fw!_E1@2Ahg8SUhmgqI(azDLQ4M@iN zC^^OE24Bns*a5 zYX13M#}>VKWJ{)NbfNLRWwol7POHxS-zz(`+@#DH?~BEaN{`5>vKM7uzs4yEHtZ6? z%b<$VnhJ`OpC?)Tqq&=9t&ST?%NVFxmMrV7#gut+RWr>z947bo(U#Wsuepn;P z2CFR7mLNf@aY{4MQuz%Ey_;>92&Gazd0)1pkuV>KwP$FYH0)fzzAyzRb18KS!#fP| zDm)@sn%t?!zS76PA{H;7zsbm`LvQ< zujr5-h3qLt)ms{ZJ(|eq>yHUna6T$~q`<+!`i{I(0_}hdrjfw{)sLA>FU8Y#MTJzp z*e50C?c_m#FH~OBZ=h(72(>P=r?NoiPd(G^7sqAn!C@OdA#19pGdl0kztLc)mT@T{ z7Be~GoNdd0Ql|LXVMXGm$s{cIE-K^)y>^vSo|GH9rXpxxY-9~l>K#GNBhG=cQF4E7 zPQ)#W|4u#$G>eS?!x}d`c5DPSs!rJR`EPK;qm=L;;3B%{6}`SczsYyVAJc^r&E~K3qG|;RjqSU&+G3p*#4?VcqDZL6ezyGN!?Y&PAwMCGXttI%{xhL8yTaq?Eq< z!Dq0=I+ttmY;wh-`*-ieub$qXlxxTIW~q$@is3z}pp}|?M^7ZTK{O0Ozv+k!XItJ+ ztD2PAu@d&U|2j?_Wf89v($Jg`iub|tXMYh$t*YDIY6l0NCw1QrW4HSAJsemBZ5|$j zc=CN$8#*Yuse0CY|4tT1nYIGD4da+(W(J81-!t|qml8NsXvJnZY`DH*u52LwX6eOO zS=lmpgRjK@9j`nq4@p?zC}%LCs(}HYF7g11dgq<8GP&Ae+?Lx6RC8wWoWnR|#or^n z#*ni+O-L?dB$%ySp}o{={FHmXPRfKTAdMzNu`Kd!M#z({447Y!hR=?#UPT;3TsRPy zp4Ci{VaAufHd_@(ddu4eCH3r1WMq6r})JmSFPFdJrM`@a{?6axWC`G}A^DqGoIlg>9x%ssmFHAc zA;yh4FL&ObY{WN%1-N@ZkQEL$$G;3WwzQ5C?2izkG6-CG9J)TO|IP@-u!NrV(IF!O z^B$y&*w-qd>0l#76lq7<_+~i>wK9}j-kQ0>a__4_Y*flT4t|0TMxo|Gdl@&YMrW|_ zyf>Rk#+sy%!PnQtW14igo!1F%z6^)&_4m-!DYYxrb*s~~n$M{#zt~jJ>Kv8V(9+i4 z*g{(07N zU#$Pmp^gUD6>_j~06U-(Tzh@KF1lDf`}$<|G`?Nw)~I&+x44+O+%wT@SuA!g(T~rN zmHKA#w_@Giy|&*|g5qw%ZWaBZm22Khof#gU!Ab#UAiM>3)4w63*ZCrZ{O}|}InXr) zDEm-=^Z;@c|HA%q!+sU`IP!MD@9;zfov$>&X%zS7{fYQ{R}k>5k%iHQbAPk6 zv>`9*-r5WeOnzihj!z!MY(Xwx=F_No(zlR6)h*&N*Y?j*K;h+iW6?!6m(t{sdS4>4 zTY#&rxiRB(jqCp|IZW2TpJOt1#LY=mIgpIsnu_FWt6e;Mw;{xXkgAk8nI`qZsD(Bv zyvkm`XZB0;m2<6&qi_R=jZU%pn;+RV=FBo@`K9B9KhnO?%gL_4Nh)<;z>P1{#oja~ zP5Tq~;tO(M&{(VFdC$4z)(}~%)j} zHaDuLH34?Tfy}eJl|Mlb3)|1$JHVBocd@TYa85+6|IRZ*9m?fCGU0)xkq{6-Cf*ZaN#F@~PP8t@EI#8X^FN|lf;z-*2tigPkH zbrg##Zrs60*X2O={)MXU%7Jr7nG#W4#aq<9*%R6EOj#p%)rC#(AeEk5y&=)qjcZUYRKJY3dvzFX0C%hZGvfmP~T#f zQE#0|`ZS;WNqe8?#T>YB${6@t4y*v{!=MN#$xTUjBy>z@K=aez!CKP*$1RsptqQGc zk|dGUV%496zS~E$+R}9%)*?sIBLm?z(d9%m`4Vn|Q4@2fa3w3t2p9ictT=2AdNUk? zLMN+KIpxkKthpLGVjEiap8)2v_dljd3GU)?Wp^bc@nX?%6L_7;3XYi#EDg^QzNTP` zBCVgG%9kK`2UACUoY-(lhqhT1bsm4*L4MLduukZszN-JxqW4DwVYV}pKLAJ%KHlO7 zpyewOysjBD1=o3I%T2PT-pko?rE%RcxC@rsV8_gkw$Oz4V4M&15?no@=0_tjhZ+fC z8$IL`v60`W-u5o)k=v(nZlh|cA|eqX{NLI6KX&^c_5V%M|5cUzFV+9;;P?NfNc#_` z|9SmC{EUV0?-Bt45rGV0H$DE%j^h-f<+aM~_CI_MRr*hAsiLC&dxP{(H~m8q(toG_ E0K6^9ApigX literal 0 HcmV?d00001 diff --git a/src/Umbraco.Tests/Services/SectionServiceTests.cs b/src/Umbraco.Tests/Services/SectionServiceTests.cs index ca5d755220..206c99ffbf 100644 --- a/src/Umbraco.Tests/Services/SectionServiceTests.cs +++ b/src/Umbraco.Tests/Services/SectionServiceTests.cs @@ -3,6 +3,7 @@ using System.Linq; using System.Threading; using Umbraco.Core.Models.Membership; using Umbraco.Tests.Testing; +using Umbraco.Web.Services; namespace Umbraco.Tests.Services { @@ -14,24 +15,20 @@ namespace Umbraco.Tests.Services [UmbracoTest(Database = UmbracoTestOptions.Database.NewSchemaPerTest, WithApplication = true)] public class SectionServiceTests : TestWithSomeContentBase { - public override void CreateTestData() - { - base.CreateTestData(); - - ServiceContext.SectionService.MakeNew("Content", "content", "icon-content"); - ServiceContext.SectionService.MakeNew("Media", "media", "icon-media"); - ServiceContext.SectionService.MakeNew("Settings", "settings", "icon-settings"); - ServiceContext.SectionService.MakeNew("Developer", "developer", "icon-developer"); - } + //fixme + private ISectionService SectionService => new SectionService(ServiceContext.UserService, null, null); + [Test] public void SectionService_Can_Get_Allowed_Sections_For_User() { + //fixme - need to mock + // Arrange var user = CreateTestUser(); // Act - var result = ServiceContext.SectionService.GetAllowedSections(user.Id).ToList(); + var result = SectionService.GetAllowedSections(user.Id).ToList(); // Assert Assert.AreEqual(3, result.Count); diff --git a/src/Umbraco.Tests/TestHelpers/ControllerTesting/TestControllerActivatorBase.cs b/src/Umbraco.Tests/TestHelpers/ControllerTesting/TestControllerActivatorBase.cs index 9e2a2156ee..31ee34843d 100644 --- a/src/Umbraco.Tests/TestHelpers/ControllerTesting/TestControllerActivatorBase.cs +++ b/src/Umbraco.Tests/TestHelpers/ControllerTesting/TestControllerActivatorBase.cs @@ -60,8 +60,7 @@ namespace Umbraco.Tests.TestHelpers.ControllerTesting memberTypeService: mockedMemberTypeService, dataTypeService: mockedDataTypeService, contentTypeService: mockedContentTypeService, - localizedTextService:Mock.Of(), - sectionService:Mock.Of()); + localizedTextService:Mock.Of()); var globalSettings = SettingsForTests.GenerateMockGlobalSettings(); diff --git a/src/Umbraco.Tests/TestHelpers/TestObjects-Mocks.cs b/src/Umbraco.Tests/TestHelpers/TestObjects-Mocks.cs index 8c230f98d0..4dfaa9e674 100644 --- a/src/Umbraco.Tests/TestHelpers/TestObjects-Mocks.cs +++ b/src/Umbraco.Tests/TestHelpers/TestObjects-Mocks.cs @@ -73,8 +73,6 @@ namespace Umbraco.Tests.TestHelpers MockService(container), MockService(container), MockService(container), - MockService(container), - MockService(container), MockService(container), MockService(container), MockService(container), diff --git a/src/Umbraco.Tests/TestHelpers/TestObjects.cs b/src/Umbraco.Tests/TestHelpers/TestObjects.cs index 14ffeb743f..f7f0d26c0e 100644 --- a/src/Umbraco.Tests/TestHelpers/TestObjects.cs +++ b/src/Umbraco.Tests/TestHelpers/TestObjects.cs @@ -188,9 +188,7 @@ namespace Umbraco.Tests.TestHelpers new DirectoryInfo(IOHelper.GetRootDirectorySafe()))); }); var relationService = GetLazyService(factory, c => new RelationService(scopeProvider, logger, eventMessagesFactory, entityService.Value, GetRepo(c), GetRepo(c))); - var treeService = GetLazyService(factory, c => new ApplicationTreeService(logger, cache, typeLoader)); - var tagService = GetLazyService(factory, c => new TagService(scopeProvider, logger, eventMessagesFactory, GetRepo(c))); - var sectionService = GetLazyService(factory, c => new SectionService(userService.Value, treeService.Value, scopeProvider, cache)); + var tagService = GetLazyService(factory, c => new TagService(scopeProvider, logger, eventMessagesFactory, GetRepo(c))); var redirectUrlService = GetLazyService(factory, c => new RedirectUrlService(scopeProvider, logger, eventMessagesFactory, GetRepo(c))); var consentService = GetLazyService(factory, c => new ConsentService(scopeProvider, logger, eventMessagesFactory, GetRepo(c))); @@ -213,8 +211,6 @@ namespace Umbraco.Tests.TestHelpers serverRegistrationService, entityService, relationService, - treeService, - sectionService, macroService, memberTypeService, memberGroupService, diff --git a/src/Umbraco.Tests/TreesAndSections/ApplicationTreeTest.cs b/src/Umbraco.Tests/TreesAndSections/ApplicationTreeTest.cs index 951246c535..95d90f1463 100644 --- a/src/Umbraco.Tests/TreesAndSections/ApplicationTreeTest.cs +++ b/src/Umbraco.Tests/TreesAndSections/ApplicationTreeTest.cs @@ -1,397 +1,397 @@ -using System.IO; -using NUnit.Framework; -using Umbraco.Core.Services; -using Umbraco.Tests.TestHelpers; -using System; -using System.Linq; -using System.Threading; -using Umbraco.Tests.Testing; -using Umbraco.Web.Services; -using Current = Umbraco.Web.Composing.Current; +//using System.IO; +//using NUnit.Framework; +//using Umbraco.Core.Services; +//using Umbraco.Tests.TestHelpers; +//using System; +//using System.Linq; +//using System.Threading; +//using Umbraco.Tests.Testing; +//using Umbraco.Web.Services; +//using Current = Umbraco.Web.Composing.Current; -namespace Umbraco.Tests.TreesAndSections -{ +//namespace Umbraco.Tests.TreesAndSections +//{ - /// - ///This is a test class for ApplicationTreeTest and is intended - ///to contain all ApplicationTreeTest Unit Tests - /// - [TestFixture] - [Apartment(ApartmentState.STA)] - [UmbracoTest(Database = UmbracoTestOptions.Database.NewSchemaPerTest)] - public class ApplicationTreeTest : TestWithDatabaseBase - { - public override void SetUp() - { - base.SetUp(); +// /// +// ///This is a test class for ApplicationTreeTest and is intended +// ///to contain all ApplicationTreeTest Unit Tests +// /// +// [TestFixture] +// [Apartment(ApartmentState.STA)] +// [UmbracoTest(Database = UmbracoTestOptions.Database.NewSchemaPerTest)] +// public class ApplicationTreeTest : TestWithDatabaseBase +// { +// public override void SetUp() +// { +// base.SetUp(); - var treesConfig = TestHelper.MapPathForTest("~/TEMP/TreesAndSections/trees.config"); - var appConfig = TestHelper.MapPathForTest("~/TEMP/TreesAndSections/applications.config"); - Directory.CreateDirectory(TestHelper.MapPathForTest("~/TEMP/TreesAndSections")); - using (var writer = File.CreateText(treesConfig)) - { - writer.Write(ResourceFiles.trees); - } - using (var writer = File.CreateText(appConfig)) - { - writer.Write(ResourceFiles.applications); - } +// var treesConfig = TestHelper.MapPathForTest("~/TEMP/TreesAndSections/trees.config"); +// var appConfig = TestHelper.MapPathForTest("~/TEMP/TreesAndSections/applications.config"); +// Directory.CreateDirectory(TestHelper.MapPathForTest("~/TEMP/TreesAndSections")); +// using (var writer = File.CreateText(treesConfig)) +// { +// writer.Write(ResourceFiles.trees); +// } +// using (var writer = File.CreateText(appConfig)) +// { +// writer.Write(ResourceFiles.applications); +// } - ApplicationTreeService.TreeConfigFilePath = treesConfig; - SectionService.AppConfigFilePath = appConfig; - } +// //ApplicationTreeService.TreeConfigFilePath = treesConfig; +// SectionService.AppConfigFilePath = appConfig; +// } - public override void TearDown() - { - base.TearDown(); +// public override void TearDown() +// { +// base.TearDown(); - if (Directory.Exists(TestHelper.MapPathForTest("~/TEMP/TreesAndSections"))) - { - Directory.Delete(TestHelper.MapPathForTest("~/TEMP/TreesAndSections"), true); - } - ApplicationTreeService.TreeConfigFilePath = null; - SectionService.AppConfigFilePath = null; - } +// if (Directory.Exists(TestHelper.MapPathForTest("~/TEMP/TreesAndSections"))) +// { +// Directory.Delete(TestHelper.MapPathForTest("~/TEMP/TreesAndSections"), true); +// } +// //ApplicationTreeService.TreeConfigFilePath = null; +// SectionService.AppConfigFilePath = null; +// } - /// - /// Creates a new app tree linked to an application, then delete the application and make sure the tree is gone as well - /// - [Test()] - public void ApplicationTree_Make_New_Then_Delete_App() - { - //create new app - var appName = Guid.NewGuid().ToString("N"); - var treeName = Guid.NewGuid().ToString("N"); - Current.Services.SectionService.MakeNew(appName, appName, "icon.jpg"); +// ///// +// ///// Creates a new app tree linked to an application, then delete the application and make sure the tree is gone as well +// ///// +// //[Test()] +// //public void ApplicationTree_Make_New_Then_Delete_App() +// //{ +// // //create new app +// // var appName = Guid.NewGuid().ToString("N"); +// // var treeName = Guid.NewGuid().ToString("N"); +// // Current.Services.SectionService.MakeNew(appName, appName, "icon.jpg"); - //check if it exists - var app = Current.Services.SectionService.GetByAlias(appName); - Assert.IsNotNull(app); +// // //check if it exists +// // var app = Current.Services.SectionService.GetByAlias(appName); +// // Assert.IsNotNull(app); - //create the new app tree assigned to the new app - Current.Services.ApplicationTreeService.MakeNew(false, 0, app.Alias, treeName, treeName, "icon.jpg", "icon.jpg", "Umbraco.Web.Trees.ContentTreeController, Umbraco.Web"); - var tree = Current.Services.ApplicationTreeService.GetByAlias(treeName); - Assert.IsNotNull(tree); +// // //create the new app tree assigned to the new app +// // Current.Services.ApplicationTreeService.MakeNew(false, 0, app.Alias, treeName, treeName, "icon.jpg", "icon.jpg", "Umbraco.Web.Trees.ContentTreeController, Umbraco.Web"); +// // var tree = Current.Services.ApplicationTreeService.GetByAlias(treeName); +// // Assert.IsNotNull(tree); - //now delete the app - Current.Services.SectionService.DeleteSection(app); +// // //now delete the app +// // Current.Services.SectionService.DeleteSection(app); - //check that the tree is gone - Assert.AreEqual(0, Current.Services.ApplicationTreeService.GetApplicationTrees(treeName).Count()); - } +// // //check that the tree is gone +// // Assert.AreEqual(0, Current.Services.ApplicationTreeService.GetApplicationTrees(treeName).Count()); +// //} - #region Tests to write - ///// - /////A test for ApplicationTree Constructor - ///// - //[TestMethod()] - //public void ApplicationTreeConstructorTest() - //{ - // bool silent = false; // TODO: Initialize to an appropriate value - // bool initialize = false; // TODO: Initialize to an appropriate value - // byte sortOrder = 0; // TODO: Initialize to an appropriate value - // string applicationAlias = string.Empty; // TODO: Initialize to an appropriate value - // string alias = string.Empty; // TODO: Initialize to an appropriate value - // string title = string.Empty; // TODO: Initialize to an appropriate value - // string iconClosed = string.Empty; // TODO: Initialize to an appropriate value - // string iconOpened = string.Empty; // TODO: Initialize to an appropriate value - // string assemblyName = string.Empty; // TODO: Initialize to an appropriate value - // string type = string.Empty; // TODO: Initialize to an appropriate value - // string action = string.Empty; // TODO: Initialize to an appropriate value - // ApplicationTree target = new ApplicationTree(silent, initialize, sortOrder, applicationAlias, alias, title, iconClosed, iconOpened, assemblyName, type, action); - // Assert.Inconclusive("TODO: Implement code to verify target"); - //} +// #region Tests to write +// ///// +// /////A test for ApplicationTree Constructor +// ///// +// //[TestMethod()] +// //public void ApplicationTreeConstructorTest() +// //{ +// // bool silent = false; // TODO: Initialize to an appropriate value +// // bool initialize = false; // TODO: Initialize to an appropriate value +// // byte sortOrder = 0; // TODO: Initialize to an appropriate value +// // string applicationAlias = string.Empty; // TODO: Initialize to an appropriate value +// // string alias = string.Empty; // TODO: Initialize to an appropriate value +// // string title = string.Empty; // TODO: Initialize to an appropriate value +// // string iconClosed = string.Empty; // TODO: Initialize to an appropriate value +// // string iconOpened = string.Empty; // TODO: Initialize to an appropriate value +// // string assemblyName = string.Empty; // TODO: Initialize to an appropriate value +// // string type = string.Empty; // TODO: Initialize to an appropriate value +// // string action = string.Empty; // TODO: Initialize to an appropriate value +// // ApplicationTree target = new ApplicationTree(silent, initialize, sortOrder, applicationAlias, alias, title, iconClosed, iconOpened, assemblyName, type, action); +// // Assert.Inconclusive("TODO: Implement code to verify target"); +// //} - ///// - /////A test for ApplicationTree Constructor - ///// - //[TestMethod()] - //public void ApplicationTreeConstructorTest1() - //{ - // ApplicationTree target = new ApplicationTree(); - // Assert.Inconclusive("TODO: Implement code to verify target"); - //} +// ///// +// /////A test for ApplicationTree Constructor +// ///// +// //[TestMethod()] +// //public void ApplicationTreeConstructorTest1() +// //{ +// // ApplicationTree target = new ApplicationTree(); +// // Assert.Inconclusive("TODO: Implement code to verify target"); +// //} - ///// - /////A test for Delete - ///// - //[TestMethod()] - //public void DeleteTest() - //{ - // ApplicationTree target = new ApplicationTree(); // TODO: Initialize to an appropriate value - // target.Delete(); - // Assert.Inconclusive("A method that does not return a value cannot be verified."); - //} +// ///// +// /////A test for Delete +// ///// +// //[TestMethod()] +// //public void DeleteTest() +// //{ +// // ApplicationTree target = new ApplicationTree(); // TODO: Initialize to an appropriate value +// // target.Delete(); +// // Assert.Inconclusive("A method that does not return a value cannot be verified."); +// //} - ///// - /////A test for Save - ///// - //[TestMethod()] - //public void SaveTest() - //{ - // ApplicationTree target = new ApplicationTree(); // TODO: Initialize to an appropriate value - // target.Save(); - // Assert.Inconclusive("A method that does not return a value cannot be verified."); - //} +// ///// +// /////A test for Save +// ///// +// //[TestMethod()] +// //public void SaveTest() +// //{ +// // ApplicationTree target = new ApplicationTree(); // TODO: Initialize to an appropriate value +// // target.Save(); +// // Assert.Inconclusive("A method that does not return a value cannot be verified."); +// //} - ///// - /////A test for getAll - ///// - //[TestMethod()] - //public void getAllTest() - //{ - // ApplicationTree[] expected = null; // TODO: Initialize to an appropriate value - // ApplicationTree[] actual; - // actual = ApplicationTree.getAll(); - // Assert.AreEqual(expected, actual); - // Assert.Inconclusive("Verify the correctness of this test method."); - //} +// ///// +// /////A test for getAll +// ///// +// //[TestMethod()] +// //public void getAllTest() +// //{ +// // ApplicationTree[] expected = null; // TODO: Initialize to an appropriate value +// // ApplicationTree[] actual; +// // actual = ApplicationTree.getAll(); +// // Assert.AreEqual(expected, actual); +// // Assert.Inconclusive("Verify the correctness of this test method."); +// //} - ///// - /////A test for getApplicationTree - ///// - //[TestMethod()] - //public void getApplicationTreeTest() - //{ - // string applicationAlias = string.Empty; // TODO: Initialize to an appropriate value - // ApplicationTree[] expected = null; // TODO: Initialize to an appropriate value - // ApplicationTree[] actual; - // actual = ApplicationTree.getApplicationTree(applicationAlias); - // Assert.AreEqual(expected, actual); - // Assert.Inconclusive("Verify the correctness of this test method."); - //} +// ///// +// /////A test for getApplicationTree +// ///// +// //[TestMethod()] +// //public void getApplicationTreeTest() +// //{ +// // string applicationAlias = string.Empty; // TODO: Initialize to an appropriate value +// // ApplicationTree[] expected = null; // TODO: Initialize to an appropriate value +// // ApplicationTree[] actual; +// // actual = ApplicationTree.getApplicationTree(applicationAlias); +// // Assert.AreEqual(expected, actual); +// // Assert.Inconclusive("Verify the correctness of this test method."); +// //} - ///// - /////A test for getApplicationTree - ///// - //[TestMethod()] - //public void getApplicationTreeTest1() - //{ - // string applicationAlias = string.Empty; // TODO: Initialize to an appropriate value - // bool onlyInitializedApplications = false; // TODO: Initialize to an appropriate value - // ApplicationTree[] expected = null; // TODO: Initialize to an appropriate value - // ApplicationTree[] actual; - // actual = ApplicationTree.getApplicationTree(applicationAlias, onlyInitializedApplications); - // Assert.AreEqual(expected, actual); - // Assert.Inconclusive("Verify the correctness of this test method."); - //} +// ///// +// /////A test for getApplicationTree +// ///// +// //[TestMethod()] +// //public void getApplicationTreeTest1() +// //{ +// // string applicationAlias = string.Empty; // TODO: Initialize to an appropriate value +// // bool onlyInitializedApplications = false; // TODO: Initialize to an appropriate value +// // ApplicationTree[] expected = null; // TODO: Initialize to an appropriate value +// // ApplicationTree[] actual; +// // actual = ApplicationTree.getApplicationTree(applicationAlias, onlyInitializedApplications); +// // Assert.AreEqual(expected, actual); +// // Assert.Inconclusive("Verify the correctness of this test method."); +// //} - ///// - /////A test for getByAlias - ///// - //[TestMethod()] - //public void getByAliasTest() - //{ - // string treeAlias = string.Empty; // TODO: Initialize to an appropriate value - // ApplicationTree expected = null; // TODO: Initialize to an appropriate value - // ApplicationTree actual; - // actual = ApplicationTree.getByAlias(treeAlias); - // Assert.AreEqual(expected, actual); - // Assert.Inconclusive("Verify the correctness of this test method."); - //} +// ///// +// /////A test for getByAlias +// ///// +// //[TestMethod()] +// //public void getByAliasTest() +// //{ +// // string treeAlias = string.Empty; // TODO: Initialize to an appropriate value +// // ApplicationTree expected = null; // TODO: Initialize to an appropriate value +// // ApplicationTree actual; +// // actual = ApplicationTree.getByAlias(treeAlias); +// // Assert.AreEqual(expected, actual); +// // Assert.Inconclusive("Verify the correctness of this test method."); +// //} - ///// - /////A test for Action - ///// - //[TestMethod()] - //public void ActionTest() - //{ - // ApplicationTree target = new ApplicationTree(); // TODO: Initialize to an appropriate value - // string expected = string.Empty; // TODO: Initialize to an appropriate value - // string actual; - // target.Action = expected; - // actual = target.Action; - // Assert.AreEqual(expected, actual); - // Assert.Inconclusive("Verify the correctness of this test method."); - //} +// ///// +// /////A test for Action +// ///// +// //[TestMethod()] +// //public void ActionTest() +// //{ +// // ApplicationTree target = new ApplicationTree(); // TODO: Initialize to an appropriate value +// // string expected = string.Empty; // TODO: Initialize to an appropriate value +// // string actual; +// // target.Action = expected; +// // actual = target.Action; +// // Assert.AreEqual(expected, actual); +// // Assert.Inconclusive("Verify the correctness of this test method."); +// //} - ///// - /////A test for Alias - ///// - //[TestMethod()] - //public void AliasTest() - //{ - // ApplicationTree target = new ApplicationTree(); // TODO: Initialize to an appropriate value - // string actual; - // actual = target.Alias; - // Assert.Inconclusive("Verify the correctness of this test method."); - //} +// ///// +// /////A test for Alias +// ///// +// //[TestMethod()] +// //public void AliasTest() +// //{ +// // ApplicationTree target = new ApplicationTree(); // TODO: Initialize to an appropriate value +// // string actual; +// // actual = target.Alias; +// // Assert.Inconclusive("Verify the correctness of this test method."); +// //} - ///// - /////A test for ApplicationAlias - ///// - //[TestMethod()] - //public void ApplicationAliasTest() - //{ - // ApplicationTree target = new ApplicationTree(); // TODO: Initialize to an appropriate value - // string actual; - // actual = target.ApplicationAlias; - // Assert.Inconclusive("Verify the correctness of this test method."); - //} +// ///// +// /////A test for ApplicationAlias +// ///// +// //[TestMethod()] +// //public void ApplicationAliasTest() +// //{ +// // ApplicationTree target = new ApplicationTree(); // TODO: Initialize to an appropriate value +// // string actual; +// // actual = target.ApplicationAlias; +// // Assert.Inconclusive("Verify the correctness of this test method."); +// //} - ///// - /////A test for AssemblyName - ///// - //[TestMethod()] - //public void AssemblyNameTest() - //{ - // ApplicationTree target = new ApplicationTree(); // TODO: Initialize to an appropriate value - // string expected = string.Empty; // TODO: Initialize to an appropriate value - // string actual; - // target.AssemblyName = expected; - // actual = target.AssemblyName; - // Assert.AreEqual(expected, actual); - // Assert.Inconclusive("Verify the correctness of this test method."); - //} +// ///// +// /////A test for AssemblyName +// ///// +// //[TestMethod()] +// //public void AssemblyNameTest() +// //{ +// // ApplicationTree target = new ApplicationTree(); // TODO: Initialize to an appropriate value +// // string expected = string.Empty; // TODO: Initialize to an appropriate value +// // string actual; +// // target.AssemblyName = expected; +// // actual = target.AssemblyName; +// // Assert.AreEqual(expected, actual); +// // Assert.Inconclusive("Verify the correctness of this test method."); +// //} - ///// - /////A test for IconClosed - ///// - //[TestMethod()] - //public void IconClosedTest() - //{ - // ApplicationTree target = new ApplicationTree(); // TODO: Initialize to an appropriate value - // string expected = string.Empty; // TODO: Initialize to an appropriate value - // string actual; - // target.IconClosed = expected; - // actual = target.IconClosed; - // Assert.AreEqual(expected, actual); - // Assert.Inconclusive("Verify the correctness of this test method."); - //} +// ///// +// /////A test for IconClosed +// ///// +// //[TestMethod()] +// //public void IconClosedTest() +// //{ +// // ApplicationTree target = new ApplicationTree(); // TODO: Initialize to an appropriate value +// // string expected = string.Empty; // TODO: Initialize to an appropriate value +// // string actual; +// // target.IconClosed = expected; +// // actual = target.IconClosed; +// // Assert.AreEqual(expected, actual); +// // Assert.Inconclusive("Verify the correctness of this test method."); +// //} - ///// - /////A test for IconOpened - ///// - //[TestMethod()] - //public void IconOpenedTest() - //{ - // ApplicationTree target = new ApplicationTree(); // TODO: Initialize to an appropriate value - // string expected = string.Empty; // TODO: Initialize to an appropriate value - // string actual; - // target.IconOpened = expected; - // actual = target.IconOpened; - // Assert.AreEqual(expected, actual); - // Assert.Inconclusive("Verify the correctness of this test method."); - //} +// ///// +// /////A test for IconOpened +// ///// +// //[TestMethod()] +// //public void IconOpenedTest() +// //{ +// // ApplicationTree target = new ApplicationTree(); // TODO: Initialize to an appropriate value +// // string expected = string.Empty; // TODO: Initialize to an appropriate value +// // string actual; +// // target.IconOpened = expected; +// // actual = target.IconOpened; +// // Assert.AreEqual(expected, actual); +// // Assert.Inconclusive("Verify the correctness of this test method."); +// //} - ///// - /////A test for Initialize - ///// - //[TestMethod()] - //public void InitializeTest() - //{ - // ApplicationTree target = new ApplicationTree(); // TODO: Initialize to an appropriate value - // bool expected = false; // TODO: Initialize to an appropriate value - // bool actual; - // target.Initialize = expected; - // actual = target.Initialize; - // Assert.AreEqual(expected, actual); - // Assert.Inconclusive("Verify the correctness of this test method."); - //} +// ///// +// /////A test for Initialize +// ///// +// //[TestMethod()] +// //public void InitializeTest() +// //{ +// // ApplicationTree target = new ApplicationTree(); // TODO: Initialize to an appropriate value +// // bool expected = false; // TODO: Initialize to an appropriate value +// // bool actual; +// // target.Initialize = expected; +// // actual = target.Initialize; +// // Assert.AreEqual(expected, actual); +// // Assert.Inconclusive("Verify the correctness of this test method."); +// //} - ///// - /////A test for Silent - ///// - //[TestMethod()] - //public void SilentTest() - //{ - // ApplicationTree target = new ApplicationTree(); // TODO: Initialize to an appropriate value - // bool expected = false; // TODO: Initialize to an appropriate value - // bool actual; - // target.Silent = expected; - // actual = target.Silent; - // Assert.AreEqual(expected, actual); - // Assert.Inconclusive("Verify the correctness of this test method."); - //} +// ///// +// /////A test for Silent +// ///// +// //[TestMethod()] +// //public void SilentTest() +// //{ +// // ApplicationTree target = new ApplicationTree(); // TODO: Initialize to an appropriate value +// // bool expected = false; // TODO: Initialize to an appropriate value +// // bool actual; +// // target.Silent = expected; +// // actual = target.Silent; +// // Assert.AreEqual(expected, actual); +// // Assert.Inconclusive("Verify the correctness of this test method."); +// //} - ///// - /////A test for SortOrder - ///// - //[TestMethod()] - //public void SortOrderTest() - //{ - // ApplicationTree target = new ApplicationTree(); // TODO: Initialize to an appropriate value - // byte expected = 0; // TODO: Initialize to an appropriate value - // byte actual; - // target.SortOrder = expected; - // actual = target.SortOrder; - // Assert.AreEqual(expected, actual); - // Assert.Inconclusive("Verify the correctness of this test method."); - //} +// ///// +// /////A test for SortOrder +// ///// +// //[TestMethod()] +// //public void SortOrderTest() +// //{ +// // ApplicationTree target = new ApplicationTree(); // TODO: Initialize to an appropriate value +// // byte expected = 0; // TODO: Initialize to an appropriate value +// // byte actual; +// // target.SortOrder = expected; +// // actual = target.SortOrder; +// // Assert.AreEqual(expected, actual); +// // Assert.Inconclusive("Verify the correctness of this test method."); +// //} - ///// - /////A test for SqlHelper - ///// - //[TestMethod()] - //public void SqlHelperTest() - //{ - // ISqlHelper actual; - // actual = ApplicationTree.SqlHelper; - // Assert.Inconclusive("Verify the correctness of this test method."); - //} +// ///// +// /////A test for SqlHelper +// ///// +// //[TestMethod()] +// //public void SqlHelperTest() +// //{ +// // ISqlHelper actual; +// // actual = ApplicationTree.SqlHelper; +// // Assert.Inconclusive("Verify the correctness of this test method."); +// //} - ///// - /////A test for Title - ///// - //[TestMethod()] - //public void TitleTest() - //{ - // ApplicationTree target = new ApplicationTree(); // TODO: Initialize to an appropriate value - // string expected = string.Empty; // TODO: Initialize to an appropriate value - // string actual; - // target.Title = expected; - // actual = target.Title; - // Assert.AreEqual(expected, actual); - // Assert.Inconclusive("Verify the correctness of this test method."); - //} +// ///// +// /////A test for Title +// ///// +// //[TestMethod()] +// //public void TitleTest() +// //{ +// // ApplicationTree target = new ApplicationTree(); // TODO: Initialize to an appropriate value +// // string expected = string.Empty; // TODO: Initialize to an appropriate value +// // string actual; +// // target.Title = expected; +// // actual = target.Title; +// // Assert.AreEqual(expected, actual); +// // Assert.Inconclusive("Verify the correctness of this test method."); +// //} - ///// - /////A test for Type - ///// - //[TestMethod()] - //public void TypeTest() - //{ - // ApplicationTree target = new ApplicationTree(); // TODO: Initialize to an appropriate value - // string expected = string.Empty; // TODO: Initialize to an appropriate value - // string actual; - // target.Type = expected; - // actual = target.Type; - // Assert.AreEqual(expected, actual); - // Assert.Inconclusive("Verify the correctness of this test method."); - //} - #endregion +// ///// +// /////A test for Type +// ///// +// //[TestMethod()] +// //public void TypeTest() +// //{ +// // ApplicationTree target = new ApplicationTree(); // TODO: Initialize to an appropriate value +// // string expected = string.Empty; // TODO: Initialize to an appropriate value +// // string actual; +// // target.Type = expected; +// // actual = target.Type; +// // Assert.AreEqual(expected, actual); +// // Assert.Inconclusive("Verify the correctness of this test method."); +// //} +// #endregion - #region Additional test attributes - // - //You can use the following additional attributes as you write your tests: - // - //Use ClassInitialize to run code before running the first test in the class - //[ClassInitialize()] - //public static void MyClassInitialize(TestContext testContext) - //{ - //} - // - //Use ClassCleanup to run code after all tests in a class have run - //[ClassCleanup()] - //public static void MyClassCleanup() - //{ - //} - // - //Use TestInitialize to run code before running each test - //[TestInitialize()] - //public void MyTestInitialize() - //{ - //} - // - //Use TestCleanup to run code after each test has run - //[TestCleanup()] - //public void MyTestCleanup() - //{ - //} - // - #endregion - } -} +// #region Additional test attributes +// // +// //You can use the following additional attributes as you write your tests: +// // +// //Use ClassInitialize to run code before running the first test in the class +// //[ClassInitialize()] +// //public static void MyClassInitialize(TestContext testContext) +// //{ +// //} +// // +// //Use ClassCleanup to run code after all tests in a class have run +// //[ClassCleanup()] +// //public static void MyClassCleanup() +// //{ +// //} +// // +// //Use TestInitialize to run code before running each test +// //[TestInitialize()] +// //public void MyTestInitialize() +// //{ +// //} +// // +// //Use TestCleanup to run code after each test has run +// //[TestCleanup()] +// //public void MyTestCleanup() +// //{ +// //} +// // +// #endregion +// } +//} diff --git a/src/Umbraco.Tests/TreesAndSections/SectionTests.cs b/src/Umbraco.Tests/TreesAndSections/SectionTests.cs index 1f4a01fd3d..83de6c4479 100644 --- a/src/Umbraco.Tests/TreesAndSections/SectionTests.cs +++ b/src/Umbraco.Tests/TreesAndSections/SectionTests.cs @@ -1,252 +1,252 @@ -using System.IO; -using NUnit.Framework; -using Umbraco.Core.Services; -using Umbraco.Tests.TestHelpers; -using System; -using Umbraco.Core.Composing; -using Umbraco.Tests.Testing; -using Umbraco.Web.Services; +//using System.IO; +//using NUnit.Framework; +//using Umbraco.Core.Services; +//using Umbraco.Tests.TestHelpers; +//using System; +//using Umbraco.Core.Composing; +//using Umbraco.Tests.Testing; +//using Umbraco.Web.Services; -namespace Umbraco.Tests.TreesAndSections -{ - /// - ///This is a test class for ApplicationTest and is intended - ///to contain all ApplicationTest Unit Tests - /// - [TestFixture] - [UmbracoTest(AutoMapper = true, Database = UmbracoTestOptions.Database.NewSchemaPerTest)] - public class SectionTests : TestWithDatabaseBase - { - protected override void Compose() - { - base.Compose(); - Composition.RegisterUnique(); - } +//namespace Umbraco.Tests.TreesAndSections +//{ +// /// +// ///This is a test class for ApplicationTest and is intended +// ///to contain all ApplicationTest Unit Tests +// /// +// [TestFixture] +// [UmbracoTest(AutoMapper = true, Database = UmbracoTestOptions.Database.NewSchemaPerTest)] +// public class SectionTests : TestWithDatabaseBase +// { +// protected override void Compose() +// { +// base.Compose(); +// Composition.RegisterUnique(); +// } - public override void SetUp() - { - base.SetUp(); +// public override void SetUp() +// { +// base.SetUp(); - var treesConfig = TestHelper.MapPathForTest("~/TEMP/TreesAndSections/trees.config"); - var appConfig = TestHelper.MapPathForTest("~/TEMP/TreesAndSections/applications.config"); - Directory.CreateDirectory(TestHelper.MapPathForTest("~/TEMP/TreesAndSections")); - using (var writer = File.CreateText(treesConfig)) - { - writer.Write(ResourceFiles.trees); - } - using (var writer = File.CreateText(appConfig)) - { - writer.Write(ResourceFiles.applications); - } +// var treesConfig = TestHelper.MapPathForTest("~/TEMP/TreesAndSections/trees.config"); +// var appConfig = TestHelper.MapPathForTest("~/TEMP/TreesAndSections/applications.config"); +// Directory.CreateDirectory(TestHelper.MapPathForTest("~/TEMP/TreesAndSections")); +// using (var writer = File.CreateText(treesConfig)) +// { +// writer.Write(ResourceFiles.trees); +// } +// using (var writer = File.CreateText(appConfig)) +// { +// writer.Write(ResourceFiles.applications); +// } - ApplicationTreeService.TreeConfigFilePath = treesConfig; - SectionService.AppConfigFilePath = appConfig; - } +// ApplicationTreeService.TreeConfigFilePath = treesConfig; +// SectionService.AppConfigFilePath = appConfig; +// } - public override void TearDown() - { - base.TearDown(); +// public override void TearDown() +// { +// base.TearDown(); - if (Directory.Exists(TestHelper.MapPathForTest("~/TEMP/TreesAndSections"))) - { - Directory.Delete(TestHelper.MapPathForTest("~/TEMP/TreesAndSections"), true); - } - ApplicationTreeService.TreeConfigFilePath = null; - SectionService.AppConfigFilePath = null; - } +// if (Directory.Exists(TestHelper.MapPathForTest("~/TEMP/TreesAndSections"))) +// { +// Directory.Delete(TestHelper.MapPathForTest("~/TEMP/TreesAndSections"), true); +// } +// ApplicationTreeService.TreeConfigFilePath = null; +// SectionService.AppConfigFilePath = null; +// } - /// - /// Create a new application and delete it - /// - [Test()] - public void Application_Make_New() - { - var name = Guid.NewGuid().ToString("N"); - ServiceContext.SectionService.MakeNew(name, name, "icon.jpg"); +// ///// +// ///// Create a new application and delete it +// ///// +// //[Test()] +// //public void Application_Make_New() +// //{ +// // var name = Guid.NewGuid().ToString("N"); +// // ServiceContext.SectionService.MakeNew(name, name, "icon.jpg"); - //check if it exists - var app = ServiceContext.SectionService.GetByAlias(name); - Assert.IsNotNull(app); +// // //check if it exists +// // var app = ServiceContext.SectionService.GetByAlias(name); +// // Assert.IsNotNull(app); - //now remove it - ServiceContext.SectionService.DeleteSection(app); - Assert.IsNull(ServiceContext.SectionService.GetByAlias(name)); - } +// // //now remove it +// // ServiceContext.SectionService.DeleteSection(app); +// // Assert.IsNull(ServiceContext.SectionService.GetByAlias(name)); +// //} - #region Tests to write +// #region Tests to write - ///// - /////A test for Application Constructor - ///// - //[TestMethod()] - //public void ApplicationConstructorTest() - //{ - // string name = string.Empty; // TODO: Initialize to an appropriate value - // string alias = string.Empty; // TODO: Initialize to an appropriate value - // string icon = string.Empty; // TODO: Initialize to an appropriate value - // Application target = new Application(name, alias, icon); - // Assert.Inconclusive("TODO: Implement code to verify target"); - //} +// ///// +// /////A test for Application Constructor +// ///// +// //[TestMethod()] +// //public void ApplicationConstructorTest() +// //{ +// // string name = string.Empty; // TODO: Initialize to an appropriate value +// // string alias = string.Empty; // TODO: Initialize to an appropriate value +// // string icon = string.Empty; // TODO: Initialize to an appropriate value +// // Application target = new Application(name, alias, icon); +// // Assert.Inconclusive("TODO: Implement code to verify target"); +// //} - ///// - /////A test for Application Constructor - ///// - //[TestMethod()] - //public void ApplicationConstructorTest1() - //{ - // Application target = new Application(); - // Assert.Inconclusive("TODO: Implement code to verify target"); - //} +// ///// +// /////A test for Application Constructor +// ///// +// //[TestMethod()] +// //public void ApplicationConstructorTest1() +// //{ +// // Application target = new Application(); +// // Assert.Inconclusive("TODO: Implement code to verify target"); +// //} - ///// - /////A test for Delete - ///// - //[TestMethod()] - //public void DeleteTest() - //{ - // Application target = new Application(); // TODO: Initialize to an appropriate value - // target.Delete(); - // Assert.Inconclusive("A method that does not return a value cannot be verified."); - //} +// ///// +// /////A test for Delete +// ///// +// //[TestMethod()] +// //public void DeleteTest() +// //{ +// // Application target = new Application(); // TODO: Initialize to an appropriate value +// // target.Delete(); +// // Assert.Inconclusive("A method that does not return a value cannot be verified."); +// //} - ///// - /////A test for MakeNew - ///// - //[TestMethod()] - //public void MakeNewTest1() - //{ - // string name = string.Empty; // TODO: Initialize to an appropriate value - // string alias = string.Empty; // TODO: Initialize to an appropriate value - // string icon = string.Empty; // TODO: Initialize to an appropriate value - // Application.MakeNew(name, alias, icon); - // Assert.Inconclusive("A method that does not return a value cannot be verified."); - //} +// ///// +// /////A test for MakeNew +// ///// +// //[TestMethod()] +// //public void MakeNewTest1() +// //{ +// // string name = string.Empty; // TODO: Initialize to an appropriate value +// // string alias = string.Empty; // TODO: Initialize to an appropriate value +// // string icon = string.Empty; // TODO: Initialize to an appropriate value +// // Application.MakeNew(name, alias, icon); +// // Assert.Inconclusive("A method that does not return a value cannot be verified."); +// //} - ///// - /////A test for RegisterIApplications - ///// - //[TestMethod()] - //public void RegisterIApplicationsTest() - //{ - // Application.RegisterIApplications(); - // Assert.Inconclusive("A method that does not return a value cannot be verified."); - //} +// ///// +// /////A test for RegisterIApplications +// ///// +// //[TestMethod()] +// //public void RegisterIApplicationsTest() +// //{ +// // Application.RegisterIApplications(); +// // Assert.Inconclusive("A method that does not return a value cannot be verified."); +// //} - ///// - /////A test for getAll - ///// - //[TestMethod()] - //public void getAllTest() - //{ - // List expected = null; // TODO: Initialize to an appropriate value - // List actual; - // actual = Application.getAll(); - // Assert.AreEqual(expected, actual); - // Assert.Inconclusive("Verify the correctness of this test method."); - //} +// ///// +// /////A test for getAll +// ///// +// //[TestMethod()] +// //public void getAllTest() +// //{ +// // List expected = null; // TODO: Initialize to an appropriate value +// // List actual; +// // actual = Application.getAll(); +// // Assert.AreEqual(expected, actual); +// // Assert.Inconclusive("Verify the correctness of this test method."); +// //} - ///// - /////A test for getByAlias - ///// - //[TestMethod()] - //public void getByAliasTest() - //{ - // string appAlias = string.Empty; // TODO: Initialize to an appropriate value - // Application expected = null; // TODO: Initialize to an appropriate value - // Application actual; - // actual = Application.getByAlias(appAlias); - // Assert.AreEqual(expected, actual); - // Assert.Inconclusive("Verify the correctness of this test method."); - //} +// ///// +// /////A test for getByAlias +// ///// +// //[TestMethod()] +// //public void getByAliasTest() +// //{ +// // string appAlias = string.Empty; // TODO: Initialize to an appropriate value +// // Application expected = null; // TODO: Initialize to an appropriate value +// // Application actual; +// // actual = Application.getByAlias(appAlias); +// // Assert.AreEqual(expected, actual); +// // Assert.Inconclusive("Verify the correctness of this test method."); +// //} - ///// - /////A test for SqlHelper - ///// - //[TestMethod()] - //public void SqlHelperTest() - //{ - // ISqlHelper actual; - // actual = Application.SqlHelper; - // Assert.Inconclusive("Verify the correctness of this test method."); - //} +// ///// +// /////A test for SqlHelper +// ///// +// //[TestMethod()] +// //public void SqlHelperTest() +// //{ +// // ISqlHelper actual; +// // actual = Application.SqlHelper; +// // Assert.Inconclusive("Verify the correctness of this test method."); +// //} - ///// - /////A test for alias - ///// - //[TestMethod()] - //public void aliasTest() - //{ - // Application target = new Application(); // TODO: Initialize to an appropriate value - // string expected = string.Empty; // TODO: Initialize to an appropriate value - // string actual; - // target.alias = expected; - // actual = target.alias; - // Assert.AreEqual(expected, actual); - // Assert.Inconclusive("Verify the correctness of this test method."); - //} +// ///// +// /////A test for alias +// ///// +// //[TestMethod()] +// //public void aliasTest() +// //{ +// // Application target = new Application(); // TODO: Initialize to an appropriate value +// // string expected = string.Empty; // TODO: Initialize to an appropriate value +// // string actual; +// // target.alias = expected; +// // actual = target.alias; +// // Assert.AreEqual(expected, actual); +// // Assert.Inconclusive("Verify the correctness of this test method."); +// //} - ///// - /////A test for icon - ///// - //[TestMethod()] - //public void iconTest() - //{ - // Application target = new Application(); // TODO: Initialize to an appropriate value - // string expected = string.Empty; // TODO: Initialize to an appropriate value - // string actual; - // target.icon = expected; - // actual = target.icon; - // Assert.AreEqual(expected, actual); - // Assert.Inconclusive("Verify the correctness of this test method."); - //} +// ///// +// /////A test for icon +// ///// +// //[TestMethod()] +// //public void iconTest() +// //{ +// // Application target = new Application(); // TODO: Initialize to an appropriate value +// // string expected = string.Empty; // TODO: Initialize to an appropriate value +// // string actual; +// // target.icon = expected; +// // actual = target.icon; +// // Assert.AreEqual(expected, actual); +// // Assert.Inconclusive("Verify the correctness of this test method."); +// //} - ///// - /////A test for name - ///// - //[TestMethod()] - //public void nameTest() - //{ - // Application target = new Application(); // TODO: Initialize to an appropriate value - // string expected = string.Empty; // TODO: Initialize to an appropriate value - // string actual; - // target.name = expected; - // actual = target.name; - // Assert.AreEqual(expected, actual); - // Assert.Inconclusive("Verify the correctness of this test method."); - //} - #endregion +// ///// +// /////A test for name +// ///// +// //[TestMethod()] +// //public void nameTest() +// //{ +// // Application target = new Application(); // TODO: Initialize to an appropriate value +// // string expected = string.Empty; // TODO: Initialize to an appropriate value +// // string actual; +// // target.name = expected; +// // actual = target.name; +// // Assert.AreEqual(expected, actual); +// // Assert.Inconclusive("Verify the correctness of this test method."); +// //} +// #endregion - #region Additional test attributes - // - //You can use the following additional attributes as you write your tests: - // - //Use ClassInitialize to run code before running the first test in the class - //[ClassInitialize()] - //public static void MyClassInitialize(TestContext testContext) - //{ - //} - // - //Use ClassCleanup to run code after all tests in a class have run - //[ClassCleanup()] - //public static void MyClassCleanup() - //{ - //} - // - //Use TestInitialize to run code before running each test - //[TestInitialize()] - //public void MyTestInitialize() - //{ - //} - // - //Use TestCleanup to run code after each test has run - //[TestCleanup()] - //public void MyTestCleanup() - //{ - //} - // - #endregion - } -} +// #region Additional test attributes +// // +// //You can use the following additional attributes as you write your tests: +// // +// //Use ClassInitialize to run code before running the first test in the class +// //[ClassInitialize()] +// //public static void MyClassInitialize(TestContext testContext) +// //{ +// //} +// // +// //Use ClassCleanup to run code after all tests in a class have run +// //[ClassCleanup()] +// //public static void MyClassCleanup() +// //{ +// //} +// // +// //Use TestInitialize to run code before running each test +// //[TestInitialize()] +// //public void MyTestInitialize() +// //{ +// //} +// // +// //Use TestCleanup to run code after each test has run +// //[TestCleanup()] +// //public void MyTestCleanup() +// //{ +// //} +// // +// #endregion +// } +//} diff --git a/src/Umbraco.Web/Cache/ApplicationTreeCacheRefresher.cs b/src/Umbraco.Web/Cache/ApplicationTreeCacheRefresher.cs index 247c33c361..4d6740a0b1 100644 --- a/src/Umbraco.Web/Cache/ApplicationTreeCacheRefresher.cs +++ b/src/Umbraco.Web/Cache/ApplicationTreeCacheRefresher.cs @@ -1,46 +1,46 @@ -using System; -using Umbraco.Core.Cache; +//using System; +//using Umbraco.Core.Cache; -namespace Umbraco.Web.Cache -{ - public sealed class ApplicationTreeCacheRefresher : CacheRefresherBase - { - public ApplicationTreeCacheRefresher(CacheHelper cacheHelper) - : base(cacheHelper) - { } +//namespace Umbraco.Web.Cache +//{ +// public sealed class ApplicationTreeCacheRefresher : CacheRefresherBase +// { +// public ApplicationTreeCacheRefresher(CacheHelper cacheHelper) +// : base(cacheHelper) +// { } - #region Define +// #region Define - protected override ApplicationTreeCacheRefresher This => this; +// protected override ApplicationTreeCacheRefresher This => this; - public static readonly Guid UniqueId = Guid.Parse("0AC6C028-9860-4EA4-958D-14D39F45886E"); +// public static readonly Guid UniqueId = Guid.Parse("0AC6C028-9860-4EA4-958D-14D39F45886E"); - public override Guid RefresherUniqueId => UniqueId; +// public override Guid RefresherUniqueId => UniqueId; - public override string Name => "Application Tree Cache Refresher"; +// public override string Name => "Application Tree Cache Refresher"; - #endregion +// #endregion - #region Refresher +// #region Refresher - public override void RefreshAll() - { - CacheHelper.RuntimeCache.ClearCacheItem(CacheKeys.ApplicationTreeCacheKey); - base.RefreshAll(); - } +// public override void RefreshAll() +// { +// CacheHelper.RuntimeCache.ClearCacheItem(CacheKeys.ApplicationTreeCacheKey); +// base.RefreshAll(); +// } - public override void Refresh(int id) - { - Remove(id); - base.Refresh(id); - } +// public override void Refresh(int id) +// { +// Remove(id); +// base.Refresh(id); +// } - public override void Remove(int id) - { - CacheHelper.RuntimeCache.ClearCacheItem(CacheKeys.ApplicationTreeCacheKey); - base.Remove(id); - } +// public override void Remove(int id) +// { +// CacheHelper.RuntimeCache.ClearCacheItem(CacheKeys.ApplicationTreeCacheKey); +// base.Remove(id); +// } - #endregion - } -} +// #endregion +// } +//} diff --git a/src/Umbraco.Web/Cache/DistributedCacheBinder_Handlers.cs b/src/Umbraco.Web/Cache/DistributedCacheBinder_Handlers.cs index d522e54de6..421eb546a4 100644 --- a/src/Umbraco.Web/Cache/DistributedCacheBinder_Handlers.cs +++ b/src/Umbraco.Web/Cache/DistributedCacheBinder_Handlers.cs @@ -46,19 +46,19 @@ namespace Umbraco.Web.Cache _logger.Info("Initializing Umbraco internal event handlers for cache refreshing."); - // bind to application tree events - Bind(() => ApplicationTreeService.Deleted += ApplicationTreeService_Deleted, - () => ApplicationTreeService.Deleted -= ApplicationTreeService_Deleted); - Bind(() => ApplicationTreeService.Updated += ApplicationTreeService_Updated, - () => ApplicationTreeService.Updated -= ApplicationTreeService_Updated); - Bind(() => ApplicationTreeService.New += ApplicationTreeService_New, - () => ApplicationTreeService.New -= ApplicationTreeService_New); + //// bind to application tree events + //Bind(() => ApplicationTreeService.Deleted += ApplicationTreeService_Deleted, + // () => ApplicationTreeService.Deleted -= ApplicationTreeService_Deleted); + //Bind(() => ApplicationTreeService.Updated += ApplicationTreeService_Updated, + // () => ApplicationTreeService.Updated -= ApplicationTreeService_Updated); + //Bind(() => ApplicationTreeService.New += ApplicationTreeService_New, + // () => ApplicationTreeService.New -= ApplicationTreeService_New); - // bind to application events - Bind(() => SectionService.Deleted += SectionService_Deleted, - () => SectionService.Deleted -= SectionService_Deleted); - Bind(() => SectionService.New += SectionService_New, - () => SectionService.New -= SectionService_New); + //// bind to application events + //Bind(() => SectionService.Deleted += SectionService_Deleted, + // () => SectionService.Deleted -= SectionService_Deleted); + //Bind(() => SectionService.New += SectionService_New, + // () => SectionService.New -= SectionService_New); // bind to user and user group events Bind(() => UserService.SavedUserGroup += UserService_SavedUserGroup, @@ -231,38 +231,38 @@ namespace Umbraco.Web.Cache #endregion - #region ApplicationTreeService + //#region ApplicationTreeService - private void ApplicationTreeService_New(ApplicationTree sender, EventArgs e) - { - _distributedCache.RefreshAllApplicationTreeCache(); - } + //private void ApplicationTreeService_New(ApplicationTree sender, EventArgs e) + //{ + // _distributedCache.RefreshAllApplicationTreeCache(); + //} - private void ApplicationTreeService_Updated(ApplicationTree sender, EventArgs e) - { - _distributedCache.RefreshAllApplicationTreeCache(); - } + //private void ApplicationTreeService_Updated(ApplicationTree sender, EventArgs e) + //{ + // _distributedCache.RefreshAllApplicationTreeCache(); + //} - private void ApplicationTreeService_Deleted(ApplicationTree sender, EventArgs e) - { - _distributedCache.RefreshAllApplicationTreeCache(); - } + //private void ApplicationTreeService_Deleted(ApplicationTree sender, EventArgs e) + //{ + // _distributedCache.RefreshAllApplicationTreeCache(); + //} - #endregion + //#endregion - #region Application event handlers + //#region Application event handlers - private void SectionService_New(ISectionService sender, EventArgs e) - { - _distributedCache.RefreshAllApplicationCache(); - } + //private void SectionService_New(ISectionService sender, EventArgs e) + //{ + // _distributedCache.RefreshAllApplicationCache(); + //} - private void SectionService_Deleted(ISectionService sender, EventArgs e) - { - _distributedCache.RefreshAllApplicationCache(); - } + //private void SectionService_Deleted(ISectionService sender, EventArgs e) + //{ + // _distributedCache.RefreshAllApplicationCache(); + //} - #endregion + //#endregion #region LocalizationService / Dictionary diff --git a/src/Umbraco.Web/Cache/DistributedCacheExtensions.cs b/src/Umbraco.Web/Cache/DistributedCacheExtensions.cs index 68ac339a46..aab0f9b157 100644 --- a/src/Umbraco.Web/Cache/DistributedCacheExtensions.cs +++ b/src/Umbraco.Web/Cache/DistributedCacheExtensions.cs @@ -18,23 +18,23 @@ namespace Umbraco.Web.Cache #endregion - #region ApplicationTreeCache + //#region ApplicationTreeCache - public static void RefreshAllApplicationTreeCache(this DistributedCache dc) - { - dc.RefreshAll(ApplicationTreeCacheRefresher.UniqueId); - } + //public static void RefreshAllApplicationTreeCache(this DistributedCache dc) + //{ + // dc.RefreshAll(ApplicationTreeCacheRefresher.UniqueId); + //} - #endregion + //#endregion - #region ApplicationCache + //#region ApplicationCache - public static void RefreshAllApplicationCache(this DistributedCache dc) - { - dc.RefreshAll(ApplicationCacheRefresher.UniqueId); - } + //public static void RefreshAllApplicationCache(this DistributedCache dc) + //{ + // dc.RefreshAll(ApplicationCacheRefresher.UniqueId); + //} - #endregion + //#endregion #region User cache diff --git a/src/Umbraco.Web/TagsController.cs b/src/Umbraco.Web/Controllers/TagsController.cs similarity index 89% rename from src/Umbraco.Web/TagsController.cs rename to src/Umbraco.Web/Controllers/TagsController.cs index 181b9f7da2..cb6a28be47 100644 --- a/src/Umbraco.Web/TagsController.cs +++ b/src/Umbraco.Web/Controllers/TagsController.cs @@ -8,7 +8,7 @@ using Umbraco.Core.Services; using Umbraco.Web.Models; using Umbraco.Web.WebApi; -namespace Umbraco.Web.WebServices +namespace Umbraco.Web.Controllers { /// /// A public web service for querying tags @@ -29,8 +29,8 @@ namespace Umbraco.Web.WebServices /// /// Initializes a new instance of the with all its dependencies. /// - public TagsController(IGlobalSettings globalSettings, IUmbracoContextAccessor umbracoContextAccessor, ISqlContext sqlContext, ServiceContext services, CacheHelper applicationCache, IProfilingLogger logger, IRuntimeState runtimeState) - : base(globalSettings, umbracoContextAccessor, sqlContext, services, applicationCache, logger, runtimeState) + public TagsController(IGlobalSettings globalSettings, UmbracoContext umbracoContext, ISqlContext sqlContext, ServiceContext services, CacheHelper applicationCache, IProfilingLogger logger, IRuntimeState runtimeState) + : base(globalSettings, umbracoContext, sqlContext, services, applicationCache, logger, runtimeState) { } /// diff --git a/src/Umbraco.Web/Editors/AuthenticationController.cs b/src/Umbraco.Web/Editors/AuthenticationController.cs index 231ec9ba67..7ffc6e1207 100644 --- a/src/Umbraco.Web/Editors/AuthenticationController.cs +++ b/src/Umbraco.Web/Editors/AuthenticationController.cs @@ -52,8 +52,8 @@ namespace Umbraco.Web.Editors /// /// Initializes a new instance of the class with all its dependencies. /// - public AuthenticationController(IGlobalSettings globalSettings, IUmbracoContextAccessor umbracoContextAccessor, ISqlContext sqlContext, ServiceContext services, CacheHelper applicationCache, IProfilingLogger logger, IRuntimeState runtimeState) - : base(globalSettings, umbracoContextAccessor, sqlContext, services, applicationCache, logger, runtimeState) + public AuthenticationController(IGlobalSettings globalSettings, UmbracoContext umbracoContext, ISqlContext sqlContext, ServiceContext services, CacheHelper applicationCache, IProfilingLogger logger, IRuntimeState runtimeState) + : base(globalSettings, umbracoContext, sqlContext, services, applicationCache, logger, runtimeState) { } protected BackOfficeUserManager UserManager => _userManager diff --git a/src/Umbraco.Web/Editors/BackOfficeServerVariables.cs b/src/Umbraco.Web/Editors/BackOfficeServerVariables.cs index ee973a4b58..65ab27d76a 100644 --- a/src/Umbraco.Web/Editors/BackOfficeServerVariables.cs +++ b/src/Umbraco.Web/Editors/BackOfficeServerVariables.cs @@ -14,13 +14,13 @@ using Umbraco.Core.Composing; using Umbraco.Core.Configuration; using Umbraco.Core.Configuration.UmbracoSettings; using Umbraco.Core.IO; +using Umbraco.Web.Controllers; using Umbraco.Web.Features; using Umbraco.Web.HealthCheck; using Umbraco.Web.Models.ContentEditing; using Umbraco.Web.Mvc; using Umbraco.Web.PropertyEditors; using Umbraco.Web.Trees; -using Umbraco.Web.WebServices; using Constants = Umbraco.Core.Constants; namespace Umbraco.Web.Editors @@ -158,7 +158,7 @@ namespace Umbraco.Web.Editors }, { "treeApplicationApiBaseUrl", _urlHelper.GetUmbracoApiServiceBaseUrl( - controller => controller.GetApplicationTrees(null, null, null, true)) + controller => controller.GetApplicationTrees(null, null, null)) }, { "contentTypeApiBaseUrl", _urlHelper.GetUmbracoApiServiceBaseUrl( diff --git a/src/Umbraco.Web/Editors/ContentTypeController.cs b/src/Umbraco.Web/Editors/ContentTypeController.cs index 670d37e7a7..00a0cb90bc 100644 --- a/src/Umbraco.Web/Editors/ContentTypeController.cs +++ b/src/Umbraco.Web/Editors/ContentTypeController.cs @@ -54,11 +54,11 @@ namespace Umbraco.Web.Editors public ContentTypeController(IEntityXmlSerializer serializer, ICultureDictionaryFactory cultureDictionaryFactory, IGlobalSettings globalSettings, - IUmbracoContextAccessor umbracoContextAccessor, + UmbracoContext umbracoContext, ISqlContext sqlContext, PropertyEditorCollection propertyEditors, ServiceContext services, CacheHelper applicationCache, IProfilingLogger logger, IRuntimeState runtimeState) - : base(cultureDictionaryFactory, globalSettings, umbracoContextAccessor, sqlContext, services, applicationCache, logger, runtimeState) + : base(cultureDictionaryFactory, globalSettings, umbracoContext, sqlContext, services, applicationCache, logger, runtimeState) { _serializer = serializer; _propertyEditors = propertyEditors; diff --git a/src/Umbraco.Web/Editors/ContentTypeControllerBase.cs b/src/Umbraco.Web/Editors/ContentTypeControllerBase.cs index 898208319a..a11fcaa869 100644 --- a/src/Umbraco.Web/Editors/ContentTypeControllerBase.cs +++ b/src/Umbraco.Web/Editors/ContentTypeControllerBase.cs @@ -33,7 +33,8 @@ namespace Umbraco.Web.Editors private readonly ICultureDictionaryFactory _cultureDictionaryFactory; private ICultureDictionary _cultureDictionary; - protected ContentTypeControllerBase(ICultureDictionaryFactory cultureDictionaryFactory, IGlobalSettings globalSettings, IUmbracoContextAccessor umbracoContextAccessor, ISqlContext sqlContext, ServiceContext services, CacheHelper applicationCache, IProfilingLogger logger, IRuntimeState runtimeState) : base(globalSettings, umbracoContextAccessor, sqlContext, services, applicationCache, logger, runtimeState) + protected ContentTypeControllerBase(ICultureDictionaryFactory cultureDictionaryFactory, IGlobalSettings globalSettings, UmbracoContext umbracoContext, ISqlContext sqlContext, ServiceContext services, CacheHelper applicationCache, IProfilingLogger logger, IRuntimeState runtimeState) + : base(globalSettings, umbracoContext, sqlContext, services, applicationCache, logger, runtimeState) { _cultureDictionaryFactory = cultureDictionaryFactory; } diff --git a/src/Umbraco.Web/Editors/DashboardController.cs b/src/Umbraco.Web/Editors/DashboardController.cs index 8960f110c3..0340926ce4 100644 --- a/src/Umbraco.Web/Editors/DashboardController.cs +++ b/src/Umbraco.Web/Editors/DashboardController.cs @@ -38,8 +38,8 @@ namespace Umbraco.Web.Editors /// /// Initializes a new instance of the with all its dependencies. /// - public DashboardController(IGlobalSettings globalSettings, IUmbracoContextAccessor umbracoContextAccessor, ISqlContext sqlContext, ServiceContext services, CacheHelper applicationCache, IProfilingLogger logger, IRuntimeState runtimeState, Dashboards dashboards) - : base(globalSettings, umbracoContextAccessor, sqlContext, services, applicationCache, logger, runtimeState) + public DashboardController(IGlobalSettings globalSettings, UmbracoContext umbracoContext, ISqlContext sqlContext, ServiceContext services, CacheHelper applicationCache, IProfilingLogger logger, IRuntimeState runtimeState, Dashboards dashboards) + : base(globalSettings, umbracoContext, sqlContext, services, applicationCache, logger, runtimeState) { _dashboards = dashboards; } diff --git a/src/Umbraco.Web/Editors/DashboardSecurity.cs b/src/Umbraco.Web/Editors/DashboardSecurity.cs index 1481606c7e..fdbf5af7d9 100644 --- a/src/Umbraco.Web/Editors/DashboardSecurity.cs +++ b/src/Umbraco.Web/Editors/DashboardSecurity.cs @@ -6,6 +6,7 @@ using Umbraco.Core; using Umbraco.Core.Configuration.Dashboard; using Umbraco.Core.Models.Membership; using Umbraco.Core.Services; +using Umbraco.Web.Services; namespace Umbraco.Web.Editors { diff --git a/src/Umbraco.Web/Editors/Dashboards.cs b/src/Umbraco.Web/Editors/Dashboards.cs index 4bf2d81045..c837cbbf33 100644 --- a/src/Umbraco.Web/Editors/Dashboards.cs +++ b/src/Umbraco.Web/Editors/Dashboards.cs @@ -8,6 +8,7 @@ using Umbraco.Core.Manifest; using Umbraco.Core.Models.Membership; using Umbraco.Core.Services; using Umbraco.Web.Models.ContentEditing; +using Umbraco.Web.Services; namespace Umbraco.Web.Editors { diff --git a/src/Umbraco.Web/Editors/EntityController.cs b/src/Umbraco.Web/Editors/EntityController.cs index 993489855f..c8368d11b0 100644 --- a/src/Umbraco.Web/Editors/EntityController.cs +++ b/src/Umbraco.Web/Editors/EntityController.cs @@ -16,11 +16,16 @@ using Constants = Umbraco.Core.Constants; using Umbraco.Core.Persistence.DatabaseModelDefinitions; using System.Web.Http.Controllers; using Examine; +using Umbraco.Core.Cache; +using Umbraco.Core.Configuration; +using Umbraco.Core.Logging; using Umbraco.Core.Models.Entities; +using Umbraco.Core.Persistence; using Umbraco.Core.Services; using Umbraco.Core.Xml; using Umbraco.Web.Models.Mapping; using Umbraco.Web.Search; +using Umbraco.Web.Services; using Umbraco.Web.Trees; using Umbraco.Web.WebApi; using Umbraco.Web.WebApi.Filters; @@ -37,6 +42,15 @@ namespace Umbraco.Web.Editors [PluginController("UmbracoApi")] public class EntityController : UmbracoAuthorizedJsonController { + private readonly IApplicationTreeService _treeService; + + public EntityController(IGlobalSettings globalSettings, UmbracoContext umbracoContext, ISqlContext sqlContext, ServiceContext services, CacheHelper applicationCache, IProfilingLogger logger, IRuntimeState runtimeState, + IApplicationTreeService treeService) + : base(globalSettings, umbracoContext, sqlContext, services, applicationCache, logger, runtimeState) + { + _treeService = treeService; + } + /// /// Configures this controller with a custom action selector /// @@ -129,7 +143,7 @@ namespace Umbraco.Web.Editors { if (allowedSections.Contains(searchableTree.Value.AppAlias)) { - var tree = Services.ApplicationTreeService.GetByAlias(searchableTree.Key); + var tree = _treeService.GetByAlias(searchableTree.Key); if (tree == null) continue; //shouldn't occur var searchableTreeAttribute = searchableTree.Value.SearchableTree.GetType().GetCustomAttribute(false); diff --git a/src/Umbraco.Web/Editors/MediaTypeController.cs b/src/Umbraco.Web/Editors/MediaTypeController.cs index f2b8fd3dda..e2fbe8c428 100644 --- a/src/Umbraco.Web/Editors/MediaTypeController.cs +++ b/src/Umbraco.Web/Editors/MediaTypeController.cs @@ -37,7 +37,8 @@ namespace Umbraco.Web.Editors [MediaTypeControllerControllerConfiguration] public class MediaTypeController : ContentTypeControllerBase { - public MediaTypeController(ICultureDictionaryFactory cultureDictionaryFactory, IGlobalSettings globalSettings, IUmbracoContextAccessor umbracoContextAccessor, ISqlContext sqlContext, ServiceContext services, CacheHelper applicationCache, IProfilingLogger logger, IRuntimeState runtimeState) : base(cultureDictionaryFactory, globalSettings, umbracoContextAccessor, sqlContext, services, applicationCache, logger, runtimeState) + public MediaTypeController(ICultureDictionaryFactory cultureDictionaryFactory, IGlobalSettings globalSettings, UmbracoContext umbracoContext, ISqlContext sqlContext, ServiceContext services, CacheHelper applicationCache, IProfilingLogger logger, IRuntimeState runtimeState) + : base(cultureDictionaryFactory, globalSettings, umbracoContext, sqlContext, services, applicationCache, logger, runtimeState) { } diff --git a/src/Umbraco.Web/Editors/MemberTypeController.cs b/src/Umbraco.Web/Editors/MemberTypeController.cs index 3abc0035d3..c59bf6d332 100644 --- a/src/Umbraco.Web/Editors/MemberTypeController.cs +++ b/src/Umbraco.Web/Editors/MemberTypeController.cs @@ -30,7 +30,8 @@ namespace Umbraco.Web.Editors [UmbracoTreeAuthorize(new string[] { Constants.Trees.MemberTypes, Constants.Trees.Members})] public class MemberTypeController : ContentTypeControllerBase { - public MemberTypeController(ICultureDictionaryFactory cultureDictionaryFactory, IGlobalSettings globalSettings, IUmbracoContextAccessor umbracoContextAccessor, ISqlContext sqlContext, ServiceContext services, CacheHelper applicationCache, IProfilingLogger logger, IRuntimeState runtimeState) : base(cultureDictionaryFactory, globalSettings, umbracoContextAccessor, sqlContext, services, applicationCache, logger, runtimeState) + public MemberTypeController(ICultureDictionaryFactory cultureDictionaryFactory, IGlobalSettings globalSettings, UmbracoContext umbracoContext, ISqlContext sqlContext, ServiceContext services, CacheHelper applicationCache, IProfilingLogger logger, IRuntimeState runtimeState) + : base(cultureDictionaryFactory, globalSettings, umbracoContext, sqlContext, services, applicationCache, logger, runtimeState) { } diff --git a/src/Umbraco.Web/Editors/PackageInstallController.cs b/src/Umbraco.Web/Editors/PackageInstallController.cs index 05d1e2a7a3..ec81b794a1 100644 --- a/src/Umbraco.Web/Editors/PackageInstallController.cs +++ b/src/Umbraco.Web/Editors/PackageInstallController.cs @@ -44,10 +44,10 @@ namespace Umbraco.Web.Editors [UmbracoApplicationAuthorize(Core.Constants.Applications.Packages)] public class PackageInstallController : UmbracoAuthorizedJsonController { - public PackageInstallController(IGlobalSettings globalSettings, IUmbracoContextAccessor umbracoContextAccessor, + public PackageInstallController(IGlobalSettings globalSettings, UmbracoContext umbracoContext, ISqlContext sqlContext, ServiceContext services, CacheHelper applicationCache, IProfilingLogger logger, IRuntimeState runtimeState) - : base(globalSettings, umbracoContextAccessor, sqlContext, services, applicationCache, logger, runtimeState) + : base(globalSettings, umbracoContext, sqlContext, services, applicationCache, logger, runtimeState) { } diff --git a/src/Umbraco.Web/Editors/SectionController.cs b/src/Umbraco.Web/Editors/SectionController.cs index f650c18fb3..7b484b09b1 100644 --- a/src/Umbraco.Web/Editors/SectionController.cs +++ b/src/Umbraco.Web/Editors/SectionController.cs @@ -2,10 +2,17 @@ using AutoMapper; using Umbraco.Web.Mvc; using System.Linq; +using Umbraco.Core; +using Umbraco.Core.Cache; +using Umbraco.Core.Configuration; +using Umbraco.Core.Logging; using Umbraco.Core.Models; +using Umbraco.Core.Persistence; +using Umbraco.Core.Services; using Umbraco.Web.Trees; using Section = Umbraco.Web.Models.ContentEditing.Section; using Umbraco.Web.Models.Trees; +using Umbraco.Web.Services; namespace Umbraco.Web.Editors { @@ -16,21 +23,32 @@ namespace Umbraco.Web.Editors public class SectionController : UmbracoAuthorizedJsonController { private readonly Dashboards _dashboards; + private readonly ISectionService _sectionService; + private readonly TreeControllerResolver _treeControllerResolver; + private readonly IApplicationTreeService _treeService; - public SectionController(Dashboards dashboards) + public SectionController(IGlobalSettings globalSettings, UmbracoContext umbracoContext, ISqlContext sqlContext, ServiceContext services, CacheHelper applicationCache, IProfilingLogger logger, IRuntimeState runtimeState, + Dashboards dashboards, ISectionService sectionService, TreeControllerResolver treeControllerResolver, IApplicationTreeService treeService) + : base(globalSettings, umbracoContext, sqlContext, services, applicationCache, logger, runtimeState) { _dashboards = dashboards; + _sectionService = sectionService; + _treeControllerResolver = treeControllerResolver; + _treeService = treeService; } public IEnumerable
GetSections() { - var sections = Services.SectionService.GetAllowedSections(Security.GetUserId().ResultOr(0)); + var sections = _sectionService.GetAllowedSections(Security.GetUserId().ResultOr(0)); - var sectionModels = sections.Select(Mapper.Map).ToArray(); + var sectionModels = sections.Select(Mapper.Map
).ToArray(); // this is a bit nasty since we'll be proxying via the app tree controller but we sort of have to do that // since tree's by nature are controllers and require request contextual data - var appTreeController = new ApplicationTreeController { ControllerContext = ControllerContext }; + var appTreeController = new ApplicationTreeController(GlobalSettings, UmbracoContext, SqlContext, Services, ApplicationCache, Logger, RuntimeState, _treeControllerResolver, _treeService) + { + ControllerContext = ControllerContext + }; var dashboards = _dashboards.GetDashboards(Security.CurrentUser); @@ -76,8 +94,8 @@ namespace Umbraco.Web.Editors /// public IEnumerable
GetAllSections() { - var sections = Services.SectionService.GetSections(); - var mapped = sections.Select(Mapper.Map); + var sections = _sectionService.GetSections(); + var mapped = sections.Select(Mapper.Map
); if (Security.CurrentUser.IsAdmin()) return mapped; diff --git a/src/Umbraco.Web/Editors/UmbracoAuthorizedJsonController.cs b/src/Umbraco.Web/Editors/UmbracoAuthorizedJsonController.cs index 3baa5e85ff..4e430b833c 100644 --- a/src/Umbraco.Web/Editors/UmbracoAuthorizedJsonController.cs +++ b/src/Umbraco.Web/Editors/UmbracoAuthorizedJsonController.cs @@ -31,13 +31,13 @@ namespace Umbraco.Web.Editors /// Initializes a new instance of the class with all its dependencies. ///
/// - /// + /// /// /// /// /// /// - protected UmbracoAuthorizedJsonController(IGlobalSettings globalSettings, IUmbracoContextAccessor umbracoContextAccessor, ISqlContext sqlContext, ServiceContext services, CacheHelper applicationCache, IProfilingLogger logger, IRuntimeState runtimeState) : base(globalSettings, umbracoContextAccessor, sqlContext, services, applicationCache, logger, runtimeState) + protected UmbracoAuthorizedJsonController(IGlobalSettings globalSettings, UmbracoContext umbracoContext, ISqlContext sqlContext, ServiceContext services, CacheHelper applicationCache, IProfilingLogger logger, IRuntimeState runtimeState) : base(globalSettings, umbracoContext, sqlContext, services, applicationCache, logger, runtimeState) { } } diff --git a/src/Umbraco.Web/Models/ContentEditing/ApplicationTree.cs b/src/Umbraco.Web/Models/ContentEditing/ApplicationTree.cs new file mode 100644 index 0000000000..e9befb0e27 --- /dev/null +++ b/src/Umbraco.Web/Models/ContentEditing/ApplicationTree.cs @@ -0,0 +1,177 @@ +using System; +using System.Diagnostics; +using Umbraco.Core.Services; + +namespace Umbraco.Web.Models.ContentEditing +{ + [DebuggerDisplay("Tree - {Alias} ({ApplicationAlias})")] + public class ApplicationTree + { + //private static readonly ConcurrentDictionary ResolvedTypes = new ConcurrentDictionary(); + + ///// + ///// Initializes a new instance of the class. + ///// + //public ApplicationTree() { } + + ///// + ///// Initializes a new instance of the class. + ///// + ///// if set to true [initialize]. + ///// The sort order. + ///// The application alias. + ///// The tree alias. + ///// The tree title. + ///// The icon closed. + ///// The icon opened. + ///// The tree type. + //public ApplicationTree(bool initialize, int sortOrder, string applicationAlias, string alias, string title, string iconClosed, string iconOpened, string type) + //{ + // //Initialize = initialize; + // SortOrder = sortOrder; + // ApplicationAlias = applicationAlias; + // Alias = alias; + // Title = title; + // IconClosed = iconClosed; + // IconOpened = iconOpened; + // Type = type; + + //} + + public ApplicationTree(int sortOrder, string applicationAlias, string alias, string title) + { + SortOrder = sortOrder; + ApplicationAlias = applicationAlias; + Alias = alias; + Title = title; + } + + ///// + ///// Gets or sets a value indicating whether this should initialize. + ///// + ///// true if initialize; otherwise, false. + //public bool Initialize { get; set; } + + /// + /// Gets or sets the sort order. + /// + /// The sort order. + public int SortOrder { get; set; } + + /// + /// Gets the application alias. + /// + /// The application alias. + public string ApplicationAlias { get; } + + /// + /// Gets the tree alias. + /// + /// The alias. + public string Alias { get; } + + /// + /// Gets or sets the tree title (fallback if the tree alias isn't localized) + /// + /// The title. + public string Title { get; set; } + + ///// + ///// Gets or sets the icon closed. + ///// + ///// The icon closed. + //public string IconClosed { get; set; } + + ///// + ///// Gets or sets the icon opened. + ///// + ///// The icon opened. + //public string IconOpened { get; set; } + + ///// + ///// Gets or sets the tree type assembly name. + ///// + ///// The type. + //public string Type { get; set; } + + /// + /// Returns the localized root node display name + /// + /// + /// + public string GetRootNodeDisplayName(ILocalizedTextService textService) + { + var label = $"[{Alias}]"; + + // try to look up a the localized tree header matching the tree alias + var localizedLabel = textService.Localize("treeHeaders/" + Alias); + + // if the localizedLabel returns [alias] then return the title if it's defined + if (localizedLabel != null && localizedLabel.Equals(label, StringComparison.InvariantCultureIgnoreCase)) + { + if (string.IsNullOrEmpty(Title) == false) + label = Title; + } + else + { + // the localizedLabel translated into something that's not just [alias], so use the translation + label = localizedLabel; + } + + return label; + } + + //private Type _runtimeType; + + ///// + ///// Returns the CLR type based on it's assembly name stored in the config + ///// + ///// + //public Type GetRuntimeType() + //{ + // return _runtimeType ?? (_runtimeType = System.Type.GetType(Type)); + //} + + ///// + ///// Used to try to get and cache the tree type + ///// + ///// + ///// + //internal static Type TryGetType(string type) + //{ + // try + // { + // return ResolvedTypes.GetOrAdd(type, s => + // { + // var result = System.Type.GetType(type); + // if (result != null) + // { + // return result; + // } + + // //we need to implement a bit of a hack here due to some trees being renamed and backwards compat + // var parts = type.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries); + // if (parts.Length != 2) + // throw new InvalidOperationException("Could not resolve type"); + // if (parts[1].Trim() != "Umbraco.Web" || parts[0].StartsWith("Umbraco.Web.Trees") == false || parts[0].EndsWith("Controller")) + // throw new InvalidOperationException("Could not resolve type"); + + // //if it's one of our controllers but it's not suffixed with "Controller" then add it and try again + // var tempType = parts[0] + "Controller, Umbraco.Web"; + + // result = System.Type.GetType(tempType); + // if (result != null) + // return result; + + // throw new InvalidOperationException("Could not resolve type"); + // }); + // } + // catch (InvalidOperationException) + // { + // //swallow, this is our own exception, couldn't find the type + // // fixme bad use of exceptions here! + // return null; + // } + //} + } +} diff --git a/src/Umbraco.Web/Models/ContentEditing/IBackOfficeSection.cs b/src/Umbraco.Web/Models/ContentEditing/IBackOfficeSection.cs new file mode 100644 index 0000000000..f27941035a --- /dev/null +++ b/src/Umbraco.Web/Models/ContentEditing/IBackOfficeSection.cs @@ -0,0 +1,15 @@ +using Umbraco.Core.Composing; + +namespace Umbraco.Web.Models.ContentEditing +{ + + /// + /// Defines a back office section + /// + public interface IBackOfficeSection : IDiscoverable + { + string Alias { get; } + string Name { get; } + int SortOrder { get; } + } +} diff --git a/src/Umbraco.Web/Models/Mapping/SectionMapperProfile.cs b/src/Umbraco.Web/Models/Mapping/SectionMapperProfile.cs index ba7ff3c38d..683fce36e8 100644 --- a/src/Umbraco.Web/Models/Mapping/SectionMapperProfile.cs +++ b/src/Umbraco.Web/Models/Mapping/SectionMapperProfile.cs @@ -1,5 +1,6 @@ using System.Collections.Generic; using AutoMapper; +using Umbraco.Core.Models.ContentEditing; using Umbraco.Core.Services; using Umbraco.Web.Models.ContentEditing; @@ -9,7 +10,7 @@ namespace Umbraco.Web.Models.Mapping { public SectionMapperProfile(ILocalizedTextService textService) { - CreateMap() + CreateMap() .ForMember(dest => dest.RoutePath, opt => opt.Ignore()) .ForMember(dest => dest.Icon, opt => opt.Ignore()) .ForMember(dest => dest.Name, opt => opt.MapFrom(src => textService.Localize("sections/" + src.Alias, (IDictionary)null))) diff --git a/src/Umbraco.Web/Models/Mapping/UserMapperProfile.cs b/src/Umbraco.Web/Models/Mapping/UserMapperProfile.cs index 8261dda0d4..c975f3a106 100644 --- a/src/Umbraco.Web/Models/Mapping/UserMapperProfile.cs +++ b/src/Umbraco.Web/Models/Mapping/UserMapperProfile.cs @@ -12,6 +12,7 @@ using Umbraco.Core.Models.Entities; using Umbraco.Core.Security; using Umbraco.Core.Services; using Umbraco.Web.Actions; +using Umbraco.Web.Services; namespace Umbraco.Web.Models.Mapping diff --git a/src/Umbraco.Web/Models/Trees/ApplicationAttribute.cs b/src/Umbraco.Web/Models/Trees/ApplicationAttribute.cs deleted file mode 100644 index 65fc4ed6f3..0000000000 --- a/src/Umbraco.Web/Models/Trees/ApplicationAttribute.cs +++ /dev/null @@ -1,30 +0,0 @@ -using System; - -namespace Umbraco.Web.Models.Trees -{ - /// - /// Identifies an application tree - /// - [AttributeUsage(AttributeTargets.Class, AllowMultiple = false)] - public class ApplicationAttribute : Attribute - { - /// - /// Initializes a new instance of the class. - /// - /// The alias. - /// The name. - /// The sort order. - public ApplicationAttribute(string alias, - string name, - int sortOrder = 0) - { - Alias = alias; - Name = name; - SortOrder = sortOrder; - } - - public string Alias { get; private set; } - public string Name { get; private set; } - public int SortOrder { get; private set; } - } -} diff --git a/src/Umbraco.Web/Models/Trees/ApplicationDefinitions.cs b/src/Umbraco.Web/Models/Trees/ApplicationDefinitions.cs index aa8e0cfda6..ba48c9e240 100644 --- a/src/Umbraco.Web/Models/Trees/ApplicationDefinitions.cs +++ b/src/Umbraco.Web/Models/Trees/ApplicationDefinitions.cs @@ -1,37 +1,77 @@ using Umbraco.Core; using Umbraco.Core.Models; +using Umbraco.Core.Models.ContentEditing; +using Umbraco.Web.Models.ContentEditing; namespace Umbraco.Web.Models.Trees { - // The application definitions are intended as a means to auto populate - // the application.config. On app startup, Umbraco will look for any - // unregistered classes with an ApplicationAttribute and add them to the cache + /// + /// Defines the back office content section + /// + public class ContentBackOfficeSectionDefinition : IBackOfficeSection + { + public string Alias => Constants.Applications.Content; + public string Name => "Content"; + public int SortOrder => 0; + } - [Application(Constants.Applications.Content, "Content")] - public class ContentApplicationDefinition : IApplication - { } + /// + /// Defines the back office media section + /// + public class MediaBackOfficeSectionDefinition : IBackOfficeSection + { + public string Alias => Constants.Applications.Media; + public string Name => "Media"; + public int SortOrder => 1; + } - [Application(Constants.Applications.Media, "Media", sortOrder: 1)] - public class MediaApplicationDefinition : IApplication - { } + /// + /// Defines the back office settings section + /// + public class SettingsBackOfficeSectionDefinition : IBackOfficeSection + { + public string Alias => Constants.Applications.Settings; + public string Name => "Settings"; + public int SortOrder => 2; + } - [Application(Constants.Applications.Settings, "Settings", sortOrder: 2)] - public class SettingsApplicationDefinition : IApplication - { } + /// + /// Defines the back office packages section + /// + public class PackagesBackOfficeSectionDefinition : IBackOfficeSection + { + public string Alias => Constants.Applications.Packages; + public string Name => "Packages"; + public int SortOrder => 3; + } - [Application(Constants.Applications.Packages, "Packages", sortOrder: 3)] - public class PackagesApplicationDefinition : IApplication - { } + /// + /// Defines the back office users section + /// + public class UsersBackOfficeSectionDefinition : IBackOfficeSection + { + public string Alias => Constants.Applications.Users; + public string Name => "Users"; + public int SortOrder => 4; + } - [Application(Constants.Applications.Users, "Users", sortOrder: 4)] - public class UsersApplicationDefinition : IApplication - { } + /// + /// Defines the back office members section + /// + public class MembersBackOfficeSectionDefinition : IBackOfficeSection + { + public string Alias => Constants.Applications.Members; + public string Name => "Members"; + public int SortOrder => 5; + } - [Application(Constants.Applications.Members, "Members", sortOrder: 5)] - public class MembersApplicationDefinition : IApplication - { } - - [Application(Constants.Applications.Translation, "Translation", sortOrder: 6)] - public class TranslationApplicationDefinition : IApplication - { } + /// + /// Defines the back office translation section + /// + public class TranslationBackOfficeSectionDefinition : IBackOfficeSection + { + public string Alias => Constants.Applications.Translation; + public string Name => "Translation"; + public int SortOrder => 6; + } } diff --git a/src/Umbraco.Web/Models/Trees/IApplication.cs b/src/Umbraco.Web/Models/Trees/IApplication.cs deleted file mode 100644 index 4e9cae43fd..0000000000 --- a/src/Umbraco.Web/Models/Trees/IApplication.cs +++ /dev/null @@ -1,10 +0,0 @@ -using Umbraco.Core.Composing; - -namespace Umbraco.Web.Models.Trees -{ - /// - /// Marker interface for created applications in the umbraco backoffice - /// - public interface IApplication : IDiscoverable - { } -} diff --git a/src/Umbraco.Web/Mvc/SurfaceControllerTypeCollection.cs b/src/Umbraco.Web/Mvc/SurfaceControllerTypeCollection.cs index 30c21fce96..eef6ab1ca2 100644 --- a/src/Umbraco.Web/Mvc/SurfaceControllerTypeCollection.cs +++ b/src/Umbraco.Web/Mvc/SurfaceControllerTypeCollection.cs @@ -8,6 +8,8 @@ namespace Umbraco.Web.Mvc // which we are not doing at the moment // we can inherit from BuilderCollectionBase and just be enumerable + //fixme: this should be LazyCollectionBuilderBase ? + public class SurfaceControllerTypeCollection : BuilderCollectionBase { public SurfaceControllerTypeCollection(IEnumerable items) diff --git a/src/Umbraco.Web/Runtime/WebRuntimeComponent.cs b/src/Umbraco.Web/Runtime/WebRuntimeComponent.cs index 422b502f80..b7f4e13432 100644 --- a/src/Umbraco.Web/Runtime/WebRuntimeComponent.cs +++ b/src/Umbraco.Web/Runtime/WebRuntimeComponent.cs @@ -22,10 +22,12 @@ using Umbraco.Core.Models.PublishedContent; using Umbraco.Core.Profiling; using Umbraco.Core.Services; using Umbraco.Web.Install; +using Umbraco.Web.Models.Trees; using Umbraco.Web.Mvc; using Umbraco.Web.PublishedCache; using Umbraco.Web.Routing; using Umbraco.Web.Security; +using Umbraco.Web.Trees; using Umbraco.Web.UI.JavaScript; using Umbraco.Web.WebApi; diff --git a/src/Umbraco.Web/Runtime/WebRuntimeComposer.cs b/src/Umbraco.Web/Runtime/WebRuntimeComposer.cs index 51e4fbd008..0ef9adddb7 100644 --- a/src/Umbraco.Web/Runtime/WebRuntimeComposer.cs +++ b/src/Umbraco.Web/Runtime/WebRuntimeComposer.cs @@ -8,6 +8,8 @@ using Umbraco.Core.Composing; using Umbraco.Core.Configuration; using Umbraco.Core.Dictionary; using Umbraco.Core.Events; +using Umbraco.Core.Models; +using Umbraco.Core.Models.ContentEditing; using Umbraco.Core.Models.PublishedContent; using Umbraco.Core.PropertyEditors; using Umbraco.Core.PropertyEditors.ValueConverters; @@ -21,6 +23,7 @@ using Umbraco.Web.Dictionary; using Umbraco.Web.Editors; using Umbraco.Web.Features; using Umbraco.Web.HealthCheck; +using Umbraco.Web.Models.ContentEditing; using Umbraco.Web.Models.PublishedContent; using Umbraco.Web.Mvc; using Umbraco.Web.PublishedCache; @@ -189,6 +192,14 @@ namespace Umbraco.Web.Runtime .Append() .Append() .Append(); + + // register back office sections + composition.WithCollectionBuilder() + .Add(() => composition.TypeLoader.GetTypes()); + + // register back office trees + composition.WithCollectionBuilder() + .Add(() => composition.TypeLoader.GetTypes()); } } } diff --git a/src/Umbraco.Web/Search/SearchableTreeCollection.cs b/src/Umbraco.Web/Search/SearchableTreeCollection.cs index 38c329cafa..2b1baa5194 100644 --- a/src/Umbraco.Web/Search/SearchableTreeCollection.cs +++ b/src/Umbraco.Web/Search/SearchableTreeCollection.cs @@ -5,6 +5,7 @@ using System.Linq; using Umbraco.Core; using Umbraco.Core.Composing; using Umbraco.Core.Services; +using Umbraco.Web.Services; using Umbraco.Web.Trees; namespace Umbraco.Web.Search diff --git a/src/Umbraco.Web/Services/ApplicationTreeService.cs b/src/Umbraco.Web/Services/ApplicationTreeService.cs index 86bfc5d0bb..72b26e26d3 100644 --- a/src/Umbraco.Web/Services/ApplicationTreeService.cs +++ b/src/Umbraco.Web/Services/ApplicationTreeService.cs @@ -11,7 +11,9 @@ using Umbraco.Core.IO; using Umbraco.Core.Logging; using Umbraco.Core.Models; using Umbraco.Core.Composing; +using Umbraco.Core.Models.ContentEditing; using Umbraco.Core.Services; +using Umbraco.Web.Models.ContentEditing; using Umbraco.Web.Trees; namespace Umbraco.Web.Services @@ -19,276 +21,251 @@ namespace Umbraco.Web.Services internal class ApplicationTreeService : IApplicationTreeService { private readonly ILogger _logger; - private readonly CacheHelper _cache; - private readonly TypeLoader _typeLoader; - private Lazy> _allAvailableTrees; - internal const string TreeConfigFileName = "trees.config"; - private static string _treeConfig; + private readonly TreeCollection _treeCollection; private static readonly object Locker = new object(); private readonly Lazy>> _groupedTrees; - public ApplicationTreeService(ILogger logger, CacheHelper cache, TypeLoader typeLoader) + public ApplicationTreeService(ILogger logger, TreeCollection treeCollection) { _logger = logger; - _cache = cache; - _typeLoader = typeLoader; - _groupedTrees = new Lazy>>(InitGroupedTrees); + _treeCollection = treeCollection; + //_groupedTrees = new Lazy>>(InitGroupedTrees); } - /// - /// gets/sets the trees.config file path - /// - /// - /// The setter is generally only going to be used in unit tests, otherwise it will attempt to resolve it using the IOHelper.MapPath - /// - internal static string TreeConfigFilePath - { - get - { - if (string.IsNullOrWhiteSpace(_treeConfig)) - { - _treeConfig = IOHelper.MapPath(SystemDirectories.Config + "/" + TreeConfigFileName); - } - return _treeConfig; - } - set { _treeConfig = value; } - } + ///// + ///// gets/sets the trees.config file path + ///// + ///// + ///// The setter is generally only going to be used in unit tests, otherwise it will attempt to resolve it using the IOHelper.MapPath + ///// + //internal static string TreeConfigFilePath + //{ + // get + // { + // if (string.IsNullOrWhiteSpace(_treeConfig)) + // { + // _treeConfig = IOHelper.MapPath(SystemDirectories.Config + "/" + TreeConfigFileName); + // } + // return _treeConfig; + // } + // set { _treeConfig = value; } + //} - /// - /// The main entry point to get application trees - /// - /// - /// This lazily on first access will scan for plugin trees and ensure the trees.config is up-to-date with the plugins. If plugins - /// haven't changed on disk then the file will not be saved. The trees are all then loaded from this config file into cache and returned. - /// - private List GetAppTrees() - { - return _cache.RuntimeCache.GetCacheItem>( - CacheKeys.ApplicationTreeCacheKey, - () => - { - var list = ReadFromXmlAndSort(); + ///// + ///// The main entry point to get application trees + ///// + ///// + ///// This lazily on first access will scan for plugin trees and ensure the trees.config is up-to-date with the plugins. If plugins + ///// haven't changed on disk then the file will not be saved. The trees are all then loaded from this config file into cache and returned. + ///// + //private List GetAppTrees() + //{ + // return _cache.RuntimeCache.GetCacheItem>( + // CacheKeys.ApplicationTreeCacheKey, + // () => + // { + // var list = ReadFromXmlAndSort(); - //now we can check the non-volatile flag - if (_allAvailableTrees != null) - { - var hasChanges = false; + // //now we can check the non-volatile flag + // if (_allAvailableTrees != null) + // { + // var hasChanges = false; - LoadXml(doc => - { - //Now, load in the xml structure and update it with anything that is not declared there and save the file. + // LoadXml(doc => + // { + // //Now, load in the xml structure and update it with anything that is not declared there and save the file. - //NOTE: On the first iteration here, it will lazily scan all trees, etc... this is because this ienumerable is lazy - // based on the ApplicationTreeRegistrar - and as noted there this is not an ideal way to do things but were stuck like this - // currently because of the legacy assemblies and types not in the Core. + // //NOTE: On the first iteration here, it will lazily scan all trees, etc... this is because this ienumerable is lazy + // // based on the ApplicationTreeRegistrar - and as noted there this is not an ideal way to do things but were stuck like this + // // currently because of the legacy assemblies and types not in the Core. - //Get all the trees not registered in the config (those not matching by alias casing will be detected as "unregistered") - var unregistered = _allAvailableTrees.Value - .Where(x => list.Any(l => l.Alias == x.Alias) == false) - .ToArray(); + // //Get all the trees not registered in the config (those not matching by alias casing will be detected as "unregistered") + // var unregistered = _allAvailableTrees.Value + // .Where(x => list.Any(l => l.Alias == x.Alias) == false) + // .ToArray(); - hasChanges = unregistered.Any(); + // hasChanges = unregistered.Any(); - if (hasChanges == false) return false; + // if (hasChanges == false) return false; - //add or edit the unregistered ones and re-save the file if any changes were found - var count = 0; - foreach (var tree in unregistered) - { - var existingElement = doc.Root.Elements("add").SingleOrDefault(x => - string.Equals(x.Attribute("alias").Value, tree.Alias, - StringComparison.InvariantCultureIgnoreCase) && - string.Equals(x.Attribute("application").Value, tree.ApplicationAlias, - StringComparison.InvariantCultureIgnoreCase)); - if (existingElement != null) - { - existingElement.SetAttributeValue("alias", tree.Alias); - } - else - { - if (tree.Title.IsNullOrWhiteSpace()) - { - doc.Root.Add(new XElement("add", - new XAttribute("initialize", tree.Initialize), - new XAttribute("sortOrder", tree.SortOrder), - new XAttribute("alias", tree.Alias), - new XAttribute("application", tree.ApplicationAlias), - new XAttribute("iconClosed", tree.IconClosed), - new XAttribute("iconOpen", tree.IconOpened), - new XAttribute("type", tree.Type))); - } - else - { - doc.Root.Add(new XElement("add", - new XAttribute("initialize", tree.Initialize), - new XAttribute("sortOrder", tree.SortOrder), - new XAttribute("alias", tree.Alias), - new XAttribute("application", tree.ApplicationAlias), - new XAttribute("title", tree.Title), - new XAttribute("iconClosed", tree.IconClosed), - new XAttribute("iconOpen", tree.IconOpened), - new XAttribute("type", tree.Type))); - } + // //add or edit the unregistered ones and re-save the file if any changes were found + // var count = 0; + // foreach (var tree in unregistered) + // { + // var existingElement = doc.Root.Elements("add").SingleOrDefault(x => + // string.Equals(x.Attribute("alias").Value, tree.Alias, + // StringComparison.InvariantCultureIgnoreCase) && + // string.Equals(x.Attribute("application").Value, tree.ApplicationAlias, + // StringComparison.InvariantCultureIgnoreCase)); + // if (existingElement != null) + // { + // existingElement.SetAttributeValue("alias", tree.Alias); + // } + // else + // { + // if (tree.Title.IsNullOrWhiteSpace()) + // { + // doc.Root.Add(new XElement("add", + // new XAttribute("initialize", tree.Initialize), + // new XAttribute("sortOrder", tree.SortOrder), + // new XAttribute("alias", tree.Alias), + // new XAttribute("application", tree.ApplicationAlias), + // new XAttribute("iconClosed", tree.IconClosed), + // new XAttribute("iconOpen", tree.IconOpened), + // new XAttribute("type", tree.Type))); + // } + // else + // { + // doc.Root.Add(new XElement("add", + // new XAttribute("initialize", tree.Initialize), + // new XAttribute("sortOrder", tree.SortOrder), + // new XAttribute("alias", tree.Alias), + // new XAttribute("application", tree.ApplicationAlias), + // new XAttribute("title", tree.Title), + // new XAttribute("iconClosed", tree.IconClosed), + // new XAttribute("iconOpen", tree.IconOpened), + // new XAttribute("type", tree.Type))); + // } - } - count++; - } + // } + // count++; + // } - //don't save if there's no changes - return count > 0; - }, true); + // //don't save if there's no changes + // return count > 0; + // }, true); - if (hasChanges) - { - //If there were changes, we need to re-read the structures from the XML - list = ReadFromXmlAndSort(); - } - } + // if (hasChanges) + // { + // //If there were changes, we need to re-read the structures from the XML + // list = ReadFromXmlAndSort(); + // } + // } - return list; - }, new TimeSpan(0, 10, 0)); - } + // return list; + // }, new TimeSpan(0, 10, 0)); + //} - /// - /// Creates a new application tree. - /// - /// if set to true [initialize]. - /// The sort order. - /// The application alias. - /// The alias. - /// The title. - /// The icon closed. - /// The icon opened. - /// The type. - public void MakeNew(bool initialize, int sortOrder, string applicationAlias, string alias, string title, string iconClosed, string iconOpened, string type) - { - LoadXml(doc => - { - var el = doc.Root.Elements("add").SingleOrDefault(x => x.Attribute("alias").Value == alias && x.Attribute("application").Value == applicationAlias); + ///// + ///// Creates a new application tree. + ///// + ///// if set to true [initialize]. + ///// The sort order. + ///// The application alias. + ///// The alias. + ///// The title. + ///// The icon closed. + ///// The icon opened. + ///// The type. + //public void MakeNew(bool initialize, int sortOrder, string applicationAlias, string alias, string title, string iconClosed, string iconOpened, string type) + //{ + // LoadXml(doc => + // { + // var el = doc.Root.Elements("add").SingleOrDefault(x => x.Attribute("alias").Value == alias && x.Attribute("application").Value == applicationAlias); - if (el == null) - { - doc.Root.Add(new XElement("add", - new XAttribute("initialize", initialize), - new XAttribute("sortOrder", sortOrder), - new XAttribute("alias", alias), - new XAttribute("application", applicationAlias), - new XAttribute("title", title), - new XAttribute("iconClosed", iconClosed), - new XAttribute("iconOpen", iconOpened), - new XAttribute("type", type))); - } + // if (el == null) + // { + // doc.Root.Add(new XElement("add", + // new XAttribute("initialize", initialize), + // new XAttribute("sortOrder", sortOrder), + // new XAttribute("alias", alias), + // new XAttribute("application", applicationAlias), + // new XAttribute("title", title), + // new XAttribute("iconClosed", iconClosed), + // new XAttribute("iconOpen", iconOpened), + // new XAttribute("type", type))); + // } - return true; + // return true; - }, true); + // }, true); - OnNew(new ApplicationTree(initialize, sortOrder, applicationAlias, alias, title, iconClosed, iconOpened, type), new EventArgs()); - } + // OnNew(new ApplicationTree(initialize, sortOrder, applicationAlias, alias, title, iconClosed, iconOpened, type), new EventArgs()); + //} - /// - /// Saves this instance. - /// - public void SaveTree(ApplicationTree tree) - { - LoadXml(doc => - { - var el = doc.Root.Elements("add").SingleOrDefault(x => x.Attribute("alias").Value == tree.Alias && x.Attribute("application").Value == tree.ApplicationAlias); + ///// + ///// Saves this instance. + ///// + //public void SaveTree(ApplicationTree tree) + //{ + // LoadXml(doc => + // { + // var el = doc.Root.Elements("add").SingleOrDefault(x => x.Attribute("alias").Value == tree.Alias && x.Attribute("application").Value == tree.ApplicationAlias); - if (el != null) - { - el.RemoveAttributes(); + // if (el != null) + // { + // el.RemoveAttributes(); - el.Add(new XAttribute("initialize", tree.Initialize)); - el.Add(new XAttribute("sortOrder", tree.SortOrder)); - el.Add(new XAttribute("alias", tree.Alias)); - el.Add(new XAttribute("application", tree.ApplicationAlias)); - el.Add(new XAttribute("title", tree.Title)); - el.Add(new XAttribute("iconClosed", tree.IconClosed)); - el.Add(new XAttribute("iconOpen", tree.IconOpened)); - el.Add(new XAttribute("type", tree.Type)); - } + // el.Add(new XAttribute("initialize", tree.Initialize)); + // el.Add(new XAttribute("sortOrder", tree.SortOrder)); + // el.Add(new XAttribute("alias", tree.Alias)); + // el.Add(new XAttribute("application", tree.ApplicationAlias)); + // el.Add(new XAttribute("title", tree.Title)); + // el.Add(new XAttribute("iconClosed", tree.IconClosed)); + // el.Add(new XAttribute("iconOpen", tree.IconOpened)); + // el.Add(new XAttribute("type", tree.Type)); + // } - return true; + // return true; - }, true); + // }, true); - OnUpdated(tree, new EventArgs()); - } + // OnUpdated(tree, new EventArgs()); + //} - /// - /// Deletes this instance. - /// - public void DeleteTree(ApplicationTree tree) - { - LoadXml(doc => - { - doc.Root.Elements("add") - .Where(x => x.Attribute("application") != null - && x.Attribute("application").Value == tree.ApplicationAlias - && x.Attribute("alias") != null && x.Attribute("alias").Value == tree.Alias).Remove(); + ///// + ///// Deletes this instance. + ///// + //public void DeleteTree(ApplicationTree tree) + //{ + // LoadXml(doc => + // { + // doc.Root.Elements("add") + // .Where(x => x.Attribute("application") != null + // && x.Attribute("application").Value == tree.ApplicationAlias + // && x.Attribute("alias") != null && x.Attribute("alias").Value == tree.Alias).Remove(); - return true; + // return true; - }, true); + // }, true); - OnDeleted(tree, new EventArgs()); - } + // OnDeleted(tree, new EventArgs()); + //} - /// - /// Gets an ApplicationTree by it's tree alias. - /// - /// The tree alias. - /// An ApplicationTree instance - public ApplicationTree GetByAlias(string treeAlias) - { - return GetAppTrees().Find(t => (t.Alias == treeAlias)); + /// + public ApplicationTree GetByAlias(string treeAlias) => _treeCollection.FirstOrDefault(t => t.Alias == treeAlias); - } + /// + public IEnumerable GetAll() => _treeCollection; - /// - /// Gets all applicationTrees registered in umbraco from the umbracoAppTree table.. - /// - /// Returns a ApplicationTree Array - public IEnumerable GetAll() - { - return GetAppTrees().OrderBy(x => x.SortOrder); - } - - /// - /// Gets the application tree for the applcation with the specified alias - /// - /// The application alias. - /// Returns a ApplicationTree Array + /// public IEnumerable GetApplicationTrees(string applicationAlias) - { - return GetApplicationTrees(applicationAlias, false); - } + => GetAll().Where(x => x.ApplicationAlias.InvariantEquals(applicationAlias)).OrderBy(x => x.SortOrder).ToList(); - /// - /// Gets the application tree for the applcation with the specified alias - /// - /// The application alias. - /// - /// Returns a ApplicationTree Array - public IEnumerable GetApplicationTrees(string applicationAlias, bool onlyInitialized) - { - var list = GetAppTrees().FindAll( - t => - { - if (onlyInitialized) - return (t.ApplicationAlias == applicationAlias && t.Initialize); - return (t.ApplicationAlias == applicationAlias); - } - ); + ///// + ///// Gets the application tree for the applcation with the specified alias + ///// + ///// The application alias. + ///// + ///// Returns a ApplicationTree Array + //public IEnumerable GetApplicationTrees(string applicationAlias, bool onlyInitialized) + //{ + // var list = GetAppTrees().FindAll( + // t => + // { + // if (onlyInitialized) + // return (t.ApplicationAlias == applicationAlias && t.Initialize); + // return (t.ApplicationAlias == applicationAlias); + // } + // ); - return list.OrderBy(x => x.SortOrder).ToArray(); - } + // return list.OrderBy(x => x.SortOrder).ToArray(); + //} - public IDictionary> GetGroupedApplicationTrees(string applicationAlias, bool onlyInitialized) + public IDictionary> GetGroupedApplicationTrees(string applicationAlias) { var result = new Dictionary>(); - var foundTrees = GetApplicationTrees(applicationAlias, onlyInitialized); + var foundTrees = GetApplicationTrees(applicationAlias).ToList(); foreach(var treeGroup in _groupedTrees.Value) { List resultGroup = null; @@ -309,185 +286,185 @@ namespace Umbraco.Web.Services return result; } - /// - /// Creates a group of all tree groups and their tree aliases - /// - /// - /// - /// Used to initialize the field - /// - private IReadOnlyCollection> InitGroupedTrees() - { - var result = GetAll() - .Select(x => (treeAlias: x.Alias, treeGroup: x.GetRuntimeType().GetCustomAttribute(false)?.TreeGroup)) - .GroupBy(x => x.treeGroup, x => x.treeAlias) - .ToList(); - return result; - } - - /// - /// Loads in the xml structure from disk if one is found, otherwise loads in an empty xml structure, calls the - /// callback with the xml document and saves the structure back to disk if saveAfterCallback is true. - /// - /// - /// - internal void LoadXml(Func callback, bool saveAfterCallbackIfChanges) - { - lock (Locker) - { - var doc = System.IO.File.Exists(TreeConfigFilePath) - ? XDocument.Load(TreeConfigFilePath) - : XDocument.Parse(""); + ///// + ///// Creates a group of all tree groups and their tree aliases + ///// + ///// + ///// + ///// Used to initialize the field + ///// + //private IReadOnlyCollection> InitGroupedTrees() + //{ + // var result = GetAll() + // .Select(x => (treeAlias: x.Alias, treeGroup: x.GetRuntimeType().GetCustomAttribute(false)?.TreeGroup)) + // .GroupBy(x => x.treeGroup, x => x.treeAlias) + // .ToList(); + // return result; + //} - if (doc.Root != null) - { - var hasChanges = callback.Invoke(doc); + ///// + ///// Loads in the xml structure from disk if one is found, otherwise loads in an empty xml structure, calls the + ///// callback with the xml document and saves the structure back to disk if saveAfterCallback is true. + ///// + ///// + ///// + //internal void LoadXml(Func callback, bool saveAfterCallbackIfChanges) + //{ + // lock (Locker) + // { + // var doc = System.IO.File.Exists(TreeConfigFilePath) + // ? XDocument.Load(TreeConfigFilePath) + // : XDocument.Parse(""); - if (saveAfterCallbackIfChanges && hasChanges - //Don't save it if it is empty, in some very rare cases if the app domain get's killed in the middle of this process - // in some insane way the file saved will be empty. I'm pretty sure it's not actually anything to do with the xml doc and - // more about the IO trying to save the XML doc, but it doesn't hurt to check. - && doc.Root != null && doc.Root.Elements().Any()) - { - //ensures the folder exists - Directory.CreateDirectory(Path.GetDirectoryName(TreeConfigFilePath)); + // if (doc.Root != null) + // { + // var hasChanges = callback.Invoke(doc); - //saves it - doc.Save(TreeConfigFilePath); + // if (saveAfterCallbackIfChanges && hasChanges + // //Don't save it if it is empty, in some very rare cases if the app domain get's killed in the middle of this process + // // in some insane way the file saved will be empty. I'm pretty sure it's not actually anything to do with the xml doc and + // // more about the IO trying to save the XML doc, but it doesn't hurt to check. + // && doc.Root != null && doc.Root.Elements().Any()) + // { + // //ensures the folder exists + // Directory.CreateDirectory(Path.GetDirectoryName(TreeConfigFilePath)); - //remove the cache now that it has changed SD: I'm leaving this here even though it - // is taken care of by events as well, I think unit tests may rely on it being cleared here. - _cache.RuntimeCache.ClearCacheItem(CacheKeys.ApplicationTreeCacheKey); - } - } - } - } + // //saves it + // doc.Save(TreeConfigFilePath); - private List ReadFromXmlAndSort() - { - var list = new List(); + // //remove the cache now that it has changed SD: I'm leaving this here even though it + // // is taken care of by events as well, I think unit tests may rely on it being cleared here. + // _cache.RuntimeCache.ClearCacheItem(CacheKeys.ApplicationTreeCacheKey); + // } + // } + // } + //} - //read in the xml file containing trees and convert them all to ApplicationTree instances - LoadXml(doc => - { - foreach (var addElement in doc.Root.Elements("add").OrderBy(x => - { - var sortOrderAttr = x.Attribute("sortOrder"); - return sortOrderAttr != null ? Convert.ToInt32(sortOrderAttr.Value) : 0; - })) - { - var applicationAlias = (string)addElement.Attribute("application"); - var type = (string)addElement.Attribute("type"); - var assembly = (string)addElement.Attribute("assembly"); + //private List ReadFromXmlAndSort() + //{ + // var list = new List(); - var clrType = Type.GetType(type); - if (clrType == null) - { - _logger.Warn("The tree definition: {AddElement} could not be resolved to a .Net object type", addElement); - continue; - } + // //read in the xml file containing trees and convert them all to ApplicationTree instances + // LoadXml(doc => + // { + // foreach (var addElement in doc.Root.Elements("add").OrderBy(x => + // { + // var sortOrderAttr = x.Attribute("sortOrder"); + // return sortOrderAttr != null ? Convert.ToInt32(sortOrderAttr.Value) : 0; + // })) + // { + // var applicationAlias = (string)addElement.Attribute("application"); + // var type = (string)addElement.Attribute("type"); + // var assembly = (string)addElement.Attribute("assembly"); - //check if the tree definition (applicationAlias + type + assembly) is already in the list + // var clrType = Type.GetType(type); + // if (clrType == null) + // { + // _logger.Warn("The tree definition: {AddElement} could not be resolved to a .Net object type", addElement); + // continue; + // } - if (list.Any(tree => tree.ApplicationAlias.InvariantEquals(applicationAlias) && tree.GetRuntimeType() == clrType) == false) - { - list.Add(new ApplicationTree( - addElement.Attribute("initialize") == null || Convert.ToBoolean(addElement.Attribute("initialize").Value), - addElement.Attribute("sortOrder") != null - ? Convert.ToByte(addElement.Attribute("sortOrder").Value) - : (byte)0, - (string)addElement.Attribute("application"), - (string)addElement.Attribute("alias"), - (string)addElement.Attribute("title"), - (string)addElement.Attribute("iconClosed"), - (string)addElement.Attribute("iconOpen"), - (string)addElement.Attribute("type"))); - } - } + // //check if the tree definition (applicationAlias + type + assembly) is already in the list - return false; + // if (list.Any(tree => tree.ApplicationAlias.InvariantEquals(applicationAlias) && tree.GetRuntimeType() == clrType) == false) + // { + // list.Add(new ApplicationTree( + // addElement.Attribute("initialize") == null || Convert.ToBoolean(addElement.Attribute("initialize").Value), + // addElement.Attribute("sortOrder") != null + // ? Convert.ToByte(addElement.Attribute("sortOrder").Value) + // : (byte)0, + // (string)addElement.Attribute("application"), + // (string)addElement.Attribute("alias"), + // (string)addElement.Attribute("title"), + // (string)addElement.Attribute("iconClosed"), + // (string)addElement.Attribute("iconOpen"), + // (string)addElement.Attribute("type"))); + // } + // } - }, false); + // return false; - return list; - } + // }, false); + + // return list; + //} - internal static event TypedEventHandler Deleted; - private static void OnDeleted(ApplicationTree app, EventArgs args) - { - if (Deleted != null) - { - Deleted(app, args); - } - } + //internal static event TypedEventHandler Deleted; + //private static void OnDeleted(ApplicationTree app, EventArgs args) + //{ + // if (Deleted != null) + // { + // Deleted(app, args); + // } + //} - internal static event TypedEventHandler New; - private static void OnNew(ApplicationTree app, EventArgs args) - { - if (New != null) - { - New(app, args); - } - } + //internal static event TypedEventHandler New; + //private static void OnNew(ApplicationTree app, EventArgs args) + //{ + // if (New != null) + // { + // New(app, args); + // } + //} - internal static event TypedEventHandler Updated; - private static void OnUpdated(ApplicationTree app, EventArgs args) - { - if (Updated != null) - { - Updated(app, args); - } - } + //internal static event TypedEventHandler Updated; + //private static void OnUpdated(ApplicationTree app, EventArgs args) + //{ + // if (Updated != null) + // { + // Updated(app, args); + // } + //} - /// - /// This class is here so that we can provide lazy access to tree scanning for when it is needed - /// - private class LazyEnumerableTrees : IEnumerable - { - public LazyEnumerableTrees(TypeLoader typeLoader) - { - _lazyTrees = new Lazy>(() => - { - var added = new List(); + ///// + ///// This class is here so that we can provide lazy access to tree scanning for when it is needed + ///// + //private class LazyEnumerableTrees : IEnumerable + //{ + // public LazyEnumerableTrees(TypeLoader typeLoader) + // { + // _lazyTrees = new Lazy>(() => + // { + // var added = new List(); - // Load all Controller Trees by attribute - var types = typeLoader.GetTypesWithAttribute(); // fixme inject - //convert them to ApplicationTree instances - var items = types - .Select(x => (tree: x, treeAttribute: x.GetCustomAttributes(false).Single())) - .Select(x => new ApplicationTree(x.treeAttribute.Initialize, x.treeAttribute.SortOrder, x.treeAttribute.ApplicationAlias, x.treeAttribute.Alias, x.treeAttribute.Title, x.treeAttribute.IconClosed, x.treeAttribute.IconOpen, x.tree.GetFullNameWithAssembly())) - .ToArray(); + // // Load all Controller Trees by attribute + // var types = typeLoader.GetTypesWithAttribute(); // fixme inject + // //convert them to ApplicationTree instances + // var items = types + // .Select(x => (tree: x, treeAttribute: x.GetCustomAttributes(false).Single())) + // .Select(x => new ApplicationTree(x.treeAttribute.Initialize, x.treeAttribute.SortOrder, x.treeAttribute.ApplicationAlias, x.treeAttribute.Alias, x.treeAttribute.Title, x.treeAttribute.IconClosed, x.treeAttribute.IconOpen, x.tree.GetFullNameWithAssembly())) + // .ToArray(); - added.AddRange(items.Select(x => x.Alias)); + // added.AddRange(items.Select(x => x.Alias)); - return items.ToArray(); - }); - } + // return items.ToArray(); + // }); + // } - private readonly Lazy> _lazyTrees; - - /// - /// Returns an enumerator that iterates through the collection. - /// - /// - /// A that can be used to iterate through the collection. - /// - public IEnumerator GetEnumerator() - { - return _lazyTrees.Value.GetEnumerator(); - } + // private readonly Lazy> _lazyTrees; - /// - /// Returns an enumerator that iterates through a collection. - /// - /// - /// An object that can be used to iterate through the collection. - /// - IEnumerator IEnumerable.GetEnumerator() - { - return GetEnumerator(); - } - } + // /// + // /// Returns an enumerator that iterates through the collection. + // /// + // /// + // /// A that can be used to iterate through the collection. + // /// + // public IEnumerator GetEnumerator() + // { + // return _lazyTrees.Value.GetEnumerator(); + // } + + // /// + // /// Returns an enumerator that iterates through a collection. + // /// + // /// + // /// An object that can be used to iterate through the collection. + // /// + // IEnumerator IEnumerable.GetEnumerator() + // { + // return GetEnumerator(); + // } + //} } } diff --git a/src/Umbraco.Core/Services/IApplicationTreeService.cs b/src/Umbraco.Web/Services/IApplicationTreeService.cs similarity index 52% rename from src/Umbraco.Core/Services/IApplicationTreeService.cs rename to src/Umbraco.Web/Services/IApplicationTreeService.cs index 691a3a0b63..1fd7bc939a 100644 --- a/src/Umbraco.Core/Services/IApplicationTreeService.cs +++ b/src/Umbraco.Web/Services/IApplicationTreeService.cs @@ -2,33 +2,35 @@ using System.Collections.Generic; using System.Linq; using Umbraco.Core.Models; +using Umbraco.Core.Models.ContentEditing; +using Umbraco.Web.Models.ContentEditing; -namespace Umbraco.Core.Services +namespace Umbraco.Web.Services { public interface IApplicationTreeService { - /// - /// Creates a new application tree. - /// - /// if set to true [initialize]. - /// The sort order. - /// The application alias. - /// The alias. - /// The title. - /// The icon closed. - /// The icon opened. - /// The type. - void MakeNew(bool initialize, int sortOrder, string applicationAlias, string alias, string title, string iconClosed, string iconOpened, string type); + ///// + ///// Creates a new application tree. + ///// + ///// if set to true [initialize]. + ///// The sort order. + ///// The application alias. + ///// The alias. + ///// The title. + ///// The icon closed. + ///// The icon opened. + ///// The type. + //void MakeNew(bool initialize, int sortOrder, string applicationAlias, string alias, string title, string iconClosed, string iconOpened, string type); - /// - /// Saves this instance. - /// - void SaveTree(ApplicationTree tree); + ///// + ///// Saves this instance. + ///// + //void SaveTree(ApplicationTree tree); - /// - /// Deletes this instance. - /// - void DeleteTree(ApplicationTree tree); + ///// + ///// Deletes this instance. + ///// + //void DeleteTree(ApplicationTree tree); /// /// Gets an ApplicationTree by it's tree alias. @@ -50,21 +52,20 @@ namespace Umbraco.Core.Services /// Returns a ApplicationTree Array IEnumerable GetApplicationTrees(string applicationAlias); - /// - /// Gets the application tree for the applcation with the specified alias - /// - /// The application alias. - /// - /// Returns a ApplicationTree Array - IEnumerable GetApplicationTrees(string applicationAlias, bool onlyInitialized); + ///// + ///// Gets the application tree for the applcation with the specified alias + ///// + ///// The application alias. + ///// + ///// Returns a ApplicationTree Array + //IEnumerable GetApplicationTrees(string applicationAlias, bool onlyInitialized); /// /// Gets the grouped application trees for the application with the specified alias /// /// - /// /// - IDictionary> GetGroupedApplicationTrees(string applicationAlias, bool onlyInitialized); + IDictionary> GetGroupedApplicationTrees(string applicationAlias); } /// @@ -72,37 +73,37 @@ namespace Umbraco.Core.Services /// internal class EmptyApplicationTreeService : IApplicationTreeService { - /// - /// Creates a new application tree. - /// - /// if set to true [initialize]. - /// The sort order. - /// The application alias. - /// The alias. - /// The title. - /// The icon closed. - /// The icon opened. - /// The type. - public void MakeNew(bool initialize, int sortOrder, string applicationAlias, string alias, string title, string iconClosed, string iconOpened, string type) - { - throw new System.NotImplementedException(); - } + ///// + ///// Creates a new application tree. + ///// + ///// if set to true [initialize]. + ///// The sort order. + ///// The application alias. + ///// The alias. + ///// The title. + ///// The icon closed. + ///// The icon opened. + ///// The type. + //public void MakeNew(bool initialize, int sortOrder, string applicationAlias, string alias, string title, string iconClosed, string iconOpened, string type) + //{ + // throw new System.NotImplementedException(); + //} - /// - /// Saves this instance. - /// - public void SaveTree(ApplicationTree tree) - { - throw new System.NotImplementedException(); - } + ///// + ///// Saves this instance. + ///// + //public void SaveTree(ApplicationTree tree) + //{ + // throw new System.NotImplementedException(); + //} - /// - /// Deletes this instance. - /// - public void DeleteTree(ApplicationTree tree) - { - throw new System.NotImplementedException(); - } + ///// + ///// Deletes this instance. + ///// + //public void DeleteTree(ApplicationTree tree) + //{ + // throw new System.NotImplementedException(); + //} /// /// Gets an ApplicationTree by it's tree alias. @@ -123,7 +124,7 @@ namespace Umbraco.Core.Services throw new System.NotImplementedException(); } - public IDictionary> GetGroupedApplicationTrees(string applicationAlias, bool onlyInitialized) + public IDictionary> GetGroupedApplicationTrees(string applicationAlias) { throw new System.NotImplementedException(); } diff --git a/src/Umbraco.Web/Services/ISectionService.cs b/src/Umbraco.Web/Services/ISectionService.cs new file mode 100644 index 0000000000..560805634f --- /dev/null +++ b/src/Umbraco.Web/Services/ISectionService.cs @@ -0,0 +1,116 @@ +using System.Collections.Generic; +using Umbraco.Core.Models; +using Umbraco.Core.Models.ContentEditing; +using Umbraco.Web.Models.ContentEditing; + +namespace Umbraco.Web.Services +{ + public interface ISectionService + { + /// + /// The cache storage for all applications + /// + IEnumerable GetSections(); + + /// + /// Get the user group's allowed sections + /// + /// + /// + IEnumerable GetAllowedSections(int userId); + + /// + /// Gets the application by its alias. + /// + /// The application alias. + /// + IBackOfficeSection GetByAlias(string appAlias); + + ///// + ///// Creates a new applcation if no application with the specified alias is found. + ///// + ///// The application name. + ///// The application alias. + ///// The application icon, which has to be located in umbraco/images/tray folder. + //void MakeNew(string name, string alias, string icon); + + ///// + ///// Makes the new. + ///// + ///// The name. + ///// The alias. + ///// The icon. + ///// The sort order. + //void MakeNew(string name, string alias, string icon, int sortOrder); + + ///// + ///// Deletes the section + ///// + //void DeleteSection(Section section); + } + + /// + /// Purely used to allow a service context to create the default services + /// + internal class EmptySectionService : ISectionService + { + /// + /// The cache storage for all applications + /// + public IEnumerable GetSections() + { + throw new System.NotImplementedException(); + } + + /// + /// Get the user's allowed sections + /// + /// + /// + public IEnumerable GetAllowedSections(int userId) + { + throw new System.NotImplementedException(); + } + + /// + /// Gets the application by its alias. + /// + /// The application alias. + /// + public IBackOfficeSection GetByAlias(string appAlias) + { + throw new System.NotImplementedException(); + } + + ///// + ///// Creates a new applcation if no application with the specified alias is found. + ///// + ///// The application name. + ///// The application alias. + ///// The application icon, which has to be located in umbraco/images/tray folder. + //public void MakeNew(string name, string alias, string icon) + //{ + // throw new System.NotImplementedException(); + //} + + ///// + ///// Makes the new. + ///// + ///// The name. + ///// The alias. + ///// The icon. + ///// The sort order. + //public void MakeNew(string name, string alias, string icon, int sortOrder) + //{ + // throw new System.NotImplementedException(); + //} + + ///// + ///// Deletes the section + ///// + //public void DeleteSection(IBackOfficeSection section) + //{ + // throw new System.NotImplementedException(); + //} + } +} diff --git a/src/Umbraco.Web/Services/SectionService.cs b/src/Umbraco.Web/Services/SectionService.cs index 6337db67f9..bb154976f0 100644 --- a/src/Umbraco.Web/Services/SectionService.cs +++ b/src/Umbraco.Web/Services/SectionService.cs @@ -10,9 +10,12 @@ using Umbraco.Core.Events; using Umbraco.Core.IO; using Umbraco.Core.Models; using Umbraco.Core.Composing; +using Umbraco.Core.Models.ContentEditing; using Umbraco.Core.Scoping; using Umbraco.Core.Services; +using Umbraco.Web.Models.ContentEditing; using Umbraco.Web.Models.Trees; +using Umbraco.Web.Trees; using File = System.IO.File; namespace Umbraco.Web.Services @@ -20,130 +23,90 @@ namespace Umbraco.Web.Services internal class SectionService : ISectionService { private readonly IUserService _userService; - private readonly Lazy> _allAvailableSections; - private readonly IApplicationTreeService _applicationTreeService; - private readonly IScopeProvider _scopeProvider; + private readonly BackOfficeSectionCollection _sectionCollection; + + private readonly Lazy> _allAvailableSections; + //private readonly IApplicationTreeService _applicationTreeService; + //private readonly IScopeProvider _scopeProvider; private readonly CacheHelper _cache; - internal const string AppConfigFileName = "applications.config"; - private static string _appConfig; - private static readonly object Locker = new object(); + //internal const string AppConfigFileName = "applications.config"; + //private static string _appConfig; + //private static readonly object Locker = new object(); public SectionService( IUserService userService, - IApplicationTreeService applicationTreeService, - IScopeProvider scopeProvider, + BackOfficeSectionCollection sectionCollection, CacheHelper cache) { - _applicationTreeService = applicationTreeService ?? throw new ArgumentNullException(nameof(applicationTreeService)); + //_applicationTreeService = applicationTreeService ?? throw new ArgumentNullException(nameof(applicationTreeService)); _cache = cache ?? throw new ArgumentNullException(nameof(cache)); _userService = userService; - _scopeProvider = scopeProvider; - _allAvailableSections = new Lazy>(() => new LazyEnumerableSections()); + _sectionCollection = sectionCollection; + //_scopeProvider = scopeProvider; + //_allAvailableSections = new Lazy>(() => new LazyEnumerableSections()); } - /// - /// gets/sets the application.config file path - /// - /// - /// The setter is generally only going to be used in unit tests, otherwise it will attempt to resolve it using the IOHelper.MapPath - /// - internal static string AppConfigFilePath - { - get - { - if (string.IsNullOrWhiteSpace(_appConfig)) - { - _appConfig = IOHelper.MapPath(SystemDirectories.Config + "/" + AppConfigFileName); - } - return _appConfig; - } - set => _appConfig = value; - } + ///// + ///// gets/sets the application.config file path + ///// + ///// + ///// The setter is generally only going to be used in unit tests, otherwise it will attempt to resolve it using the IOHelper.MapPath + ///// + //internal static string AppConfigFilePath + //{ + // get + // { + // if (string.IsNullOrWhiteSpace(_appConfig)) + // { + // _appConfig = IOHelper.MapPath(SystemDirectories.Config + "/" + AppConfigFileName); + // } + // return _appConfig; + // } + // set => _appConfig = value; + //} /// /// The cache storage for all applications /// - public IEnumerable
GetSections() + public IEnumerable GetSections() { - return _cache.RuntimeCache.GetCacheItem>( - CacheKeys.ApplicationsCacheKey, - () => - { - var list = ReadFromXmlAndSort(); - var hasChanges = false; - var localCopyList = list; - - LoadXml(doc => - { - //Now, load in the xml structure and update it with anything that is not declared there and save the file. - //NOTE: On the first iteration here, it will lazily scan all apps, etc... this is because this ienumerable is lazy - //Get all the trees not registered in the config - - var unregistered = _allAvailableSections.Value - .Where(x => localCopyList.Any(l => l.Alias == x.Alias) == false) - .ToArray(); - - hasChanges = unregistered.Any(); - - var count = 0; - foreach (var attr in unregistered) - { - doc.Root.Add(new XElement("add", - new XAttribute("alias", attr.Alias), - new XAttribute("name", attr.Name), - new XAttribute("sortOrder", attr.SortOrder))); - count++; - } - - //don't save if there's no changes - return count > 0; - }, true); - - if (hasChanges) - { - //If there were changes, we need to re-read the structures from the XML - list = ReadFromXmlAndSort(); - } - - return list; - - }, new TimeSpan(0, 10, 0)); + return _sectionCollection; } - internal void LoadXml(Func callback, bool saveAfterCallbackIfChanged) - { - lock (Locker) - { - var doc = File.Exists(AppConfigFilePath) - ? XDocument.Load(AppConfigFilePath) - : XDocument.Parse(""); + //internal void LoadXml(Func callback, bool saveAfterCallbackIfChanged) + //{ + // lock (Locker) + // { + // var doc = File.Exists(AppConfigFilePath) + // ? XDocument.Load(AppConfigFilePath) + // : XDocument.Parse(""); - if (doc.Root != null) - { - var changed = callback.Invoke(doc); + // if (doc.Root != null) + // { + // var changed = callback.Invoke(doc); - if (saveAfterCallbackIfChanged && changed) - { - //ensure the folder is created! - Directory.CreateDirectory(Path.GetDirectoryName(AppConfigFilePath)); + // if (saveAfterCallbackIfChanged && changed) + // { + // //ensure the folder is created! + // Directory.CreateDirectory(Path.GetDirectoryName(AppConfigFilePath)); - doc.Save(AppConfigFilePath); + // doc.Save(AppConfigFilePath); - //remove the cache so it gets re-read ... SD: I'm leaving this here even though it - // is taken care of by events as well, I think unit tests may rely on it being cleared here. - _cache.RuntimeCache.ClearCacheItem(CacheKeys.ApplicationsCacheKey); - } - } - } - } + // //remove the cache so it gets re-read ... SD: I'm leaving this here even though it + // // is taken care of by events as well, I think unit tests may rely on it being cleared here. + // _cache.RuntimeCache.ClearCacheItem(CacheKeys.ApplicationsCacheKey); + // } + // } + // } + //} /// /// Get the user's allowed sections /// /// /// - public IEnumerable
GetAllowedSections(int userId) + public IEnumerable GetAllowedSections(int userId) { var user = _userService.GetUserById(userId); @@ -160,172 +123,172 @@ namespace Umbraco.Web.Services ///
/// The application alias. /// - public Section GetByAlias(string appAlias) + public IBackOfficeSection GetByAlias(string appAlias) { return GetSections().FirstOrDefault(t => t.Alias == appAlias); } - /// - /// Creates a new applcation if no application with the specified alias is found. - /// - /// The application name. - /// The application alias. - /// The application icon, which has to be located in umbraco/images/tray folder. - public void MakeNew(string name, string alias, string icon) - { - var sections = GetSections(); - var nextSortOrder = sections.Any() ? sections.Max(x => x.SortOrder) + 1 : 1; - MakeNew(name, alias, icon, nextSortOrder); - } + ///// + ///// Creates a new applcation if no application with the specified alias is found. + ///// + ///// The application name. + ///// The application alias. + ///// The application icon, which has to be located in umbraco/images/tray folder. + //public void MakeNew(string name, string alias, string icon) + //{ + // var sections = GetSections(); + // var nextSortOrder = sections.Any() ? sections.Max(x => x.SortOrder) + 1 : 1; + // MakeNew(name, alias, icon, nextSortOrder); + //} - /// - /// Makes the new. - /// - /// The name. - /// The alias. - /// The icon. - /// The sort order. - public void MakeNew(string name, string alias, string icon, int sortOrder) - { - if (GetSections().All(x => x.Alias != alias)) - { - LoadXml(doc => - { - doc.Root.Add(new XElement("add", - new XAttribute("alias", alias), - new XAttribute("name", name), - new XAttribute("icon", icon), - new XAttribute("sortOrder", sortOrder))); - return true; - }, true); + ///// + ///// Makes the new. + ///// + ///// The name. + ///// The alias. + ///// The icon. + ///// The sort order. + //public void MakeNew(string name, string alias, string icon, int sortOrder) + //{ + // if (GetSections().All(x => x.Alias != alias)) + // { + // LoadXml(doc => + // { + // doc.Root.Add(new XElement("add", + // new XAttribute("alias", alias), + // new XAttribute("name", name), + // new XAttribute("icon", icon), + // new XAttribute("sortOrder", sortOrder))); + // return true; + // }, true); - //raise event - OnNew(this /*new Section(name, alias, sortOrder)*/, new EventArgs()); - } - } + // //raise event + // OnNew(this /*new Section(name, alias, sortOrder)*/, new EventArgs()); + // } + //} - /// - /// Deletes the section - /// - public void DeleteSection(Section section) - { - lock (Locker) - { - //delete the assigned applications - using (var scope = _scopeProvider.CreateScope()) - { - scope.Database.Execute("delete from umbracoUserGroup2App where app = @appAlias", - new { appAlias = section.Alias }); - scope.Complete(); - } + ///// + ///// Deletes the section + ///// + //public void DeleteSection(Section section) + //{ + // lock (Locker) + // { + // //delete the assigned applications + // using (var scope = _scopeProvider.CreateScope()) + // { + // scope.Database.Execute("delete from umbracoUserGroup2App where app = @appAlias", + // new { appAlias = section.Alias }); + // scope.Complete(); + // } - //delete the assigned trees - var trees = _applicationTreeService.GetApplicationTrees(section.Alias); - foreach (var t in trees) - { - _applicationTreeService.DeleteTree(t); - } + // //delete the assigned trees + // var trees = _applicationTreeService.GetApplicationTrees(section.Alias); + // foreach (var t in trees) + // { + // _applicationTreeService.DeleteTree(t); + // } - LoadXml(doc => - { - doc.Root.Elements("add").Where(x => x.Attribute("alias") != null && x.Attribute("alias").Value == section.Alias) - .Remove(); + // LoadXml(doc => + // { + // doc.Root.Elements("add").Where(x => x.Attribute("alias") != null && x.Attribute("alias").Value == section.Alias) + // .Remove(); - return true; - }, true); + // return true; + // }, true); - //raise event - OnDeleted(this, new EventArgs()); - } - } + // //raise event + // OnDeleted(this, new EventArgs()); + // } + //} - private List
ReadFromXmlAndSort() - { - var tmp = new List
(); + //private List
ReadFromXmlAndSort() + //{ + // var tmp = new List
(); - LoadXml(doc => - { - foreach (var addElement in doc.Root.Elements("add").OrderBy(x => - { - var sortOrderAttr = x.Attribute("sortOrder"); - return sortOrderAttr != null ? Convert.ToInt32(sortOrderAttr.Value) : 0; - })) - { - var sortOrderAttr = addElement.Attribute("sortOrder"); - tmp.Add(new Section(addElement.Attribute("name").Value, - addElement.Attribute("alias").Value, - sortOrderAttr != null ? Convert.ToInt32(sortOrderAttr.Value) : 0)); - } - return false; - }, false); + // LoadXml(doc => + // { + // foreach (var addElement in doc.Root.Elements("add").OrderBy(x => + // { + // var sortOrderAttr = x.Attribute("sortOrder"); + // return sortOrderAttr != null ? Convert.ToInt32(sortOrderAttr.Value) : 0; + // })) + // { + // var sortOrderAttr = addElement.Attribute("sortOrder"); + // tmp.Add(new Section(addElement.Attribute("name").Value, + // addElement.Attribute("alias").Value, + // sortOrderAttr != null ? Convert.ToInt32(sortOrderAttr.Value) : 0)); + // } + // return false; + // }, false); - return tmp; - } + // return tmp; + //} - internal static event TypedEventHandler Deleted; - private static void OnDeleted(ISectionService app, EventArgs args) - { - if (Deleted != null) - { - Deleted(app, args); - } - } + //internal static event TypedEventHandler Deleted; + //private static void OnDeleted(ISectionService app, EventArgs args) + //{ + // if (Deleted != null) + // { + // Deleted(app, args); + // } + //} - internal static event TypedEventHandler New; - private static void OnNew(ISectionService app, EventArgs args) - { - if (New != null) - { - New(app, args); - } - } + //internal static event TypedEventHandler New; + //private static void OnNew(ISectionService app, EventArgs args) + //{ + // if (New != null) + // { + // New(app, args); + // } + //} - /// - /// This class is here so that we can provide lazy access to tree scanning for when it is needed - /// - private class LazyEnumerableSections : IEnumerable
- { - public LazyEnumerableSections() - { - _lazySections = new Lazy>(() => - { - // Load all Applications by attribute and add them to the XML config + ///// + ///// This class is here so that we can provide lazy access to tree scanning for when it is needed + ///// + //private class LazyEnumerableSections : IEnumerable
+ //{ + // public LazyEnumerableSections() + // { + // _lazySections = new Lazy>(() => + // { + // // Load all Applications by attribute and add them to the XML config - //don't cache the result of this because it is only used once during app startup, caching will just add a bit more mem overhead for no reason - var types = Current.TypeLoader.GetTypesWithAttribute(cache: false); // fixme - inject + // //don't cache the result of this because it is only used once during app startup, caching will just add a bit more mem overhead for no reason + // var types = Current.TypeLoader.GetTypesWithAttribute(cache: false); // fixme - inject - //since applications don't populate their metadata from the attribute and because it is an interface, - //we need to interrogate the attributes for the data. Would be better to have a base class that contains - //metadata populated by the attribute. Oh well i guess. - var attrs = types.Select(x => x.GetCustomAttributes(false).Single()); - return attrs.Select(x => new Section(x.Name, x.Alias, x.SortOrder)).ToArray(); - }); - } + // //since applications don't populate their metadata from the attribute and because it is an interface, + // //we need to interrogate the attributes for the data. Would be better to have a base class that contains + // //metadata populated by the attribute. Oh well i guess. + // var attrs = types.Select(x => x.GetCustomAttributes(false).Single()); + // return attrs.Select(x => new Section(x.Name, x.Alias, x.SortOrder)).ToArray(); + // }); + // } - private readonly Lazy> _lazySections; + // private readonly Lazy> _lazySections; - /// - /// Returns an enumerator that iterates through the collection. - /// - /// - /// A that can be used to iterate through the collection. - /// - public IEnumerator
GetEnumerator() - { - return _lazySections.Value.GetEnumerator(); - } + // /// + // /// Returns an enumerator that iterates through the collection. + // /// + // /// + // /// A that can be used to iterate through the collection. + // /// + // public IEnumerator
GetEnumerator() + // { + // return _lazySections.Value.GetEnumerator(); + // } - /// - /// Returns an enumerator that iterates through a collection. - /// - /// - /// An object that can be used to iterate through the collection. - /// - IEnumerator IEnumerable.GetEnumerator() - { - return GetEnumerator(); - } - } + // /// + // /// Returns an enumerator that iterates through a collection. + // /// + // /// + // /// An object that can be used to iterate through the collection. + // /// + // IEnumerator IEnumerable.GetEnumerator() + // { + // return GetEnumerator(); + // } + //} } } diff --git a/src/Umbraco.Web/Trees/ApplicationTreeController.cs b/src/Umbraco.Web/Trees/ApplicationTreeController.cs index 0454155772..7e7c77d607 100644 --- a/src/Umbraco.Web/Trees/ApplicationTreeController.cs +++ b/src/Umbraco.Web/Trees/ApplicationTreeController.cs @@ -7,10 +7,17 @@ using System.Net.Http.Formatting; using System.Threading.Tasks; using System.Web.Http; using Umbraco.Core; +using Umbraco.Core.Cache; +using Umbraco.Core.Configuration; +using Umbraco.Core.Logging; using Umbraco.Core.Models; +using Umbraco.Core.Models.ContentEditing; +using Umbraco.Core.Persistence; using Umbraco.Core.Services; +using Umbraco.Web.Models.ContentEditing; using Umbraco.Web.Models.Trees; using Umbraco.Web.Mvc; +using Umbraco.Web.Services; using Umbraco.Web.WebApi; using Umbraco.Web.WebApi.Filters; using Constants = Umbraco.Core.Constants; @@ -20,7 +27,19 @@ namespace Umbraco.Web.Trees [AngularJsonOnlyConfiguration] [PluginController("UmbracoTrees")] public class ApplicationTreeController : UmbracoAuthorizedApiController - { + { + private readonly TreeControllerResolver _treeControllerResolver; + private readonly IApplicationTreeService _treeService; + + public ApplicationTreeController(IGlobalSettings globalSettings, UmbracoContext umbracoContext, + ISqlContext sqlContext, ServiceContext services, CacheHelper applicationCache, IProfilingLogger logger, + IRuntimeState runtimeState, TreeControllerResolver treeControllerResolver, IApplicationTreeService treeService) + : base(globalSettings, umbracoContext, sqlContext, services, applicationCache, logger, runtimeState) + { + _treeControllerResolver = treeControllerResolver; + _treeService = treeService; + } + /// /// Returns the tree nodes for an application /// @@ -30,14 +49,14 @@ namespace Umbraco.Web.Trees /// An optional bool (defaults to true), if set to false it will also load uninitialized trees /// [HttpQueryStringFilter("queryStrings")] - public async Task GetApplicationTrees(string application, string tree, FormDataCollection queryStrings, bool onlyInitialized = true) + public async Task GetApplicationTrees(string application, string tree, FormDataCollection queryStrings/*, bool onlyInitialized = true*/) { application = application.CleanForXss(); if (string.IsNullOrEmpty(application)) throw new HttpResponseException(HttpStatusCode.NotFound); //find all tree definitions that have the current application alias - var groupedTrees = Services.ApplicationTreeService.GetGroupedApplicationTrees(application, onlyInitialized); + var groupedTrees = _treeService.GetGroupedApplicationTrees(application); var allTrees = groupedTrees.Values.SelectMany(x => x).ToList(); if (string.IsNullOrEmpty(tree) == false || allTrees.Count == 1) @@ -142,7 +161,7 @@ namespace Umbraco.Web.Trees if (configTree == null) throw new ArgumentNullException(nameof(configTree)); try { - var byControllerAttempt = await configTree.TryGetRootNodeFromControllerTree(queryStrings, ControllerContext); + var byControllerAttempt = await _treeControllerResolver.TryGetRootNodeFromControllerTree(configTree, queryStrings, ControllerContext); if (byControllerAttempt.Success) { return byControllerAttempt.Result; @@ -170,17 +189,17 @@ namespace Umbraco.Web.Trees { var rootId = Constants.System.Root.ToString(CultureInfo.InvariantCulture); if (configTree == null) throw new ArgumentNullException(nameof(configTree)); - var byControllerAttempt = configTree.TryLoadFromControllerTree(id, queryStrings, ControllerContext); + var byControllerAttempt = _treeControllerResolver.TryLoadFromControllerTree(configTree, id, queryStrings, ControllerContext); if (byControllerAttempt.Success) { - var rootNode = await configTree.TryGetRootNodeFromControllerTree(queryStrings, ControllerContext); + var rootNode = await _treeControllerResolver.TryGetRootNodeFromControllerTree(configTree, queryStrings, ControllerContext); if (rootNode.Success == false) { //This should really never happen if we've successfully got the children above. throw new InvalidOperationException("Could not create root node for tree " + configTree.Alias); } - var treeAttribute = configTree.GetTreeAttribute(); + var treeAttribute = _treeControllerResolver.GetTreeAttribute(configTree); var sectionRoot = TreeRootNode.CreateSingleTreeRoot( rootId, diff --git a/src/Umbraco.Web/Trees/BackOfficeSectionCollection.cs b/src/Umbraco.Web/Trees/BackOfficeSectionCollection.cs new file mode 100644 index 0000000000..2b5a78d758 --- /dev/null +++ b/src/Umbraco.Web/Trees/BackOfficeSectionCollection.cs @@ -0,0 +1,21 @@ +using System.Collections.Generic; +using Umbraco.Core.Composing; +using Umbraco.Core.Models.ContentEditing; +using Umbraco.Web.Models.ContentEditing; + +namespace Umbraco.Web.Trees +{ + public class BackOfficeSectionCollection : BuilderCollectionBase + { + public BackOfficeSectionCollection(IEnumerable items) + : base(items) + { } + } + + public class BackOfficeSectionCollectionBuilder : LazyCollectionBuilderBase + { + protected override BackOfficeSectionCollectionBuilder This => this; + + //TODO: can we allow for re-ordering OOTB without exposing other methods? + } +} diff --git a/src/Umbraco.Web/Trees/TreeCollection.cs b/src/Umbraco.Web/Trees/TreeCollection.cs new file mode 100644 index 0000000000..8f913fb2d7 --- /dev/null +++ b/src/Umbraco.Web/Trees/TreeCollection.cs @@ -0,0 +1,27 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Umbraco.Core.Composing; +using Umbraco.Core.Models; +using Umbraco.Core.Models.ContentEditing; +using Umbraco.Web.Models.ContentEditing; + +namespace Umbraco.Web.Trees +{ + public class TreeCollection : BuilderCollectionBase + { + public TreeCollection(IEnumerable items) + : base(items) + { } + } + + public class TreeCollectionBuilder : LazyCollectionBuilderBase + { + protected override TreeCollectionBuilder This => this; + + //TODO: can we allow for re-ordering OOTB without exposing other methods? + } + +} diff --git a/src/Umbraco.Web/Trees/TreeController.cs b/src/Umbraco.Web/Trees/TreeController.cs index 1c37307db5..102671ec29 100644 --- a/src/Umbraco.Web/Trees/TreeController.cs +++ b/src/Umbraco.Web/Trees/TreeController.cs @@ -1,4 +1,12 @@ -namespace Umbraco.Web.Trees +using System; +using Umbraco.Core; +using Umbraco.Core.Cache; +using Umbraco.Core.Configuration; +using Umbraco.Core.Logging; +using Umbraco.Core.Persistence; +using Umbraco.Core.Services; + +namespace Umbraco.Web.Trees { /// /// The base controller for all tree requests @@ -8,6 +16,10 @@ private TreeAttribute _attribute; private string _rootNodeDisplayName; + protected TreeController(IGlobalSettings globalSettings, UmbracoContext umbracoContext, ISqlContext sqlContext, ServiceContext services, CacheHelper applicationCache, IProfilingLogger logger, IRuntimeState runtimeState) : base(globalSettings, umbracoContext, sqlContext, services, applicationCache, logger, runtimeState) + { + } + protected TreeController() { Initialize(); @@ -17,21 +29,25 @@ /// The name to display on the root node /// public override string RootNodeDisplayName - => _rootNodeDisplayName - ?? (_rootNodeDisplayName = Services.ApplicationTreeService.GetByAlias(_attribute.Alias) - ?.GetRootNodeDisplayName(Services.TextService)); + { + get + { + throw new NotImplementedException(); + //return _rootNodeDisplayName + // ?? (_rootNodeDisplayName = Services.ApplicationTreeService.GetByAlias(_attribute.Alias) + // ?.GetRootNodeDisplayName(Services.TextService)); + } + } /// /// Gets the current tree alias from the attribute assigned to it. /// - public override string TreeAlias - { - get { return _attribute.Alias; } - } + public override string TreeAlias => _attribute.Alias; private void Initialize() { - _attribute = GetType().GetTreeAttribute(); + throw new NotImplementedException(); + //_attribute = GetType().GetTreeAttribute(); } } } diff --git a/src/Umbraco.Web/Trees/TreeControllerBase.cs b/src/Umbraco.Web/Trees/TreeControllerBase.cs index ffdcac4479..c00d6053c8 100644 --- a/src/Umbraco.Web/Trees/TreeControllerBase.cs +++ b/src/Umbraco.Web/Trees/TreeControllerBase.cs @@ -4,9 +4,14 @@ using System.Linq; using System.Net.Http.Formatting; using System.Web.Http.Routing; using Umbraco.Core; +using Umbraco.Core.Cache; +using Umbraco.Core.Configuration; using Umbraco.Core.Events; +using Umbraco.Core.Logging; using Umbraco.Core.Models; using Umbraco.Core.Models.Entities; +using Umbraco.Core.Persistence; +using Umbraco.Core.Services; using Umbraco.Web.Models.Trees; using Umbraco.Web.WebApi; using Umbraco.Web.WebApi.Filters; @@ -14,12 +19,23 @@ using Umbraco.Web.WebApi.Filters; namespace Umbraco.Web.Trees { /// - /// A base controller reference for non-attributed trees (un-registered). Developers should inherit from - /// TreeController. + /// A base controller reference for non-attributed trees (un-registered). /// + /// + /// Developers should generally inherit from TreeController. + /// [AngularJsonOnlyConfiguration] public abstract class TreeControllerBase : UmbracoAuthorizedApiController { + protected TreeControllerBase() + { + } + + protected TreeControllerBase(IGlobalSettings globalSettings, UmbracoContext umbracoContext, ISqlContext sqlContext, ServiceContext services, CacheHelper applicationCache, IProfilingLogger logger, IRuntimeState runtimeState) : base(globalSettings, umbracoContext, sqlContext, services, applicationCache, logger, runtimeState) + { + } + + /// /// The method called to render the contents of the tree structure /// @@ -351,7 +367,7 @@ namespace Umbraco.Web.Trees private static void OnTreeNodesRendering(TreeControllerBase instance, TreeNodesRenderingEventArgs e) { var handler = TreeNodesRendering; - if (handler != null) handler(instance, e); + handler?.Invoke(instance, e); } /// @@ -363,7 +379,7 @@ namespace Umbraco.Web.Trees internal static void OnRootNodeRendering(TreeControllerBase instance, TreeNodeRenderingEventArgs e) { var handler = RootNodeRendering; - if (handler != null) handler(instance, e); + handler?.Invoke(instance, e); } /// @@ -377,80 +393,8 @@ namespace Umbraco.Web.Trees private static void OnMenuRendering(TreeControllerBase instance, MenuRenderingEventArgs e) { var handler = MenuRendering; - if (handler != null) handler(instance, e); + handler?.Invoke(instance, e); } } - internal class TreeControllerBaseStuffForLegacy - { - private readonly string _treeAlias; - private readonly string _rootNodeDisplayName; - private readonly UrlHelper _url; - - public TreeControllerBaseStuffForLegacy(string treeAlias, string rootNodeDisplayName, UrlHelper url) - { - _treeAlias = treeAlias; - _rootNodeDisplayName = rootNodeDisplayName; - _url = url; - } - - public TreeNode GetRootNode(FormDataCollection queryStrings) - { - if (queryStrings == null) queryStrings = new FormDataCollection(""); - var node = CreateRootNode(queryStrings); - - //add the tree alias to the root - node.AdditionalData["treeAlias"] = _treeAlias; - - AddQueryStringsToAdditionalData(node, queryStrings); - - //check if the tree is searchable and add that to the meta data as well - if (this is ISearchableTree) - { - node.AdditionalData.Add("searchable", "true"); - } - - //now update all data based on some of the query strings, like if we are running in dialog mode - if (IsDialog(queryStrings)) - { - node.RoutePath = "#"; - } - - TreeControllerBase.OnRootNodeRendering(null, new TreeNodeRenderingEventArgs(node, queryStrings)); - - return node; - } - - protected virtual TreeNode CreateRootNode(FormDataCollection queryStrings) - { - var rootNodeAsString = Constants.System.Root.ToString(CultureInfo.InvariantCulture); - var currApp = queryStrings.GetValue(TreeQueryStringParameters.Application); - - var node = new TreeNode( - rootNodeAsString, - null, //this is a root node, there is no parent - _url.GetTreeUrl(GetType(), rootNodeAsString, queryStrings), - _url.GetMenuUrl(GetType(), rootNodeAsString, queryStrings)) - { - HasChildren = true, - RoutePath = currApp, - Name = _rootNodeDisplayName - }; - - return node; - } - - protected void AddQueryStringsToAdditionalData(TreeNode node, FormDataCollection queryStrings) - { - foreach (var q in queryStrings.Where(x => node.AdditionalData.ContainsKey(x.Key) == false)) - { - node.AdditionalData.Add(q.Key, q.Value); - } - } - - protected bool IsDialog(FormDataCollection queryStrings) - { - return queryStrings.GetValue(TreeQueryStringParameters.IsDialog); - } - } } diff --git a/src/Umbraco.Web/Trees/ApplicationTreeExtensions.cs b/src/Umbraco.Web/Trees/TreeControllerResolver.cs similarity index 56% rename from src/Umbraco.Web/Trees/ApplicationTreeExtensions.cs rename to src/Umbraco.Web/Trees/TreeControllerResolver.cs index 2c43cbd5dc..62cafbb5dd 100644 --- a/src/Umbraco.Web/Trees/ApplicationTreeExtensions.cs +++ b/src/Umbraco.Web/Trees/TreeControllerResolver.cs @@ -14,16 +14,25 @@ using Umbraco.Web.Models.Trees; using Umbraco.Web.Mvc; using Umbraco.Web.WebApi; using Umbraco.Core.Composing; -using Current = Umbraco.Web.Composing.Current; -using ApplicationTree = Umbraco.Core.Models.ApplicationTree; +using ApplicationTree = Umbraco.Web.Models.ContentEditing.ApplicationTree; namespace Umbraco.Web.Trees { - internal static class ApplicationTreeExtensions + public class TreeControllerResolver { - private static readonly ConcurrentDictionary TreeAttributeCache = new ConcurrentDictionary(); + private readonly TreeCollection _trees; + private readonly UmbracoApiControllerTypeCollection _apiControllers; - internal static TreeAttribute GetTreeAttribute(this Type treeControllerType) + public TreeControllerResolver(TreeCollection trees, UmbracoApiControllerTypeCollection apiControllers) + { + _trees = trees; + _apiControllers = apiControllers; + } + + private static readonly ConcurrentDictionary TreeAttributeCache = new ConcurrentDictionary(); + private static readonly ConcurrentDictionary ResolvedControllerTypes = new ConcurrentDictionary(); + + private TreeAttribute GetTreeAttribute(Type treeControllerType) { return TreeAttributeCache.GetOrAdd(treeControllerType, type => { @@ -42,25 +51,41 @@ namespace Umbraco.Web.Trees }); } - internal static TreeAttribute GetTreeAttribute(this ApplicationTree tree) + internal TreeAttribute GetTreeAttribute(ApplicationTree tree) { - return tree.GetRuntimeType().GetTreeAttribute(); + throw new NotImplementedException(); + //return ResolvedControllerTypes.GetOrAdd(tree.Alias, s => + //{ + // var controllerType = _apiControllers + // .OfType() + // .FirstOrDefault(x => x.) + //}); + + //return GetTreeAttribute(tree.GetRuntimeType()); } - internal static Attempt TryGetControllerTree(this ApplicationTree appTree) + private Type GetControllerType(ApplicationTree tree) { - //get reference to all TreeApiControllers - var controllerTrees = Current.UmbracoApiControllerTypes - .Where(TypeHelper.IsTypeAssignableFrom) - .ToArray(); + throw new NotImplementedException(); + } + - //find the one we're looking for - var foundControllerTree = controllerTrees.FirstOrDefault(x => x == appTree.GetRuntimeType()); - if (foundControllerTree == null) - { - return Attempt.Fail(new InstanceNotFoundException("Could not find tree of type " + appTree.Type + " in any loaded DLLs")); - } - return Attempt.Succeed(foundControllerTree); + internal Attempt TryGetControllerTree(ApplicationTree appTree) + { + throw new NotImplementedException(); + + ////get reference to all TreeApiControllers + //var controllerTrees = _apiControllers + // .Where(TypeHelper.IsTypeAssignableFrom) + // .ToArray(); + + ////find the one we're looking for + //var foundControllerTree = controllerTrees.FirstOrDefault(x => x == appTree.GetRuntimeType()); + //if (foundControllerTree == null) + //{ + // return Attempt.Fail(new InstanceNotFoundException("Could not find tree of type " + appTree.Type + " in any loaded DLLs")); + //} + //return Attempt.Succeed(foundControllerTree); } /// @@ -73,9 +98,9 @@ namespace Umbraco.Web.Trees /// /// This ensures that authorization filters are applied to the sub request /// - internal static async Task> TryGetRootNodeFromControllerTree(this ApplicationTree appTree, FormDataCollection formCollection, HttpControllerContext controllerContext) + internal async Task> TryGetRootNodeFromControllerTree(ApplicationTree appTree, FormDataCollection formCollection, HttpControllerContext controllerContext) { - var foundControllerTreeAttempt = appTree.TryGetControllerTree(); + var foundControllerTreeAttempt = TryGetControllerTree(appTree); if (foundControllerTreeAttempt.Success == false) { return Attempt.Fail(foundControllerTreeAttempt.Exception); @@ -110,12 +135,15 @@ namespace Umbraco.Web.Trees if (WebApiVersionCheck.WebApiVersion >= Version.Parse("5.0.0")) { - //In WebApi2, this is required to be set: - // proxiedControllerContext.RequestContext = controllerContext.RequestContext - // but we need to do this with reflection because of codebase changes between version 4/5 - //NOTE: Use TypeHelper here since the reflection is cached - var controllerContextRequestContext = TypeHelper.GetProperty(controllerContext.GetType(), "RequestContext").GetValue(controllerContext); - TypeHelper.GetProperty(proxiedControllerContext.GetType(), "RequestContext").SetValue(proxiedControllerContext, controllerContextRequestContext); + //fixme - will this 'just' work now? + proxiedControllerContext.RequestContext = controllerContext.RequestContext; + + ////In WebApi2, this is required to be set: + //// proxiedControllerContext.RequestContext = controllerContext.RequestContext + //// but we need to do this with reflection because of codebase changes between version 4/5 + ////NOTE: Use TypeHelper here since the reflection is cached + //var controllerContextRequestContext = TypeHelper.GetProperty(controllerContext.GetType(), "RequestContext").GetValue(controllerContext); + //TypeHelper.GetProperty(proxiedControllerContext.GetType(), "RequestContext").SetValue(proxiedControllerContext, controllerContextRequestContext); } instance.ControllerContext = proxiedControllerContext; @@ -123,13 +151,17 @@ namespace Umbraco.Web.Trees if (WebApiVersionCheck.WebApiVersion >= Version.Parse("5.0.0")) { - //now we can change the request context's route data to be the proxied route data - NOTE: we cannot do this directly above - // because it will detect that the request context is different throw an exception. This is a change in webapi2 and we need to set - // this with reflection due to codebase changes between version 4/5 - // instance.RequestContext.RouteData = proxiedRouteData; - //NOTE: Use TypeHelper here since the reflection is cached - var instanceRequestContext = TypeHelper.GetProperty(typeof(ApiController), "RequestContext").GetValue(instance); - TypeHelper.GetProperty(instanceRequestContext.GetType(), "RouteData").SetValue(instanceRequestContext, proxiedRouteData); + + //fixme - will this 'just' work now? + instance.RequestContext.RouteData = proxiedRouteData; + + ////now we can change the request context's route data to be the proxied route data - NOTE: we cannot do this directly above + //// because it will detect that the request context is different throw an exception. This is a change in webapi2 and we need to set + //// this with reflection due to codebase changes between version 4/5 + //// instance.RequestContext.RouteData = proxiedRouteData; + ////NOTE: Use TypeHelper here since the reflection is cached + //var instanceRequestContext = TypeHelper.GetProperty(typeof(ApiController), "RequestContext").GetValue(instance); + //TypeHelper.GetProperty(instanceRequestContext.GetType(), "RouteData").SetValue(instanceRequestContext, proxiedRouteData); } //invoke auth filters for this sub request @@ -143,13 +175,13 @@ namespace Umbraco.Web.Trees //return the root var node = instance.GetRootNode(formCollection); return node == null - ? Attempt.Fail(new InvalidOperationException("Could not return a root node for tree " + appTree.Type)) + ? Attempt.Fail(new InvalidOperationException("Could not return a root node for tree " + appTree.Alias)) : Attempt.Succeed(node); } - internal static Attempt TryLoadFromControllerTree(this ApplicationTree appTree, string id, FormDataCollection formCollection, HttpControllerContext controllerContext) + internal Attempt TryLoadFromControllerTree(ApplicationTree appTree, string id, FormDataCollection formCollection, HttpControllerContext controllerContext) { - var foundControllerTreeAttempt = appTree.TryGetControllerTree(); + var foundControllerTreeAttempt = TryGetControllerTree(appTree); if (foundControllerTreeAttempt.Success == false) return Attempt.Fail(foundControllerTreeAttempt.Exception); diff --git a/src/Umbraco.Web/UI/Pages/UmbracoEnsuredPage.cs b/src/Umbraco.Web/UI/Pages/UmbracoEnsuredPage.cs index bb9ce3c421..9e632eabc9 100644 --- a/src/Umbraco.Web/UI/Pages/UmbracoEnsuredPage.cs +++ b/src/Umbraco.Web/UI/Pages/UmbracoEnsuredPage.cs @@ -29,12 +29,14 @@ namespace Umbraco.Web.UI.Pages var treeAuth = this.GetType().GetCustomAttribute(true); if (treeAuth != null) { - var treeByAlias = Current.Services.ApplicationTreeService - .GetByAlias(treeAuth.TreeAlias); - if (treeByAlias != null) - { - CurrentApp = treeByAlias.ApplicationAlias; - } + throw new NotImplementedException(); + + //var treeByAlias = Current.Services.ApplicationTreeService + // .GetByAlias(treeAuth.TreeAlias); + //if (treeByAlias != null) + //{ + // CurrentApp = treeByAlias.ApplicationAlias; + //} } } diff --git a/src/Umbraco.Web/Umbraco.Web.csproj b/src/Umbraco.Web/Umbraco.Web.csproj index b0142771d2..f1d15e9ea6 100755 --- a/src/Umbraco.Web/Umbraco.Web.csproj +++ b/src/Umbraco.Web/Umbraco.Web.csproj @@ -166,6 +166,8 @@ + + @@ -181,6 +183,9 @@ + + + @@ -217,6 +222,7 @@ + @@ -585,9 +591,7 @@ - - @@ -890,7 +894,6 @@ - @@ -969,7 +972,7 @@ - + @@ -1236,7 +1239,7 @@ True Reference.map - + diff --git a/src/Umbraco.Web/UrlHelperExtensions.cs b/src/Umbraco.Web/UrlHelperExtensions.cs index 9b1c282aab..0a04539967 100644 --- a/src/Umbraco.Web/UrlHelperExtensions.cs +++ b/src/Umbraco.Web/UrlHelperExtensions.cs @@ -13,7 +13,6 @@ using Umbraco.Web.Composing; using Umbraco.Web.Editors; using Umbraco.Web.Mvc; using Umbraco.Web.WebApi; -using Umbraco.Web.WebServices; namespace Umbraco.Web { diff --git a/src/Umbraco.Web/WebApi/Filters/LegacyTreeAuthorizeAttribute.cs b/src/Umbraco.Web/WebApi/Filters/LegacyTreeAuthorizeAttribute.cs deleted file mode 100644 index 5d1b90a09d..0000000000 --- a/src/Umbraco.Web/WebApi/Filters/LegacyTreeAuthorizeAttribute.cs +++ /dev/null @@ -1,29 +0,0 @@ -using System.Web.Http; -using System.Web.Http.Controllers; -using Umbraco.Core; -using Umbraco.Web.Composing; - -namespace Umbraco.Web.WebApi.Filters -{ - internal class LegacyTreeAuthorizeAttribute : AuthorizeAttribute - { - protected override bool IsAuthorized(HttpActionContext actionContext) - { - var httpContext = actionContext.Request.TryGetHttpContext(); - if (httpContext) - { - var treeRequest = httpContext.Result.Request.QueryString["treeType"]; - if (treeRequest.IsNullOrWhiteSpace()) return false; - - var tree = Current.Services.ApplicationTreeService.GetByAlias(treeRequest); - if (tree == null) return false; - - return UmbracoContext.Current.Security.CurrentUser != null - && UmbracoContext.Current.Security.UserHasSectionAccess(tree.ApplicationAlias, UmbracoContext.Current.Security.CurrentUser); - } - return false; - - - } - } -} diff --git a/src/Umbraco.Web/WebApi/Filters/UmbracoTreeAuthorizeAttribute.cs b/src/Umbraco.Web/WebApi/Filters/UmbracoTreeAuthorizeAttribute.cs index 7318c9d9b8..cc483db416 100644 --- a/src/Umbraco.Web/WebApi/Filters/UmbracoTreeAuthorizeAttribute.cs +++ b/src/Umbraco.Web/WebApi/Filters/UmbracoTreeAuthorizeAttribute.cs @@ -1,4 +1,5 @@ -using System.Linq; +using System; +using System.Linq; using System.Web.Http.Controllers; using System.Web.Http.Filters; using Umbraco.Core; @@ -40,16 +41,18 @@ namespace Umbraco.Web.WebApi.Filters return true; } - var apps = _treeAliases.Select(x => Current.Services.ApplicationTreeService - .GetByAlias(x)) - .WhereNotNull() - .Select(x => x.ApplicationAlias) - .Distinct() - .ToArray(); + throw new NotImplementedException(); - return Current.UmbracoContext.Security.CurrentUser != null - && apps.Any(app => Current.UmbracoContext.Security.UserHasSectionAccess( - app, Current.UmbracoContext.Security.CurrentUser)); + //var apps = _treeAliases.Select(x => Current.Services.ApplicationTreeService + // .GetByAlias(x)) + // .WhereNotNull() + // .Select(x => x.ApplicationAlias) + // .Distinct() + // .ToArray(); + + //return Current.UmbracoContext.Security.CurrentUser != null + // && apps.Any(app => Current.UmbracoContext.Security.UserHasSectionAccess( + // app, Current.UmbracoContext.Security.CurrentUser)); } } } diff --git a/src/Umbraco.Web/WebApi/UmbracoApiController.cs b/src/Umbraco.Web/WebApi/UmbracoApiController.cs index 3db3610cc2..586160cfa0 100644 --- a/src/Umbraco.Web/WebApi/UmbracoApiController.cs +++ b/src/Umbraco.Web/WebApi/UmbracoApiController.cs @@ -23,8 +23,8 @@ namespace Umbraco.Web.WebApi /// /// Initialize a new instance of the with all its dependencies. /// - protected UmbracoApiController(IGlobalSettings globalSettings, IUmbracoContextAccessor umbracoContextAccessor, ISqlContext sqlContext, ServiceContext services, CacheHelper applicationCache, IProfilingLogger logger, IRuntimeState runtimeState) - : base(globalSettings, umbracoContextAccessor, sqlContext, services, applicationCache, logger, runtimeState) + protected UmbracoApiController(IGlobalSettings globalSettings, UmbracoContext umbracoContext, ISqlContext sqlContext, ServiceContext services, CacheHelper applicationCache, IProfilingLogger logger, IRuntimeState runtimeState) + : base(globalSettings, umbracoContext, sqlContext, services, applicationCache, logger, runtimeState) { } } } diff --git a/src/Umbraco.Web/WebApi/UmbracoApiControllerBase.cs b/src/Umbraco.Web/WebApi/UmbracoApiControllerBase.cs index 21b88cc919..106ef60e0b 100644 --- a/src/Umbraco.Web/WebApi/UmbracoApiControllerBase.cs +++ b/src/Umbraco.Web/WebApi/UmbracoApiControllerBase.cs @@ -21,7 +21,6 @@ namespace Umbraco.Web.WebApi [FeatureAuthorize] public abstract class UmbracoApiControllerBase : ApiController { - private readonly IUmbracoContextAccessor _umbracoContextAccessor; private UmbracoHelper _umbracoHelper; // note: all Umbraco controllers have two constructors: one with all dependencies, which should be used, @@ -36,7 +35,7 @@ namespace Umbraco.Web.WebApi protected UmbracoApiControllerBase() : this( Current.Factory.GetInstance(), - Current.Factory.GetInstance(), + Current.Factory.GetInstance().UmbracoContext, Current.Factory.GetInstance(), Current.Factory.GetInstance(), Current.Factory.GetInstance(), @@ -48,15 +47,15 @@ namespace Umbraco.Web.WebApi /// /// Initializes a new instance of the class with all its dependencies. /// - protected UmbracoApiControllerBase(IGlobalSettings globalSettings, IUmbracoContextAccessor umbracoContextAccessor, ISqlContext sqlContext, ServiceContext services, CacheHelper applicationCache, IProfilingLogger logger, IRuntimeState runtimeState) + protected UmbracoApiControllerBase(IGlobalSettings globalSettings, UmbracoContext umbracoContext, ISqlContext sqlContext, ServiceContext services, CacheHelper applicationCache, IProfilingLogger logger, IRuntimeState runtimeState) { GlobalSettings = globalSettings; - _umbracoContextAccessor = umbracoContextAccessor; SqlContext = sqlContext; Services = services; ApplicationCache = applicationCache; Logger = logger; RuntimeState = runtimeState; + UmbracoContext = umbracoContext; } /// @@ -73,8 +72,8 @@ namespace Umbraco.Web.WebApi /// /// Gets the Umbraco context. /// - public virtual UmbracoContext UmbracoContext => _umbracoContextAccessor.UmbracoContext; - + public virtual UmbracoContext UmbracoContext { get; } + /// /// Gets the sql context. /// diff --git a/src/Umbraco.Web/WebApi/UmbracoApiControllerTypeCollection.cs b/src/Umbraco.Web/WebApi/UmbracoApiControllerTypeCollection.cs index cdb1aa2f51..d84ab3fe4a 100644 --- a/src/Umbraco.Web/WebApi/UmbracoApiControllerTypeCollection.cs +++ b/src/Umbraco.Web/WebApi/UmbracoApiControllerTypeCollection.cs @@ -8,6 +8,8 @@ namespace Umbraco.Web.WebApi // which we are not doing at the moment // we can inherit from BuilderCollectionBase and just be enumerable + //fixme: this should be LazyCollectionBuilderBase ? + public class UmbracoApiControllerTypeCollection : BuilderCollectionBase { public UmbracoApiControllerTypeCollection(IEnumerable items) diff --git a/src/Umbraco.Web/WebApi/UmbracoAuthorizedApiController.cs b/src/Umbraco.Web/WebApi/UmbracoAuthorizedApiController.cs index 4ae9c00a47..e8c0a3c674 100644 --- a/src/Umbraco.Web/WebApi/UmbracoAuthorizedApiController.cs +++ b/src/Umbraco.Web/WebApi/UmbracoAuthorizedApiController.cs @@ -40,8 +40,8 @@ namespace Umbraco.Web.WebApi /// /// Initializes a new instance of the class with all its dependencies. /// - protected UmbracoAuthorizedApiController(IGlobalSettings globalSettings, IUmbracoContextAccessor umbracoContextAccessor, ISqlContext sqlContext, ServiceContext services, CacheHelper applicationCache, IProfilingLogger logger, IRuntimeState runtimeState) - : base(globalSettings, umbracoContextAccessor, sqlContext, services, applicationCache, logger, runtimeState) + protected UmbracoAuthorizedApiController(IGlobalSettings globalSettings, UmbracoContext umbracoContext, ISqlContext sqlContext, ServiceContext services, CacheHelper applicationCache, IProfilingLogger logger, IRuntimeState runtimeState) + : base(globalSettings, umbracoContext, sqlContext, services, applicationCache, logger, runtimeState) { } /// diff --git a/src/Umbraco.Web/_Legacy/PackageActions/addApplication.cs b/src/Umbraco.Web/_Legacy/PackageActions/addApplication.cs index 26116820e6..c6d5ba30d9 100644 --- a/src/Umbraco.Web/_Legacy/PackageActions/addApplication.cs +++ b/src/Umbraco.Web/_Legacy/PackageActions/addApplication.cs @@ -1,61 +1,61 @@ -using System; -using System.Xml; -using System.Xml.Linq; -using Umbraco.Core; -using Umbraco.Core._Legacy.PackageActions; -using Umbraco.Web.Composing; +//using System; +//using System.Xml; +//using System.Xml.Linq; +//using Umbraco.Core; +//using Umbraco.Core._Legacy.PackageActions; +//using Umbraco.Web.Composing; -namespace Umbraco.Web._Legacy.PackageActions -{ - /// - /// This class implements the IPackageAction Interface, used to execute code when packages are installed. - /// All IPackageActions only takes a PackageName and a XmlNode as input, and executes based on the data in the xmlnode. - /// - public class AddApplication : IPackageAction - { +//namespace Umbraco.Web._Legacy.PackageActions +//{ +// /// +// /// This class implements the IPackageAction Interface, used to execute code when packages are installed. +// /// All IPackageActions only takes a PackageName and a XmlNode as input, and executes based on the data in the xmlnode. +// /// +// public class AddApplication : IPackageAction +// { - #region IPackageAction Members +// #region IPackageAction Members - /// - /// Installs a new application in umbraco. - /// - /// Name of the package. - /// The XML data. - /// - /// - /// - /// true if successfull - public bool Execute(string packageName, XElement xmlData) - { - string name = xmlData.AttributeValue("appName"); - string alias = xmlData.AttributeValue("appAlias"); - string icon = xmlData.AttributeValue("appIcon"); +// /// +// /// Installs a new application in umbraco. +// /// +// /// Name of the package. +// /// The XML data. +// /// +// /// +// /// +// /// true if successfull +// public bool Execute(string packageName, XElement xmlData) +// { +// string name = xmlData.AttributeValue("appName"); +// string alias = xmlData.AttributeValue("appAlias"); +// string icon = xmlData.AttributeValue("appIcon"); - Current.Services.SectionService.MakeNew(name, alias, icon); +// Current.Services.SectionService.MakeNew(name, alias, icon); - return true; - } +// return true; +// } - public bool Undo(string packageName, XElement xmlData) - { - string alias = xmlData.AttributeValue("appAlias"); - var section = Current.Services.SectionService.GetByAlias(alias); - if (section != null) - { - Current.Services.SectionService.DeleteSection(section); - } - return true; - } - /// - /// Action alias. - /// - /// - public string Alias() - { - return "addApplication"; - } +// public bool Undo(string packageName, XElement xmlData) +// { +// string alias = xmlData.AttributeValue("appAlias"); +// var section = Current.Services.SectionService.GetByAlias(alias); +// if (section != null) +// { +// Current.Services.SectionService.DeleteSection(section); +// } +// return true; +// } +// /// +// /// Action alias. +// /// +// /// +// public string Alias() +// { +// return "addApplication"; +// } - #endregion +// #endregion - } -} +// } +//} From cfe1b17eecc5a06b56530610d9e04158033e66a4 Mon Sep 17 00:00:00 2001 From: Shannon Date: Thu, 17 Jan 2019 16:40:11 +1100 Subject: [PATCH 02/11] Gets trees and sections loading now in a much more simplified way without any xml, now to cleanup --- src/Umbraco.Tests/Testing/UmbracoTestBase.cs | 2 +- src/Umbraco.Web/Composing/Current.cs | 7 + .../Editors/BackOfficeServerVariables.cs | 2 +- src/Umbraco.Web/Editors/EntityController.cs | 6 +- src/Umbraco.Web/Editors/SectionController.cs | 8 +- .../Models/ContentEditing/ApplicationTree.cs | 177 --------------- .../Mvc/SurfaceControllerTypeCollection.cs | 4 +- src/Umbraco.Web/Runtime/WebRuntimeComposer.cs | 13 +- .../Search/SearchableTreeCollection.cs | 8 +- .../Services/IApplicationTreeService.cs | 153 ------------- src/Umbraco.Web/Services/ISectionService.cs | 89 +------- src/Umbraco.Web/Services/ITreeService.cs | 49 +++++ ...plicationTreeService.cs => TreeService.cs} | 40 ++-- src/Umbraco.Web/Trees/ApplicationTree.cs | 69 ++++++ .../Trees/ApplicationTreeController.cs | 173 +++++++++++---- src/Umbraco.Web/Trees/ITree.cs | 31 +++ src/Umbraco.Web/Trees/TreeAttribute.cs | 35 +-- src/Umbraco.Web/Trees/TreeCollection.cs | 21 +- src/Umbraco.Web/Trees/TreeController.cs | 55 +++-- src/Umbraco.Web/Trees/TreeControllerBase.cs | 14 +- .../Trees/TreeControllerResolver.cs | 203 ------------------ .../Trees/UserPermissionsTreeController.cs | 52 ----- src/Umbraco.Web/Umbraco.Web.csproj | 10 +- .../Filters/UmbracoTreeAuthorizeAttribute.cs | 20 +- src/Umbraco.Web/WebApi/MvcVersionCheck.cs | 10 - .../UmbracoApiControllerTypeCollection.cs | 2 - 26 files changed, 425 insertions(+), 828 deletions(-) delete mode 100644 src/Umbraco.Web/Models/ContentEditing/ApplicationTree.cs delete mode 100644 src/Umbraco.Web/Services/IApplicationTreeService.cs create mode 100644 src/Umbraco.Web/Services/ITreeService.cs rename src/Umbraco.Web/Services/{ApplicationTreeService.cs => TreeService.cs} (95%) create mode 100644 src/Umbraco.Web/Trees/ApplicationTree.cs create mode 100644 src/Umbraco.Web/Trees/ITree.cs delete mode 100644 src/Umbraco.Web/Trees/TreeControllerResolver.cs delete mode 100644 src/Umbraco.Web/Trees/UserPermissionsTreeController.cs delete mode 100644 src/Umbraco.Web/WebApi/MvcVersionCheck.cs diff --git a/src/Umbraco.Tests/Testing/UmbracoTestBase.cs b/src/Umbraco.Tests/Testing/UmbracoTestBase.cs index a79531af74..0a0999f2dc 100644 --- a/src/Umbraco.Tests/Testing/UmbracoTestBase.cs +++ b/src/Umbraco.Tests/Testing/UmbracoTestBase.cs @@ -342,7 +342,7 @@ namespace Umbraco.Tests.Testing Composition.ComposeServices(); // composition root is doing weird things, fix - Composition.RegisterUnique(); + Composition.RegisterUnique(); Composition.RegisterUnique(); // somehow property editor ends up wanting this diff --git a/src/Umbraco.Web/Composing/Current.cs b/src/Umbraco.Web/Composing/Current.cs index 1e8f3d17f7..d887720063 100644 --- a/src/Umbraco.Web/Composing/Current.cs +++ b/src/Umbraco.Web/Composing/Current.cs @@ -25,6 +25,7 @@ using Umbraco.Web.HealthCheck; using Umbraco.Web.Mvc; using Umbraco.Web.PublishedCache; using Umbraco.Web.Routing; +using Umbraco.Web.Services; using Umbraco.Web.WebApi; using CoreCurrent = Umbraco.Core.Composing.Current; @@ -135,6 +136,12 @@ namespace Umbraco.Web.Composing internal static IPublishedSnapshotService PublishedSnapshotService => Factory.GetInstance(); + public static ITreeService TreeService + => Factory.GetInstance(); + + public static ISectionService SectionService + => Factory.GetInstance(); + #endregion #region Web Constants diff --git a/src/Umbraco.Web/Editors/BackOfficeServerVariables.cs b/src/Umbraco.Web/Editors/BackOfficeServerVariables.cs index 65ab27d76a..1525dd5808 100644 --- a/src/Umbraco.Web/Editors/BackOfficeServerVariables.cs +++ b/src/Umbraco.Web/Editors/BackOfficeServerVariables.cs @@ -408,7 +408,7 @@ namespace Umbraco.Web.Editors let pluginAttr = p.attributes.OfType().Single() select new Dictionary { - {"alias", treeAttr.Alias}, {"packageFolder", pluginAttr.AreaName} + {"alias", treeAttr.TreeAlias}, {"packageFolder", pluginAttr.AreaName} }).ToArray(); } diff --git a/src/Umbraco.Web/Editors/EntityController.cs b/src/Umbraco.Web/Editors/EntityController.cs index c8368d11b0..ca1a6a12bb 100644 --- a/src/Umbraco.Web/Editors/EntityController.cs +++ b/src/Umbraco.Web/Editors/EntityController.cs @@ -42,10 +42,10 @@ namespace Umbraco.Web.Editors [PluginController("UmbracoApi")] public class EntityController : UmbracoAuthorizedJsonController { - private readonly IApplicationTreeService _treeService; + private readonly ITreeService _treeService; public EntityController(IGlobalSettings globalSettings, UmbracoContext umbracoContext, ISqlContext sqlContext, ServiceContext services, CacheHelper applicationCache, IProfilingLogger logger, IRuntimeState runtimeState, - IApplicationTreeService treeService) + ITreeService treeService) : base(globalSettings, umbracoContext, sqlContext, services, applicationCache, logger, runtimeState) { _treeService = treeService; @@ -148,7 +148,7 @@ namespace Umbraco.Web.Editors var searchableTreeAttribute = searchableTree.Value.SearchableTree.GetType().GetCustomAttribute(false); - result[tree.GetRootNodeDisplayName(Services.TextService)] = new TreeSearchResult + result[ApplicationTree.GetRootNodeDisplayName(tree, Services.TextService)] = new TreeSearchResult { Results = searchableTree.Value.SearchableTree.Search(query, 200, 0, out var total), TreeAlias = searchableTree.Key, diff --git a/src/Umbraco.Web/Editors/SectionController.cs b/src/Umbraco.Web/Editors/SectionController.cs index 7b484b09b1..d68f062f61 100644 --- a/src/Umbraco.Web/Editors/SectionController.cs +++ b/src/Umbraco.Web/Editors/SectionController.cs @@ -24,16 +24,14 @@ namespace Umbraco.Web.Editors { private readonly Dashboards _dashboards; private readonly ISectionService _sectionService; - private readonly TreeControllerResolver _treeControllerResolver; - private readonly IApplicationTreeService _treeService; + private readonly ITreeService _treeService; public SectionController(IGlobalSettings globalSettings, UmbracoContext umbracoContext, ISqlContext sqlContext, ServiceContext services, CacheHelper applicationCache, IProfilingLogger logger, IRuntimeState runtimeState, - Dashboards dashboards, ISectionService sectionService, TreeControllerResolver treeControllerResolver, IApplicationTreeService treeService) + Dashboards dashboards, ISectionService sectionService, ITreeService treeService) : base(globalSettings, umbracoContext, sqlContext, services, applicationCache, logger, runtimeState) { _dashboards = dashboards; _sectionService = sectionService; - _treeControllerResolver = treeControllerResolver; _treeService = treeService; } @@ -45,7 +43,7 @@ namespace Umbraco.Web.Editors // this is a bit nasty since we'll be proxying via the app tree controller but we sort of have to do that // since tree's by nature are controllers and require request contextual data - var appTreeController = new ApplicationTreeController(GlobalSettings, UmbracoContext, SqlContext, Services, ApplicationCache, Logger, RuntimeState, _treeControllerResolver, _treeService) + var appTreeController = new ApplicationTreeController(GlobalSettings, UmbracoContext, SqlContext, Services, ApplicationCache, Logger, RuntimeState, _treeService) { ControllerContext = ControllerContext }; diff --git a/src/Umbraco.Web/Models/ContentEditing/ApplicationTree.cs b/src/Umbraco.Web/Models/ContentEditing/ApplicationTree.cs deleted file mode 100644 index e9befb0e27..0000000000 --- a/src/Umbraco.Web/Models/ContentEditing/ApplicationTree.cs +++ /dev/null @@ -1,177 +0,0 @@ -using System; -using System.Diagnostics; -using Umbraco.Core.Services; - -namespace Umbraco.Web.Models.ContentEditing -{ - [DebuggerDisplay("Tree - {Alias} ({ApplicationAlias})")] - public class ApplicationTree - { - //private static readonly ConcurrentDictionary ResolvedTypes = new ConcurrentDictionary(); - - ///// - ///// Initializes a new instance of the class. - ///// - //public ApplicationTree() { } - - ///// - ///// Initializes a new instance of the class. - ///// - ///// if set to true [initialize]. - ///// The sort order. - ///// The application alias. - ///// The tree alias. - ///// The tree title. - ///// The icon closed. - ///// The icon opened. - ///// The tree type. - //public ApplicationTree(bool initialize, int sortOrder, string applicationAlias, string alias, string title, string iconClosed, string iconOpened, string type) - //{ - // //Initialize = initialize; - // SortOrder = sortOrder; - // ApplicationAlias = applicationAlias; - // Alias = alias; - // Title = title; - // IconClosed = iconClosed; - // IconOpened = iconOpened; - // Type = type; - - //} - - public ApplicationTree(int sortOrder, string applicationAlias, string alias, string title) - { - SortOrder = sortOrder; - ApplicationAlias = applicationAlias; - Alias = alias; - Title = title; - } - - ///// - ///// Gets or sets a value indicating whether this should initialize. - ///// - ///// true if initialize; otherwise, false. - //public bool Initialize { get; set; } - - /// - /// Gets or sets the sort order. - /// - /// The sort order. - public int SortOrder { get; set; } - - /// - /// Gets the application alias. - /// - /// The application alias. - public string ApplicationAlias { get; } - - /// - /// Gets the tree alias. - /// - /// The alias. - public string Alias { get; } - - /// - /// Gets or sets the tree title (fallback if the tree alias isn't localized) - /// - /// The title. - public string Title { get; set; } - - ///// - ///// Gets or sets the icon closed. - ///// - ///// The icon closed. - //public string IconClosed { get; set; } - - ///// - ///// Gets or sets the icon opened. - ///// - ///// The icon opened. - //public string IconOpened { get; set; } - - ///// - ///// Gets or sets the tree type assembly name. - ///// - ///// The type. - //public string Type { get; set; } - - /// - /// Returns the localized root node display name - /// - /// - /// - public string GetRootNodeDisplayName(ILocalizedTextService textService) - { - var label = $"[{Alias}]"; - - // try to look up a the localized tree header matching the tree alias - var localizedLabel = textService.Localize("treeHeaders/" + Alias); - - // if the localizedLabel returns [alias] then return the title if it's defined - if (localizedLabel != null && localizedLabel.Equals(label, StringComparison.InvariantCultureIgnoreCase)) - { - if (string.IsNullOrEmpty(Title) == false) - label = Title; - } - else - { - // the localizedLabel translated into something that's not just [alias], so use the translation - label = localizedLabel; - } - - return label; - } - - //private Type _runtimeType; - - ///// - ///// Returns the CLR type based on it's assembly name stored in the config - ///// - ///// - //public Type GetRuntimeType() - //{ - // return _runtimeType ?? (_runtimeType = System.Type.GetType(Type)); - //} - - ///// - ///// Used to try to get and cache the tree type - ///// - ///// - ///// - //internal static Type TryGetType(string type) - //{ - // try - // { - // return ResolvedTypes.GetOrAdd(type, s => - // { - // var result = System.Type.GetType(type); - // if (result != null) - // { - // return result; - // } - - // //we need to implement a bit of a hack here due to some trees being renamed and backwards compat - // var parts = type.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries); - // if (parts.Length != 2) - // throw new InvalidOperationException("Could not resolve type"); - // if (parts[1].Trim() != "Umbraco.Web" || parts[0].StartsWith("Umbraco.Web.Trees") == false || parts[0].EndsWith("Controller")) - // throw new InvalidOperationException("Could not resolve type"); - - // //if it's one of our controllers but it's not suffixed with "Controller" then add it and try again - // var tempType = parts[0] + "Controller, Umbraco.Web"; - - // result = System.Type.GetType(tempType); - // if (result != null) - // return result; - - // throw new InvalidOperationException("Could not resolve type"); - // }); - // } - // catch (InvalidOperationException) - // { - // //swallow, this is our own exception, couldn't find the type - // // fixme bad use of exceptions here! - // return null; - // } - //} - } -} diff --git a/src/Umbraco.Web/Mvc/SurfaceControllerTypeCollection.cs b/src/Umbraco.Web/Mvc/SurfaceControllerTypeCollection.cs index eef6ab1ca2..d9577417cc 100644 --- a/src/Umbraco.Web/Mvc/SurfaceControllerTypeCollection.cs +++ b/src/Umbraco.Web/Mvc/SurfaceControllerTypeCollection.cs @@ -7,9 +7,7 @@ namespace Umbraco.Web.Mvc // unless we want to modify the content of the collection // which we are not doing at the moment // we can inherit from BuilderCollectionBase and just be enumerable - - //fixme: this should be LazyCollectionBuilderBase ? - + public class SurfaceControllerTypeCollection : BuilderCollectionBase { public SurfaceControllerTypeCollection(IEnumerable items) diff --git a/src/Umbraco.Web/Runtime/WebRuntimeComposer.cs b/src/Umbraco.Web/Runtime/WebRuntimeComposer.cs index 0ef9adddb7..047d080a88 100644 --- a/src/Umbraco.Web/Runtime/WebRuntimeComposer.cs +++ b/src/Umbraco.Web/Runtime/WebRuntimeComposer.cs @@ -95,7 +95,7 @@ namespace Umbraco.Web.Runtime // replace some services composition.RegisterUnique(); composition.RegisterUnique(); - composition.RegisterUnique(); + composition.RegisterUnique(); composition.RegisterUnique(); composition.RegisterUnique(factory => ExamineManager.Instance); @@ -125,9 +125,11 @@ namespace Umbraco.Web.Runtime composition.WithCollectionBuilder() .Add(() => composition.TypeLoader.GetTypes()); + //we need to eagerly scan controller types since they will need to be routed var surfaceControllerTypes = new SurfaceControllerTypeCollection(composition.TypeLoader.GetSurfaceControllers()); composition.RegisterUnique(surfaceControllerTypes); + //we need to eagerly scan controller types since they will need to be routed var umbracoApiControllerTypes = new UmbracoApiControllerTypeCollection(composition.TypeLoader.GetUmbracoApiControllers()); composition.RegisterUnique(umbracoApiControllerTypes); @@ -198,8 +200,13 @@ namespace Umbraco.Web.Runtime .Add(() => composition.TypeLoader.GetTypes()); // register back office trees - composition.WithCollectionBuilder() - .Add(() => composition.TypeLoader.GetTypes()); + foreach (var treeControllerType in umbracoApiControllerTypes) + { + var attribute = treeControllerType.GetCustomAttribute(false); + if (attribute == null) continue; + var tree = new ApplicationTree(attribute.SortOrder, attribute.ApplicationAlias, attribute.TreeAlias, attribute.TreeTitle, treeControllerType, attribute.IsSingleNodeTree); + composition.WithCollectionBuilder().AddTree(tree); + } } } } diff --git a/src/Umbraco.Web/Search/SearchableTreeCollection.cs b/src/Umbraco.Web/Search/SearchableTreeCollection.cs index 2b1baa5194..032782b466 100644 --- a/src/Umbraco.Web/Search/SearchableTreeCollection.cs +++ b/src/Umbraco.Web/Search/SearchableTreeCollection.cs @@ -14,13 +14,13 @@ namespace Umbraco.Web.Search { private readonly Dictionary _dictionary; - public SearchableTreeCollection(IEnumerable items, IApplicationTreeService treeService) + public SearchableTreeCollection(IEnumerable items, ITreeService treeService) : base(items) { _dictionary = CreateDictionary(treeService); } - private Dictionary CreateDictionary(IApplicationTreeService treeService) + private Dictionary CreateDictionary(ITreeService treeService) { var appTrees = treeService.GetAll() .OrderBy(x => x.SortOrder) @@ -29,10 +29,10 @@ namespace Umbraco.Web.Search var searchableTrees = this.ToArray(); foreach (var appTree in appTrees) { - var found = searchableTrees.FirstOrDefault(x => x.TreeAlias.InvariantEquals(appTree.Alias)); + var found = searchableTrees.FirstOrDefault(x => x.TreeAlias.InvariantEquals(appTree.TreeAlias)); if (found != null) { - dictionary[found.TreeAlias] = new SearchableApplicationTree(appTree.ApplicationAlias, appTree.Alias, found); + dictionary[found.TreeAlias] = new SearchableApplicationTree(appTree.ApplicationAlias, appTree.TreeAlias, found); } } return dictionary; diff --git a/src/Umbraco.Web/Services/IApplicationTreeService.cs b/src/Umbraco.Web/Services/IApplicationTreeService.cs deleted file mode 100644 index 1fd7bc939a..0000000000 --- a/src/Umbraco.Web/Services/IApplicationTreeService.cs +++ /dev/null @@ -1,153 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using Umbraco.Core.Models; -using Umbraco.Core.Models.ContentEditing; -using Umbraco.Web.Models.ContentEditing; - -namespace Umbraco.Web.Services -{ - public interface IApplicationTreeService - { - ///// - ///// Creates a new application tree. - ///// - ///// if set to true [initialize]. - ///// The sort order. - ///// The application alias. - ///// The alias. - ///// The title. - ///// The icon closed. - ///// The icon opened. - ///// The type. - //void MakeNew(bool initialize, int sortOrder, string applicationAlias, string alias, string title, string iconClosed, string iconOpened, string type); - - ///// - ///// Saves this instance. - ///// - //void SaveTree(ApplicationTree tree); - - ///// - ///// Deletes this instance. - ///// - //void DeleteTree(ApplicationTree tree); - - /// - /// Gets an ApplicationTree by it's tree alias. - /// - /// The tree alias. - /// An ApplicationTree instance - ApplicationTree GetByAlias(string treeAlias); - - /// - /// Gets all applicationTrees registered in umbraco from the umbracoAppTree table.. - /// - /// Returns a ApplicationTree Array - IEnumerable GetAll(); - - /// - /// Gets the application tree for the applcation with the specified alias - /// - /// The application alias. - /// Returns a ApplicationTree Array - IEnumerable GetApplicationTrees(string applicationAlias); - - ///// - ///// Gets the application tree for the applcation with the specified alias - ///// - ///// The application alias. - ///// - ///// Returns a ApplicationTree Array - //IEnumerable GetApplicationTrees(string applicationAlias, bool onlyInitialized); - - /// - /// Gets the grouped application trees for the application with the specified alias - /// - /// - /// - IDictionary> GetGroupedApplicationTrees(string applicationAlias); - } - - /// - /// Purely used to allow a service context to create the default services - /// - internal class EmptyApplicationTreeService : IApplicationTreeService - { - ///// - ///// Creates a new application tree. - ///// - ///// if set to true [initialize]. - ///// The sort order. - ///// The application alias. - ///// The alias. - ///// The title. - ///// The icon closed. - ///// The icon opened. - ///// The type. - //public void MakeNew(bool initialize, int sortOrder, string applicationAlias, string alias, string title, string iconClosed, string iconOpened, string type) - //{ - // throw new System.NotImplementedException(); - //} - - ///// - ///// Saves this instance. - ///// - //public void SaveTree(ApplicationTree tree) - //{ - // throw new System.NotImplementedException(); - //} - - ///// - ///// Deletes this instance. - ///// - //public void DeleteTree(ApplicationTree tree) - //{ - // throw new System.NotImplementedException(); - //} - - /// - /// Gets an ApplicationTree by it's tree alias. - /// - /// The tree alias. - /// An ApplicationTree instance - public ApplicationTree GetByAlias(string treeAlias) - { - throw new System.NotImplementedException(); - } - - /// - /// Gets all applicationTrees registered in umbraco from the umbracoAppTree table.. - /// - /// Returns a ApplicationTree Array - public IEnumerable GetAll() - { - throw new System.NotImplementedException(); - } - - public IDictionary> GetGroupedApplicationTrees(string applicationAlias) - { - throw new System.NotImplementedException(); - } - - /// - /// Gets the application tree for the applcation with the specified alias - /// - /// The application alias. - /// Returns a ApplicationTree Array - public IEnumerable GetApplicationTrees(string applicationAlias) - { - throw new System.NotImplementedException(); - } - - /// - /// Gets the application tree for the applcation with the specified alias - /// - /// The application alias. - /// - /// Returns a ApplicationTree Array - public IEnumerable GetApplicationTrees(string applicationAlias, bool onlyInitialized) - { - throw new System.NotImplementedException(); - } - } -} diff --git a/src/Umbraco.Web/Services/ISectionService.cs b/src/Umbraco.Web/Services/ISectionService.cs index 560805634f..c325020cf1 100644 --- a/src/Umbraco.Web/Services/ISectionService.cs +++ b/src/Umbraco.Web/Services/ISectionService.cs @@ -25,92 +25,7 @@ namespace Umbraco.Web.Services /// The application alias. /// IBackOfficeSection GetByAlias(string appAlias); - - ///// - ///// Creates a new applcation if no application with the specified alias is found. - ///// - ///// The application name. - ///// The application alias. - ///// The application icon, which has to be located in umbraco/images/tray folder. - //void MakeNew(string name, string alias, string icon); - - ///// - ///// Makes the new. - ///// - ///// The name. - ///// The alias. - ///// The icon. - ///// The sort order. - //void MakeNew(string name, string alias, string icon, int sortOrder); - - ///// - ///// Deletes the section - ///// - //void DeleteSection(Section section); - } - - /// - /// Purely used to allow a service context to create the default services - /// - internal class EmptySectionService : ISectionService - { - /// - /// The cache storage for all applications - /// - public IEnumerable GetSections() - { - throw new System.NotImplementedException(); - } - - /// - /// Get the user's allowed sections - /// - /// - /// - public IEnumerable GetAllowedSections(int userId) - { - throw new System.NotImplementedException(); - } - - /// - /// Gets the application by its alias. - /// - /// The application alias. - /// - public IBackOfficeSection GetByAlias(string appAlias) - { - throw new System.NotImplementedException(); - } - - ///// - ///// Creates a new applcation if no application with the specified alias is found. - ///// - ///// The application name. - ///// The application alias. - ///// The application icon, which has to be located in umbraco/images/tray folder. - //public void MakeNew(string name, string alias, string icon) - //{ - // throw new System.NotImplementedException(); - //} - - ///// - ///// Makes the new. - ///// - ///// The name. - ///// The alias. - ///// The icon. - ///// The sort order. - //public void MakeNew(string name, string alias, string icon, int sortOrder) - //{ - // throw new System.NotImplementedException(); - //} - - ///// - ///// Deletes the section - ///// - //public void DeleteSection(IBackOfficeSection section) - //{ - // throw new System.NotImplementedException(); - //} + } + } diff --git a/src/Umbraco.Web/Services/ITreeService.cs b/src/Umbraco.Web/Services/ITreeService.cs new file mode 100644 index 0000000000..ce734cc5e4 --- /dev/null +++ b/src/Umbraco.Web/Services/ITreeService.cs @@ -0,0 +1,49 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using Umbraco.Core.Models; +using Umbraco.Core.Models.ContentEditing; +using Umbraco.Web.Models.ContentEditing; +using Umbraco.Web.Trees; + +namespace Umbraco.Web.Services +{ + public interface ITreeService + { + /// + /// Gets an ApplicationTree by it's tree alias. + /// + /// The tree alias. + /// An ApplicationTree instance + ApplicationTree GetByAlias(string treeAlias); + + /// + /// Gets all applicationTrees registered in umbraco from the umbracoAppTree table.. + /// + /// Returns a ApplicationTree Array + IEnumerable GetAll(); + + /// + /// Gets the application tree for the applcation with the specified alias + /// + /// The application alias. + /// Returns a ApplicationTree Array + IEnumerable GetApplicationTrees(string applicationAlias); + + ///// + ///// Gets the application tree for the applcation with the specified alias + ///// + ///// The application alias. + ///// + ///// Returns a ApplicationTree Array + //IEnumerable GetApplicationTrees(string applicationAlias, bool onlyInitialized); + + /// + /// Gets the grouped application trees for the application with the specified alias + /// + /// + /// + IDictionary> GetGroupedApplicationTrees(string applicationAlias); + } + +} diff --git a/src/Umbraco.Web/Services/ApplicationTreeService.cs b/src/Umbraco.Web/Services/TreeService.cs similarity index 95% rename from src/Umbraco.Web/Services/ApplicationTreeService.cs rename to src/Umbraco.Web/Services/TreeService.cs index 72b26e26d3..cf010f1480 100644 --- a/src/Umbraco.Web/Services/ApplicationTreeService.cs +++ b/src/Umbraco.Web/Services/TreeService.cs @@ -18,18 +18,18 @@ using Umbraco.Web.Trees; namespace Umbraco.Web.Services { - internal class ApplicationTreeService : IApplicationTreeService + internal class TreeService : ITreeService { private readonly ILogger _logger; private readonly TreeCollection _treeCollection; private static readonly object Locker = new object(); private readonly Lazy>> _groupedTrees; - public ApplicationTreeService(ILogger logger, TreeCollection treeCollection) + public TreeService(ILogger logger, TreeCollection treeCollection) { _logger = logger; _treeCollection = treeCollection; - //_groupedTrees = new Lazy>>(InitGroupedTrees); + _groupedTrees = new Lazy>>(InitGroupedTrees); } ///// @@ -233,7 +233,7 @@ namespace Umbraco.Web.Services //} /// - public ApplicationTree GetByAlias(string treeAlias) => _treeCollection.FirstOrDefault(t => t.Alias == treeAlias); + public ApplicationTree GetByAlias(string treeAlias) => _treeCollection.FirstOrDefault(t => t.TreeAlias == treeAlias); /// public IEnumerable GetAll() => _treeCollection; @@ -273,7 +273,7 @@ namespace Umbraco.Web.Services { foreach(var treeAliasInGroup in treeGroup) { - if (tree.Alias == treeAliasInGroup) + if (tree.TreeAlias == treeAliasInGroup) { if (resultGroup == null) resultGroup = new List(); resultGroup.Add(tree); @@ -286,21 +286,21 @@ namespace Umbraco.Web.Services return result; } - ///// - ///// Creates a group of all tree groups and their tree aliases - ///// - ///// - ///// - ///// Used to initialize the field - ///// - //private IReadOnlyCollection> InitGroupedTrees() - //{ - // var result = GetAll() - // .Select(x => (treeAlias: x.Alias, treeGroup: x.GetRuntimeType().GetCustomAttribute(false)?.TreeGroup)) - // .GroupBy(x => x.treeGroup, x => x.treeAlias) - // .ToList(); - // return result; - //} + /// + /// Creates a group of all tree groups and their tree aliases + /// + /// + /// + /// Used to initialize the field + /// + private IReadOnlyCollection> InitGroupedTrees() + { + var result = GetAll() + .Select(x => (treeAlias: x.TreeAlias, treeGroup: x.TreeControllerType.GetCustomAttribute(false)?.TreeGroup)) + .GroupBy(x => x.treeGroup, x => x.treeAlias) + .ToList(); + return result; + } ///// ///// Loads in the xml structure from disk if one is found, otherwise loads in an empty xml structure, calls the diff --git a/src/Umbraco.Web/Trees/ApplicationTree.cs b/src/Umbraco.Web/Trees/ApplicationTree.cs new file mode 100644 index 0000000000..5ed9847be3 --- /dev/null +++ b/src/Umbraco.Web/Trees/ApplicationTree.cs @@ -0,0 +1,69 @@ +using System; +using System.Diagnostics; +using Umbraco.Core.Services; +using Umbraco.Web.Models.Trees; + +namespace Umbraco.Web.Trees +{ + [DebuggerDisplay("Tree - {TreeAlias} ({ApplicationAlias})")] + public class ApplicationTree : ITree + { + public ApplicationTree(int sortOrder, string applicationAlias, string alias, string title, Type treeControllerType, bool isSingleNodeTree) + { + SortOrder = sortOrder; + ApplicationAlias = applicationAlias; + TreeAlias = alias; + TreeTitle = title; + TreeControllerType = treeControllerType; + IsSingleNodeTree = isSingleNodeTree; + } + + /// + /// + /// Gets or sets the sort order. + /// + public int SortOrder { get; set; } + + /// + /// Gets the application alias. + /// + public string ApplicationAlias { get; set; } + + /// + public string TreeAlias { get; } + + /// + /// + /// Gets or sets the tree title (fallback if the tree alias isn't localized) + /// + /// The title. + public string TreeTitle { get; set; } + + public bool IsSingleNodeTree { get; } + + public Type TreeControllerType { get; } + + public static string GetRootNodeDisplayName(ITree tree, ILocalizedTextService textService) + { + var label = $"[{tree.TreeAlias}]"; + + // try to look up a the localized tree header matching the tree alias + var localizedLabel = textService.Localize("treeHeaders/" + tree.TreeAlias); + + // if the localizedLabel returns [alias] then return the title if it's defined + if (localizedLabel != null && localizedLabel.Equals(label, StringComparison.InvariantCultureIgnoreCase)) + { + if (string.IsNullOrEmpty(tree.TreeTitle) == false) + label = tree.TreeTitle; + } + else + { + // the localizedLabel translated into something that's not just [alias], so use the translation + label = localizedLabel; + } + + return label; + } + + } +} diff --git a/src/Umbraco.Web/Trees/ApplicationTreeController.cs b/src/Umbraco.Web/Trees/ApplicationTreeController.cs index 7e7c77d607..0e405ca3f3 100644 --- a/src/Umbraco.Web/Trees/ApplicationTreeController.cs +++ b/src/Umbraco.Web/Trees/ApplicationTreeController.cs @@ -3,9 +3,13 @@ using System.Collections.Generic; using System.Globalization; using System.Linq; using System.Net; +using System.Net.Http; using System.Net.Http.Formatting; using System.Threading.Tasks; using System.Web.Http; +using System.Web.Http.Controllers; +using System.Web.Http.Routing; +using System.Web.Mvc; using Umbraco.Core; using Umbraco.Core.Cache; using Umbraco.Core.Configuration; @@ -24,19 +28,20 @@ using Constants = Umbraco.Core.Constants; namespace Umbraco.Web.Trees { + /// + /// Used to return tree root nodes + /// [AngularJsonOnlyConfiguration] [PluginController("UmbracoTrees")] public class ApplicationTreeController : UmbracoAuthorizedApiController { - private readonly TreeControllerResolver _treeControllerResolver; - private readonly IApplicationTreeService _treeService; + private readonly ITreeService _treeService; public ApplicationTreeController(IGlobalSettings globalSettings, UmbracoContext umbracoContext, ISqlContext sqlContext, ServiceContext services, CacheHelper applicationCache, IProfilingLogger logger, - IRuntimeState runtimeState, TreeControllerResolver treeControllerResolver, IApplicationTreeService treeService) + IRuntimeState runtimeState, ITreeService treeService) : base(globalSettings, umbracoContext, sqlContext, services, applicationCache, logger, runtimeState) { - _treeControllerResolver = treeControllerResolver; _treeService = treeService; } @@ -46,10 +51,9 @@ namespace Umbraco.Web.Trees /// The application to load tree for /// An optional single tree alias, if specified will only load the single tree for the request app /// - /// An optional bool (defaults to true), if set to false it will also load uninitialized trees /// [HttpQueryStringFilter("queryStrings")] - public async Task GetApplicationTrees(string application, string tree, FormDataCollection queryStrings/*, bool onlyInitialized = true*/) + public async Task GetApplicationTrees(string application, string tree, FormDataCollection queryStrings) { application = application.CleanForXss(); @@ -62,7 +66,7 @@ namespace Umbraco.Web.Trees if (string.IsNullOrEmpty(tree) == false || allTrees.Count == 1) { var apptree = !tree.IsNullOrWhiteSpace() - ? allTrees.FirstOrDefault(x => x.Alias == tree) + ? allTrees.FirstOrDefault(x => x.TreeAlias == tree) : allTrees.FirstOrDefault(); if (apptree == null) throw new HttpResponseException(HttpStatusCode.NotFound); @@ -153,15 +157,15 @@ namespace Umbraco.Web.Trees /// /// Get the root node for an application with multiple trees /// - /// + /// /// /// - private async Task GetRootForMultipleAppTree(ApplicationTree configTree, FormDataCollection queryStrings) + private async Task GetRootForMultipleAppTree(ApplicationTree tree, FormDataCollection queryStrings) { - if (configTree == null) throw new ArgumentNullException(nameof(configTree)); + if (tree == null) throw new ArgumentNullException(nameof(tree)); try { - var byControllerAttempt = await _treeControllerResolver.TryGetRootNodeFromControllerTree(configTree, queryStrings, ControllerContext); + var byControllerAttempt = await TryGetRootNodeFromControllerTree(tree, queryStrings, ControllerContext); if (byControllerAttempt.Success) { return byControllerAttempt.Result; @@ -174,54 +178,133 @@ namespace Umbraco.Web.Trees return null; } - throw new ApplicationException("Could not get root node for tree type " + configTree.Alias); + throw new ApplicationException("Could not get root node for tree type " + tree.TreeAlias); } /// /// Get the root node for an application with one tree /// - /// + /// /// /// /// /// - private async Task GetRootForSingleAppTree(ApplicationTree configTree, string id, FormDataCollection queryStrings, string application) + private async Task GetRootForSingleAppTree(ApplicationTree tree, string id, FormDataCollection queryStrings, string application) { var rootId = Constants.System.Root.ToString(CultureInfo.InvariantCulture); - if (configTree == null) throw new ArgumentNullException(nameof(configTree)); - var byControllerAttempt = _treeControllerResolver.TryLoadFromControllerTree(configTree, id, queryStrings, ControllerContext); - if (byControllerAttempt.Success) + if (tree == null) throw new ArgumentNullException(nameof(tree)); + var byControllerAttempt = TryLoadFromControllerTree(tree, id, queryStrings, ControllerContext); + if (!byControllerAttempt.Success) + throw new ApplicationException("Could not render a tree for type " + tree.TreeAlias); + + var rootNode = await TryGetRootNodeFromControllerTree(tree, queryStrings, ControllerContext); + if (rootNode.Success == false) { - var rootNode = await _treeControllerResolver.TryGetRootNodeFromControllerTree(configTree, queryStrings, ControllerContext); - if (rootNode.Success == false) - { - //This should really never happen if we've successfully got the children above. - throw new InvalidOperationException("Could not create root node for tree " + configTree.Alias); - } - - var treeAttribute = _treeControllerResolver.GetTreeAttribute(configTree); - - var sectionRoot = TreeRootNode.CreateSingleTreeRoot( - rootId, - rootNode.Result.ChildNodesUrl, - rootNode.Result.MenuUrl, - rootNode.Result.Name, - byControllerAttempt.Result, - treeAttribute.IsSingleNodeTree); - - //assign the route path based on the root node, this means it will route there when the section is navigated to - //and no dashboards will be available for this section - sectionRoot.RoutePath = rootNode.Result.RoutePath; - - foreach (var d in rootNode.Result.AdditionalData) - { - sectionRoot.AdditionalData[d.Key] = d.Value; - } - return sectionRoot; - + //This should really never happen if we've successfully got the children above. + throw new InvalidOperationException("Could not create root node for tree " + tree.TreeAlias); } - throw new ApplicationException("Could not render a tree for type " + configTree.Alias); + var sectionRoot = TreeRootNode.CreateSingleTreeRoot( + rootId, + rootNode.Result.ChildNodesUrl, + rootNode.Result.MenuUrl, + rootNode.Result.Name, + byControllerAttempt.Result, + tree.IsSingleNodeTree); + + //assign the route path based on the root node, this means it will route there when the section is navigated to + //and no dashboards will be available for this section + sectionRoot.RoutePath = rootNode.Result.RoutePath; + + foreach (var d in rootNode.Result.AdditionalData) + { + sectionRoot.AdditionalData[d.Key] = d.Value; + } + return sectionRoot; + } + + /// + /// Proxies a request to the destination tree controller to get it's root tree node + /// + /// + /// + /// + /// + /// + /// This ensures that authorization filters are applied to the sub request + /// + private async Task> TryGetRootNodeFromControllerTree(ApplicationTree appTree, FormDataCollection formCollection, HttpControllerContext controllerContext) + { + //instantiate it, since we are proxying, we need to setup the instance with our current context + var instance = (TreeController)DependencyResolver.Current.GetService(appTree.TreeControllerType); + + //NOTE: This is all required in order to execute the auth-filters for the sub request, we + // need to "trick" web-api into thinking that it is actually executing the proxied controller. + + var urlHelper = controllerContext.Request.GetUrlHelper(); + //create the proxied URL for the controller action + var proxiedUrl = controllerContext.Request.RequestUri.GetLeftPart(UriPartial.Authority) + + urlHelper.GetUmbracoApiService("GetRootNode", instance.GetType()); + //add the query strings to it + proxiedUrl += "?" + formCollection.ToQueryString(); + //create proxy route data specifying the action / controller to execute + var proxiedRouteData = new HttpRouteData( + controllerContext.RouteData.Route, + new HttpRouteValueDictionary(new { action = "GetRootNode", controller = ControllerExtensions.GetControllerName(instance.GetType()) })); + + //create a proxied controller context + var proxiedControllerContext = new HttpControllerContext( + controllerContext.Configuration, + proxiedRouteData, + new HttpRequestMessage(HttpMethod.Get, proxiedUrl)) + { + ControllerDescriptor = new HttpControllerDescriptor(controllerContext.ControllerDescriptor.Configuration, ControllerExtensions.GetControllerName(instance.GetType()), instance.GetType()), + RequestContext = controllerContext.RequestContext + }; + + instance.ControllerContext = proxiedControllerContext; + instance.Request = controllerContext.Request; + instance.RequestContext.RouteData = proxiedRouteData; + + //invoke auth filters for this sub request + var result = await instance.ControllerContext.InvokeAuthorizationFiltersForRequest(); + //if a result is returned it means they are unauthorized, just throw the response. + if (result != null) + { + throw new HttpResponseException(result); + } + + //return the root + var node = instance.GetRootNode(formCollection); + return node == null + ? Attempt.Fail(new InvalidOperationException("Could not return a root node for tree " + appTree.TreeAlias)) + : Attempt.Succeed(node); + } + + /// + /// Proxies a request to the destination tree controller to get it's tree node collection + /// + /// + /// + /// + /// + /// + private Attempt TryLoadFromControllerTree(ApplicationTree appTree, string id, FormDataCollection formCollection, HttpControllerContext controllerContext) + { + // instantiate it, since we are proxying, we need to setup the instance with our current context + var instance = (TreeController)DependencyResolver.Current.GetService(appTree.TreeControllerType); + if (instance == null) + throw new Exception("Failed to create tree " + appTree.TreeControllerType + "."); + + //TODO: Shouldn't we be applying the same proxying logic as above so that filters work? seems like an oversight + + instance.ControllerContext = controllerContext; + instance.Request = controllerContext.Request; + + // return its data + return Attempt.Succeed(instance.GetNodes(id, formCollection)); + } + } } diff --git a/src/Umbraco.Web/Trees/ITree.cs b/src/Umbraco.Web/Trees/ITree.cs new file mode 100644 index 0000000000..40be7338b0 --- /dev/null +++ b/src/Umbraco.Web/Trees/ITree.cs @@ -0,0 +1,31 @@ +namespace Umbraco.Web.Trees +{ + public interface ITree + { + /// + /// Gets or sets the sort order. + /// + /// The sort order. + int SortOrder { get; } + + /// + /// Gets the section alias. + /// + string ApplicationAlias { get; } + + /// + /// Gets the tree alias. + /// + string TreeAlias { get; } + + /// + /// Gets or sets the tree title (fallback if the tree alias isn't localized) + /// + string TreeTitle { get; } + + /// + /// Flag to define if this tree is a single node tree (will never contain child nodes, full screen app) + /// + bool IsSingleNodeTree { get; } + } +} diff --git a/src/Umbraco.Web/Trees/TreeAttribute.cs b/src/Umbraco.Web/Trees/TreeAttribute.cs index 1cf23c549f..dd63f8c172 100644 --- a/src/Umbraco.Web/Trees/TreeAttribute.cs +++ b/src/Umbraco.Web/Trees/TreeAttribute.cs @@ -1,4 +1,5 @@ using System; +using Umbraco.Web.Models.Trees; namespace Umbraco.Web.Trees { @@ -6,15 +7,15 @@ namespace Umbraco.Web.Trees /// Identifies an application tree /// [AttributeUsage(AttributeTargets.Class, AllowMultiple = false)] - public class TreeAttribute : Attribute + public class TreeAttribute : Attribute, ITree { /// /// Initializes a new instance of the class. /// /// The app alias. - /// The alias. + /// public TreeAttribute(string appAlias, - string alias) : this(appAlias, alias, null) + string treeAlias) : this(appAlias, treeAlias, null) { } @@ -22,16 +23,16 @@ namespace Umbraco.Web.Trees /// Initializes a new instance of the class. /// /// The app alias. - /// The alias. - /// The title. + /// + /// /// The icon closed. /// The icon open. /// if set to true [initialize]. /// The sort order. /// Flag to define if this tree is a single node tree (will never contain child nodes, full screen app) public TreeAttribute(string appAlias, - string alias, - string title, + string treeAlias, + string treeTitle, string iconClosed = "icon-folder", string iconOpen = "icon-folder-open", bool initialize = true, @@ -39,8 +40,8 @@ namespace Umbraco.Web.Trees bool isSingleNodeTree = false) { ApplicationAlias = appAlias; - Alias = alias; - Title = title; + TreeAlias = treeAlias; + TreeTitle = treeTitle; IconClosed = iconClosed; IconOpen = iconOpen; Initialize = initialize; @@ -48,17 +49,17 @@ namespace Umbraco.Web.Trees IsSingleNodeTree = isSingleNodeTree; } - public string ApplicationAlias { get; private set; } - public string Alias { get; private set; } - public string Title { get; private set; } - public string IconClosed { get; private set; } - public string IconOpen { get; private set; } - public bool Initialize { get; private set; } - public int SortOrder { get; private set; } + public string ApplicationAlias { get; } + public string TreeAlias { get; } + public string TreeTitle { get; } + public string IconClosed { get; } + public string IconOpen { get; } + public bool Initialize { get; } + public int SortOrder { get; } /// /// Flag to define if this tree is a single node tree (will never contain child nodes, full screen app) /// - public bool IsSingleNodeTree { get; private set; } + public bool IsSingleNodeTree { get; } } } diff --git a/src/Umbraco.Web/Trees/TreeCollection.cs b/src/Umbraco.Web/Trees/TreeCollection.cs index 8f913fb2d7..c7b60dea16 100644 --- a/src/Umbraco.Web/Trees/TreeCollection.cs +++ b/src/Umbraco.Web/Trees/TreeCollection.cs @@ -21,7 +21,26 @@ namespace Umbraco.Web.Trees { protected override TreeCollectionBuilder This => this; - //TODO: can we allow for re-ordering OOTB without exposing other methods? + private readonly List _instances = new List(); + + public void AddTree(ApplicationTree tree) + { + _instances.Add(tree); + } + + protected override IEnumerable CreateItems(IFactory factory) + { + return _instances; + + //var items = base.CreateItems(factory).ToList(); + //throw new NotImplementedException(); + ////validate the items, no actions should exist that do not either expose notifications or permissions + //var invalidItems = items.Where(x => !x.CanBePermissionAssigned && !x.ShowInNotifier).ToList(); + //if (invalidItems.Count == 0) return items; + + //var invalidActions = string.Join(", ", invalidItems.Select(x => "'" + x.Alias + "'")); + //throw new InvalidOperationException($"Invalid actions {invalidActions}'. All {typeof(IAction)} implementations must be true for either {nameof(IAction.CanBePermissionAssigned)} or {nameof(IAction.ShowInNotifier)}."); + } } } diff --git a/src/Umbraco.Web/Trees/TreeController.cs b/src/Umbraco.Web/Trees/TreeController.cs index 102671ec29..63e8f5aad5 100644 --- a/src/Umbraco.Web/Trees/TreeController.cs +++ b/src/Umbraco.Web/Trees/TreeController.cs @@ -1,4 +1,6 @@ using System; +using System.Collections.Concurrent; +using System.Linq; using Umbraco.Core; using Umbraco.Core.Cache; using Umbraco.Core.Configuration; @@ -14,10 +16,10 @@ namespace Umbraco.Web.Trees public abstract class TreeController : TreeControllerBase { private TreeAttribute _attribute; - private string _rootNodeDisplayName; protected TreeController(IGlobalSettings globalSettings, UmbracoContext umbracoContext, ISqlContext sqlContext, ServiceContext services, CacheHelper applicationCache, IProfilingLogger logger, IRuntimeState runtimeState) : base(globalSettings, umbracoContext, sqlContext, services, applicationCache, logger, runtimeState) { + Initialize(); } protected TreeController() @@ -25,29 +27,42 @@ namespace Umbraco.Web.Trees Initialize(); } - /// - /// The name to display on the root node - /// - public override string RootNodeDisplayName - { - get - { - throw new NotImplementedException(); - //return _rootNodeDisplayName - // ?? (_rootNodeDisplayName = Services.ApplicationTreeService.GetByAlias(_attribute.Alias) - // ?.GetRootNodeDisplayName(Services.TextService)); - } - } + /// + public override string RootNodeDisplayName => ApplicationTree.GetRootNodeDisplayName(this, Services.TextService); - /// - /// Gets the current tree alias from the attribute assigned to it. - /// - public override string TreeAlias => _attribute.Alias; + /// + public override string TreeAlias => _attribute.TreeAlias; + /// + public override string TreeTitle => _attribute.TreeTitle; + /// + public override string ApplicationAlias => _attribute.ApplicationAlias; + /// + public override int SortOrder => _attribute.SortOrder; + /// + public override bool IsSingleNodeTree => _attribute.IsSingleNodeTree; private void Initialize() { - throw new NotImplementedException(); - //_attribute = GetType().GetTreeAttribute(); + _attribute = GetTreeAttribute(); + } + + private static readonly ConcurrentDictionary TreeAttributeCache = new ConcurrentDictionary(); + + private TreeAttribute GetTreeAttribute() + { + return TreeAttributeCache.GetOrAdd(GetType(), type => + { + //Locate the tree attribute + var treeAttributes = type + .GetCustomAttributes(false) + .ToArray(); + + if (treeAttributes.Length == 0) + throw new InvalidOperationException("The Tree controller is missing the " + typeof(TreeAttribute).FullName + " attribute"); + + //assign the properties of this object to those of the metadata attribute + return treeAttributes[0]; + }); } } } diff --git a/src/Umbraco.Web/Trees/TreeControllerBase.cs b/src/Umbraco.Web/Trees/TreeControllerBase.cs index c00d6053c8..7a027033fc 100644 --- a/src/Umbraco.Web/Trees/TreeControllerBase.cs +++ b/src/Umbraco.Web/Trees/TreeControllerBase.cs @@ -25,7 +25,7 @@ namespace Umbraco.Web.Trees /// Developers should generally inherit from TreeController. /// [AngularJsonOnlyConfiguration] - public abstract class TreeControllerBase : UmbracoAuthorizedApiController + public abstract class TreeControllerBase : UmbracoAuthorizedApiController, ITree { protected TreeControllerBase() { @@ -62,10 +62,16 @@ namespace Umbraco.Web.Trees /// public abstract string RootNodeDisplayName { get; } - /// - /// Gets the current tree alias from the attribute assigned to it. - /// + /// public abstract string TreeAlias { get; } + /// + public abstract string TreeTitle { get; } + /// + public abstract string ApplicationAlias { get; } + /// + public abstract int SortOrder { get; } + /// + public abstract bool IsSingleNodeTree { get; } /// /// Returns the root node for the tree diff --git a/src/Umbraco.Web/Trees/TreeControllerResolver.cs b/src/Umbraco.Web/Trees/TreeControllerResolver.cs deleted file mode 100644 index 62cafbb5dd..0000000000 --- a/src/Umbraco.Web/Trees/TreeControllerResolver.cs +++ /dev/null @@ -1,203 +0,0 @@ -using System; -using System.Collections.Concurrent; -using System.Linq; -using System.Management.Instrumentation; -using System.Net.Http; -using System.Net.Http.Formatting; -using System.Threading.Tasks; -using System.Web.Http; -using System.Web.Http.Controllers; -using System.Web.Http.Routing; -using System.Web.Mvc; -using Umbraco.Core; -using Umbraco.Web.Models.Trees; -using Umbraco.Web.Mvc; -using Umbraco.Web.WebApi; -using Umbraco.Core.Composing; -using ApplicationTree = Umbraco.Web.Models.ContentEditing.ApplicationTree; - -namespace Umbraco.Web.Trees -{ - public class TreeControllerResolver - { - private readonly TreeCollection _trees; - private readonly UmbracoApiControllerTypeCollection _apiControllers; - - public TreeControllerResolver(TreeCollection trees, UmbracoApiControllerTypeCollection apiControllers) - { - _trees = trees; - _apiControllers = apiControllers; - } - - private static readonly ConcurrentDictionary TreeAttributeCache = new ConcurrentDictionary(); - private static readonly ConcurrentDictionary ResolvedControllerTypes = new ConcurrentDictionary(); - - private TreeAttribute GetTreeAttribute(Type treeControllerType) - { - return TreeAttributeCache.GetOrAdd(treeControllerType, type => - { - //Locate the tree attribute - var treeAttributes = type - .GetCustomAttributes(false) - .ToArray(); - - if (treeAttributes.Length == 0) - { - throw new InvalidOperationException("The Tree controller is missing the " + typeof(TreeAttribute).FullName + " attribute"); - } - - //assign the properties of this object to those of the metadata attribute - return treeAttributes[0]; - }); - } - - internal TreeAttribute GetTreeAttribute(ApplicationTree tree) - { - throw new NotImplementedException(); - //return ResolvedControllerTypes.GetOrAdd(tree.Alias, s => - //{ - // var controllerType = _apiControllers - // .OfType() - // .FirstOrDefault(x => x.) - //}); - - //return GetTreeAttribute(tree.GetRuntimeType()); - } - - private Type GetControllerType(ApplicationTree tree) - { - throw new NotImplementedException(); - } - - - internal Attempt TryGetControllerTree(ApplicationTree appTree) - { - throw new NotImplementedException(); - - ////get reference to all TreeApiControllers - //var controllerTrees = _apiControllers - // .Where(TypeHelper.IsTypeAssignableFrom) - // .ToArray(); - - ////find the one we're looking for - //var foundControllerTree = controllerTrees.FirstOrDefault(x => x == appTree.GetRuntimeType()); - //if (foundControllerTree == null) - //{ - // return Attempt.Fail(new InstanceNotFoundException("Could not find tree of type " + appTree.Type + " in any loaded DLLs")); - //} - //return Attempt.Succeed(foundControllerTree); - } - - /// - /// This will go and get the root node from a controller tree by executing the tree's GetRootNode method - /// - /// - /// - /// - /// - /// - /// This ensures that authorization filters are applied to the sub request - /// - internal async Task> TryGetRootNodeFromControllerTree(ApplicationTree appTree, FormDataCollection formCollection, HttpControllerContext controllerContext) - { - var foundControllerTreeAttempt = TryGetControllerTree(appTree); - if (foundControllerTreeAttempt.Success == false) - { - return Attempt.Fail(foundControllerTreeAttempt.Exception); - } - - var foundControllerTree = foundControllerTreeAttempt.Result; - //instantiate it, since we are proxying, we need to setup the instance with our current context - var instance = (TreeController)DependencyResolver.Current.GetService(foundControllerTree); - - //NOTE: This is all required in order to execute the auth-filters for the sub request, we - // need to "trick" web-api into thinking that it is actually executing the proxied controller. - - var urlHelper = controllerContext.Request.GetUrlHelper(); - //create the proxied URL for the controller action - var proxiedUrl = controllerContext.Request.RequestUri.GetLeftPart(UriPartial.Authority) + - urlHelper.GetUmbracoApiService("GetRootNode", instance.GetType()); - //add the query strings to it - proxiedUrl += "?" + formCollection.ToQueryString(); - //create proxy route data specifying the action / controller to execute - var proxiedRouteData = new HttpRouteData( - controllerContext.RouteData.Route, - new HttpRouteValueDictionary(new {action = "GetRootNode", controller = ControllerExtensions.GetControllerName(instance.GetType())})); - - //create a proxied controller context - var proxiedControllerContext = new HttpControllerContext( - controllerContext.Configuration, - proxiedRouteData, - new HttpRequestMessage(HttpMethod.Get, proxiedUrl)) - { - ControllerDescriptor = new HttpControllerDescriptor(controllerContext.ControllerDescriptor.Configuration, ControllerExtensions.GetControllerName(instance.GetType()), instance.GetType()) - }; - - if (WebApiVersionCheck.WebApiVersion >= Version.Parse("5.0.0")) - { - //fixme - will this 'just' work now? - proxiedControllerContext.RequestContext = controllerContext.RequestContext; - - ////In WebApi2, this is required to be set: - //// proxiedControllerContext.RequestContext = controllerContext.RequestContext - //// but we need to do this with reflection because of codebase changes between version 4/5 - ////NOTE: Use TypeHelper here since the reflection is cached - //var controllerContextRequestContext = TypeHelper.GetProperty(controllerContext.GetType(), "RequestContext").GetValue(controllerContext); - //TypeHelper.GetProperty(proxiedControllerContext.GetType(), "RequestContext").SetValue(proxiedControllerContext, controllerContextRequestContext); - } - - instance.ControllerContext = proxiedControllerContext; - instance.Request = controllerContext.Request; - - if (WebApiVersionCheck.WebApiVersion >= Version.Parse("5.0.0")) - { - - //fixme - will this 'just' work now? - instance.RequestContext.RouteData = proxiedRouteData; - - ////now we can change the request context's route data to be the proxied route data - NOTE: we cannot do this directly above - //// because it will detect that the request context is different throw an exception. This is a change in webapi2 and we need to set - //// this with reflection due to codebase changes between version 4/5 - //// instance.RequestContext.RouteData = proxiedRouteData; - ////NOTE: Use TypeHelper here since the reflection is cached - //var instanceRequestContext = TypeHelper.GetProperty(typeof(ApiController), "RequestContext").GetValue(instance); - //TypeHelper.GetProperty(instanceRequestContext.GetType(), "RouteData").SetValue(instanceRequestContext, proxiedRouteData); - } - - //invoke auth filters for this sub request - var result = await instance.ControllerContext.InvokeAuthorizationFiltersForRequest(); - //if a result is returned it means they are unauthorized, just throw the response. - if (result != null) - { - throw new HttpResponseException(result); - } - - //return the root - var node = instance.GetRootNode(formCollection); - return node == null - ? Attempt.Fail(new InvalidOperationException("Could not return a root node for tree " + appTree.Alias)) - : Attempt.Succeed(node); - } - - internal Attempt TryLoadFromControllerTree(ApplicationTree appTree, string id, FormDataCollection formCollection, HttpControllerContext controllerContext) - { - var foundControllerTreeAttempt = TryGetControllerTree(appTree); - if (foundControllerTreeAttempt.Success == false) - return Attempt.Fail(foundControllerTreeAttempt.Exception); - - // instantiate it, since we are proxying, we need to setup the instance with our current context - var foundControllerTree = foundControllerTreeAttempt.Result; - var instance = (TreeController) DependencyResolver.Current.GetService(foundControllerTree); - if (instance == null) - throw new Exception("Failed to get tree " + foundControllerTree.FullName + "."); - - instance.ControllerContext = controllerContext; - instance.Request = controllerContext.Request; - - // return its data - return Attempt.Succeed(instance.GetNodes(id, formCollection)); - } - - } - -} diff --git a/src/Umbraco.Web/Trees/UserPermissionsTreeController.cs b/src/Umbraco.Web/Trees/UserPermissionsTreeController.cs deleted file mode 100644 index 5473fee7bb..0000000000 --- a/src/Umbraco.Web/Trees/UserPermissionsTreeController.cs +++ /dev/null @@ -1,52 +0,0 @@ -using System; -using System.Linq; -using System.Net.Http.Formatting; -using Umbraco.Core; -using Umbraco.Web.Models.Trees; -using Umbraco.Web.Mvc; -using Umbraco.Web.WebApi.Filters; - -using Constants = Umbraco.Core.Constants; - -namespace Umbraco.Web.Trees -{ - [UmbracoTreeAuthorize(Constants.Trees.UserPermissions)] - [Tree(Constants.Applications.Users, Constants.Trees.UserPermissions, null, sortOrder: 2)] - [PluginController("UmbracoTrees")] - [CoreTree] - public class UserPermissionsTreeController : TreeController - { - protected override TreeNodeCollection GetTreeNodes(string id, FormDataCollection queryStrings) - { - var nodes = new TreeNodeCollection(); - long totalUsers; - nodes.AddRange( - Services.UserService.GetAll(0, int.MaxValue, out totalUsers) - .Where(x => x.Id != Constants.Security.SuperUserId && x.IsApproved) - .Select(x => CreateTreeNode(x.Id.ToString(), - id, - queryStrings, - x.Name, - "icon-user", - false, - "/" + queryStrings.GetValue("application") + "/framed/" - + Uri.EscapeDataString("users/PermissionEditor.aspx?id=" + x.Id)))); - - return nodes; - } - - protected override MenuItemCollection GetMenuForNode(string id, FormDataCollection queryStrings) - { - var menu = new MenuItemCollection(); - - if (id == Constants.System.Root.ToInvariantString()) - { - // root actions - menu.Items.Add(new RefreshNode(Services.TextService, true)); - return menu; - } - - return menu; - } - } -} diff --git a/src/Umbraco.Web/Umbraco.Web.csproj b/src/Umbraco.Web/Umbraco.Web.csproj index f1d15e9ea6..0b1603c9e3 100755 --- a/src/Umbraco.Web/Umbraco.Web.csproj +++ b/src/Umbraco.Web/Umbraco.Web.csproj @@ -166,8 +166,9 @@ - + + @@ -183,7 +184,7 @@ - + @@ -551,7 +552,6 @@ - @@ -649,7 +649,7 @@ - + @@ -972,7 +972,6 @@ - @@ -1056,7 +1055,6 @@ - diff --git a/src/Umbraco.Web/WebApi/Filters/UmbracoTreeAuthorizeAttribute.cs b/src/Umbraco.Web/WebApi/Filters/UmbracoTreeAuthorizeAttribute.cs index cc483db416..5ad3da7f4d 100644 --- a/src/Umbraco.Web/WebApi/Filters/UmbracoTreeAuthorizeAttribute.cs +++ b/src/Umbraco.Web/WebApi/Filters/UmbracoTreeAuthorizeAttribute.cs @@ -41,18 +41,16 @@ namespace Umbraco.Web.WebApi.Filters return true; } - throw new NotImplementedException(); + var apps = _treeAliases.Select(x => Current.TreeService + .GetByAlias(x)) + .WhereNotNull() + .Select(x => x.ApplicationAlias) + .Distinct() + .ToArray(); - //var apps = _treeAliases.Select(x => Current.Services.ApplicationTreeService - // .GetByAlias(x)) - // .WhereNotNull() - // .Select(x => x.ApplicationAlias) - // .Distinct() - // .ToArray(); - - //return Current.UmbracoContext.Security.CurrentUser != null - // && apps.Any(app => Current.UmbracoContext.Security.UserHasSectionAccess( - // app, Current.UmbracoContext.Security.CurrentUser)); + return Current.UmbracoContext.Security.CurrentUser != null + && apps.Any(app => Current.UmbracoContext.Security.UserHasSectionAccess( + app, Current.UmbracoContext.Security.CurrentUser)); } } } diff --git a/src/Umbraco.Web/WebApi/MvcVersionCheck.cs b/src/Umbraco.Web/WebApi/MvcVersionCheck.cs deleted file mode 100644 index 3c84fa91ce..0000000000 --- a/src/Umbraco.Web/WebApi/MvcVersionCheck.cs +++ /dev/null @@ -1,10 +0,0 @@ -namespace Umbraco.Web.WebApi -{ - internal class WebApiVersionCheck - { - public static System.Version WebApiVersion - { - get { return typeof(System.Web.Http.ApiController).Assembly.GetName().Version; } - } - } -} diff --git a/src/Umbraco.Web/WebApi/UmbracoApiControllerTypeCollection.cs b/src/Umbraco.Web/WebApi/UmbracoApiControllerTypeCollection.cs index d84ab3fe4a..cdb1aa2f51 100644 --- a/src/Umbraco.Web/WebApi/UmbracoApiControllerTypeCollection.cs +++ b/src/Umbraco.Web/WebApi/UmbracoApiControllerTypeCollection.cs @@ -8,8 +8,6 @@ namespace Umbraco.Web.WebApi // which we are not doing at the moment // we can inherit from BuilderCollectionBase and just be enumerable - //fixme: this should be LazyCollectionBuilderBase ? - public class UmbracoApiControllerTypeCollection : BuilderCollectionBase { public UmbracoApiControllerTypeCollection(IEnumerable items) From 0160f141f4104c1048cf96f498b2dc1cc4a20e06 Mon Sep 17 00:00:00 2001 From: Shannon Date: Thu, 17 Jan 2019 17:04:53 +1100 Subject: [PATCH 03/11] cleanup and explicitly registering sections --- .../Services/SectionServiceTests.cs | 2 +- .../TreesAndSections/ApplicationTreeTest.cs | 397 ----------------- .../ResourceFiles.Designer.cs | 91 ---- .../TreesAndSections/ResourceFiles.resx | 127 ------ .../TreesAndSections/SectionTests.cs | 252 ----------- .../TreesAndSections/applications.config | 16 - .../TreesAndSections/trees.config | 8 - src/Umbraco.Tests/Umbraco.Tests.csproj | 13 - .../Cache/ApplicationTreeCacheRefresher.cs | 46 -- .../Cache/DistributedCacheBinder_Handlers.cs | 47 -- .../Cache/DistributedCacheExtensions.cs | 19 - .../ContentEditing/IBackOfficeSection.cs | 15 - .../Models/Mapping/SectionMapperProfile.cs | 1 + .../Models/Trees/ApplicationDefinitions.cs | 77 ---- .../Models/Trees/IBackOfficeSection.cs | 12 + .../{SectionRootNode.cs => TreeRootNode.cs} | 0 src/Umbraco.Web/Runtime/WebRuntimeComposer.cs | 11 +- src/Umbraco.Web/Services/ISectionService.cs | 1 + src/Umbraco.Web/Services/ITreeService.cs | 10 +- src/Umbraco.Web/Services/SectionService.cs | 253 +---------- src/Umbraco.Web/Services/TreeService.cs | 410 +----------------- .../Trees/BackOfficeSectionCollection.cs | 8 +- .../BackOfficeSectionCollectionBuilder.cs | 10 + .../Trees/ContentBackOfficeSection.cs | 15 + src/Umbraco.Web/Trees/ITree.cs | 1 + .../Trees/MediaBackOfficeSection.cs | 15 + .../Trees/MembersBackOfficeSection.cs | 15 + .../Trees/PackagesBackOfficeSection.cs | 15 + .../Trees/SettingsBackOfficeSection.cs | 15 + .../Trees/TranslationBackOfficeSection.cs | 15 + src/Umbraco.Web/Trees/TreeCollection.cs | 27 -- .../Trees/TreeCollectionBuilder.cs | 18 + .../Trees/UsersBackOfficeSection.cs | 15 + src/Umbraco.Web/Umbraco.Web.csproj | 15 +- 34 files changed, 183 insertions(+), 1809 deletions(-) delete mode 100644 src/Umbraco.Tests/TreesAndSections/ApplicationTreeTest.cs delete mode 100644 src/Umbraco.Tests/TreesAndSections/ResourceFiles.Designer.cs delete mode 100644 src/Umbraco.Tests/TreesAndSections/ResourceFiles.resx delete mode 100644 src/Umbraco.Tests/TreesAndSections/SectionTests.cs delete mode 100644 src/Umbraco.Tests/TreesAndSections/applications.config delete mode 100644 src/Umbraco.Tests/TreesAndSections/trees.config delete mode 100644 src/Umbraco.Web/Cache/ApplicationTreeCacheRefresher.cs delete mode 100644 src/Umbraco.Web/Models/ContentEditing/IBackOfficeSection.cs delete mode 100644 src/Umbraco.Web/Models/Trees/ApplicationDefinitions.cs create mode 100644 src/Umbraco.Web/Models/Trees/IBackOfficeSection.cs rename src/Umbraco.Web/Models/Trees/{SectionRootNode.cs => TreeRootNode.cs} (100%) create mode 100644 src/Umbraco.Web/Trees/BackOfficeSectionCollectionBuilder.cs create mode 100644 src/Umbraco.Web/Trees/ContentBackOfficeSection.cs create mode 100644 src/Umbraco.Web/Trees/MediaBackOfficeSection.cs create mode 100644 src/Umbraco.Web/Trees/MembersBackOfficeSection.cs create mode 100644 src/Umbraco.Web/Trees/PackagesBackOfficeSection.cs create mode 100644 src/Umbraco.Web/Trees/SettingsBackOfficeSection.cs create mode 100644 src/Umbraco.Web/Trees/TranslationBackOfficeSection.cs create mode 100644 src/Umbraco.Web/Trees/TreeCollectionBuilder.cs create mode 100644 src/Umbraco.Web/Trees/UsersBackOfficeSection.cs diff --git a/src/Umbraco.Tests/Services/SectionServiceTests.cs b/src/Umbraco.Tests/Services/SectionServiceTests.cs index 206c99ffbf..9211755251 100644 --- a/src/Umbraco.Tests/Services/SectionServiceTests.cs +++ b/src/Umbraco.Tests/Services/SectionServiceTests.cs @@ -16,7 +16,7 @@ namespace Umbraco.Tests.Services public class SectionServiceTests : TestWithSomeContentBase { //fixme - private ISectionService SectionService => new SectionService(ServiceContext.UserService, null, null); + private ISectionService SectionService => new SectionService(ServiceContext.UserService, null); [Test] diff --git a/src/Umbraco.Tests/TreesAndSections/ApplicationTreeTest.cs b/src/Umbraco.Tests/TreesAndSections/ApplicationTreeTest.cs deleted file mode 100644 index 95d90f1463..0000000000 --- a/src/Umbraco.Tests/TreesAndSections/ApplicationTreeTest.cs +++ /dev/null @@ -1,397 +0,0 @@ -//using System.IO; -//using NUnit.Framework; -//using Umbraco.Core.Services; -//using Umbraco.Tests.TestHelpers; -//using System; -//using System.Linq; -//using System.Threading; -//using Umbraco.Tests.Testing; -//using Umbraco.Web.Services; -//using Current = Umbraco.Web.Composing.Current; - -//namespace Umbraco.Tests.TreesAndSections -//{ - - -// /// -// ///This is a test class for ApplicationTreeTest and is intended -// ///to contain all ApplicationTreeTest Unit Tests -// /// -// [TestFixture] -// [Apartment(ApartmentState.STA)] -// [UmbracoTest(Database = UmbracoTestOptions.Database.NewSchemaPerTest)] -// public class ApplicationTreeTest : TestWithDatabaseBase -// { -// public override void SetUp() -// { -// base.SetUp(); - -// var treesConfig = TestHelper.MapPathForTest("~/TEMP/TreesAndSections/trees.config"); -// var appConfig = TestHelper.MapPathForTest("~/TEMP/TreesAndSections/applications.config"); -// Directory.CreateDirectory(TestHelper.MapPathForTest("~/TEMP/TreesAndSections")); -// using (var writer = File.CreateText(treesConfig)) -// { -// writer.Write(ResourceFiles.trees); -// } -// using (var writer = File.CreateText(appConfig)) -// { -// writer.Write(ResourceFiles.applications); -// } - -// //ApplicationTreeService.TreeConfigFilePath = treesConfig; -// SectionService.AppConfigFilePath = appConfig; -// } - -// public override void TearDown() -// { -// base.TearDown(); - -// if (Directory.Exists(TestHelper.MapPathForTest("~/TEMP/TreesAndSections"))) -// { -// Directory.Delete(TestHelper.MapPathForTest("~/TEMP/TreesAndSections"), true); -// } -// //ApplicationTreeService.TreeConfigFilePath = null; -// SectionService.AppConfigFilePath = null; -// } - -// ///// -// ///// Creates a new app tree linked to an application, then delete the application and make sure the tree is gone as well -// ///// -// //[Test()] -// //public void ApplicationTree_Make_New_Then_Delete_App() -// //{ -// // //create new app -// // var appName = Guid.NewGuid().ToString("N"); -// // var treeName = Guid.NewGuid().ToString("N"); -// // Current.Services.SectionService.MakeNew(appName, appName, "icon.jpg"); - -// // //check if it exists -// // var app = Current.Services.SectionService.GetByAlias(appName); -// // Assert.IsNotNull(app); - -// // //create the new app tree assigned to the new app -// // Current.Services.ApplicationTreeService.MakeNew(false, 0, app.Alias, treeName, treeName, "icon.jpg", "icon.jpg", "Umbraco.Web.Trees.ContentTreeController, Umbraco.Web"); -// // var tree = Current.Services.ApplicationTreeService.GetByAlias(treeName); -// // Assert.IsNotNull(tree); - -// // //now delete the app -// // Current.Services.SectionService.DeleteSection(app); - -// // //check that the tree is gone -// // Assert.AreEqual(0, Current.Services.ApplicationTreeService.GetApplicationTrees(treeName).Count()); -// //} - - -// #region Tests to write -// ///// -// /////A test for ApplicationTree Constructor -// ///// -// //[TestMethod()] -// //public void ApplicationTreeConstructorTest() -// //{ -// // bool silent = false; // TODO: Initialize to an appropriate value -// // bool initialize = false; // TODO: Initialize to an appropriate value -// // byte sortOrder = 0; // TODO: Initialize to an appropriate value -// // string applicationAlias = string.Empty; // TODO: Initialize to an appropriate value -// // string alias = string.Empty; // TODO: Initialize to an appropriate value -// // string title = string.Empty; // TODO: Initialize to an appropriate value -// // string iconClosed = string.Empty; // TODO: Initialize to an appropriate value -// // string iconOpened = string.Empty; // TODO: Initialize to an appropriate value -// // string assemblyName = string.Empty; // TODO: Initialize to an appropriate value -// // string type = string.Empty; // TODO: Initialize to an appropriate value -// // string action = string.Empty; // TODO: Initialize to an appropriate value -// // ApplicationTree target = new ApplicationTree(silent, initialize, sortOrder, applicationAlias, alias, title, iconClosed, iconOpened, assemblyName, type, action); -// // Assert.Inconclusive("TODO: Implement code to verify target"); -// //} - -// ///// -// /////A test for ApplicationTree Constructor -// ///// -// //[TestMethod()] -// //public void ApplicationTreeConstructorTest1() -// //{ -// // ApplicationTree target = new ApplicationTree(); -// // Assert.Inconclusive("TODO: Implement code to verify target"); -// //} - -// ///// -// /////A test for Delete -// ///// -// //[TestMethod()] -// //public void DeleteTest() -// //{ -// // ApplicationTree target = new ApplicationTree(); // TODO: Initialize to an appropriate value -// // target.Delete(); -// // Assert.Inconclusive("A method that does not return a value cannot be verified."); -// //} - - -// ///// -// /////A test for Save -// ///// -// //[TestMethod()] -// //public void SaveTest() -// //{ -// // ApplicationTree target = new ApplicationTree(); // TODO: Initialize to an appropriate value -// // target.Save(); -// // Assert.Inconclusive("A method that does not return a value cannot be verified."); -// //} - -// ///// -// /////A test for getAll -// ///// -// //[TestMethod()] -// //public void getAllTest() -// //{ -// // ApplicationTree[] expected = null; // TODO: Initialize to an appropriate value -// // ApplicationTree[] actual; -// // actual = ApplicationTree.getAll(); -// // Assert.AreEqual(expected, actual); -// // Assert.Inconclusive("Verify the correctness of this test method."); -// //} - -// ///// -// /////A test for getApplicationTree -// ///// -// //[TestMethod()] -// //public void getApplicationTreeTest() -// //{ -// // string applicationAlias = string.Empty; // TODO: Initialize to an appropriate value -// // ApplicationTree[] expected = null; // TODO: Initialize to an appropriate value -// // ApplicationTree[] actual; -// // actual = ApplicationTree.getApplicationTree(applicationAlias); -// // Assert.AreEqual(expected, actual); -// // Assert.Inconclusive("Verify the correctness of this test method."); -// //} - -// ///// -// /////A test for getApplicationTree -// ///// -// //[TestMethod()] -// //public void getApplicationTreeTest1() -// //{ -// // string applicationAlias = string.Empty; // TODO: Initialize to an appropriate value -// // bool onlyInitializedApplications = false; // TODO: Initialize to an appropriate value -// // ApplicationTree[] expected = null; // TODO: Initialize to an appropriate value -// // ApplicationTree[] actual; -// // actual = ApplicationTree.getApplicationTree(applicationAlias, onlyInitializedApplications); -// // Assert.AreEqual(expected, actual); -// // Assert.Inconclusive("Verify the correctness of this test method."); -// //} - -// ///// -// /////A test for getByAlias -// ///// -// //[TestMethod()] -// //public void getByAliasTest() -// //{ -// // string treeAlias = string.Empty; // TODO: Initialize to an appropriate value -// // ApplicationTree expected = null; // TODO: Initialize to an appropriate value -// // ApplicationTree actual; -// // actual = ApplicationTree.getByAlias(treeAlias); -// // Assert.AreEqual(expected, actual); -// // Assert.Inconclusive("Verify the correctness of this test method."); -// //} - -// ///// -// /////A test for Action -// ///// -// //[TestMethod()] -// //public void ActionTest() -// //{ -// // ApplicationTree target = new ApplicationTree(); // TODO: Initialize to an appropriate value -// // string expected = string.Empty; // TODO: Initialize to an appropriate value -// // string actual; -// // target.Action = expected; -// // actual = target.Action; -// // Assert.AreEqual(expected, actual); -// // Assert.Inconclusive("Verify the correctness of this test method."); -// //} - -// ///// -// /////A test for Alias -// ///// -// //[TestMethod()] -// //public void AliasTest() -// //{ -// // ApplicationTree target = new ApplicationTree(); // TODO: Initialize to an appropriate value -// // string actual; -// // actual = target.Alias; -// // Assert.Inconclusive("Verify the correctness of this test method."); -// //} - -// ///// -// /////A test for ApplicationAlias -// ///// -// //[TestMethod()] -// //public void ApplicationAliasTest() -// //{ -// // ApplicationTree target = new ApplicationTree(); // TODO: Initialize to an appropriate value -// // string actual; -// // actual = target.ApplicationAlias; -// // Assert.Inconclusive("Verify the correctness of this test method."); -// //} - -// ///// -// /////A test for AssemblyName -// ///// -// //[TestMethod()] -// //public void AssemblyNameTest() -// //{ -// // ApplicationTree target = new ApplicationTree(); // TODO: Initialize to an appropriate value -// // string expected = string.Empty; // TODO: Initialize to an appropriate value -// // string actual; -// // target.AssemblyName = expected; -// // actual = target.AssemblyName; -// // Assert.AreEqual(expected, actual); -// // Assert.Inconclusive("Verify the correctness of this test method."); -// //} - -// ///// -// /////A test for IconClosed -// ///// -// //[TestMethod()] -// //public void IconClosedTest() -// //{ -// // ApplicationTree target = new ApplicationTree(); // TODO: Initialize to an appropriate value -// // string expected = string.Empty; // TODO: Initialize to an appropriate value -// // string actual; -// // target.IconClosed = expected; -// // actual = target.IconClosed; -// // Assert.AreEqual(expected, actual); -// // Assert.Inconclusive("Verify the correctness of this test method."); -// //} - -// ///// -// /////A test for IconOpened -// ///// -// //[TestMethod()] -// //public void IconOpenedTest() -// //{ -// // ApplicationTree target = new ApplicationTree(); // TODO: Initialize to an appropriate value -// // string expected = string.Empty; // TODO: Initialize to an appropriate value -// // string actual; -// // target.IconOpened = expected; -// // actual = target.IconOpened; -// // Assert.AreEqual(expected, actual); -// // Assert.Inconclusive("Verify the correctness of this test method."); -// //} - -// ///// -// /////A test for Initialize -// ///// -// //[TestMethod()] -// //public void InitializeTest() -// //{ -// // ApplicationTree target = new ApplicationTree(); // TODO: Initialize to an appropriate value -// // bool expected = false; // TODO: Initialize to an appropriate value -// // bool actual; -// // target.Initialize = expected; -// // actual = target.Initialize; -// // Assert.AreEqual(expected, actual); -// // Assert.Inconclusive("Verify the correctness of this test method."); -// //} - -// ///// -// /////A test for Silent -// ///// -// //[TestMethod()] -// //public void SilentTest() -// //{ -// // ApplicationTree target = new ApplicationTree(); // TODO: Initialize to an appropriate value -// // bool expected = false; // TODO: Initialize to an appropriate value -// // bool actual; -// // target.Silent = expected; -// // actual = target.Silent; -// // Assert.AreEqual(expected, actual); -// // Assert.Inconclusive("Verify the correctness of this test method."); -// //} - -// ///// -// /////A test for SortOrder -// ///// -// //[TestMethod()] -// //public void SortOrderTest() -// //{ -// // ApplicationTree target = new ApplicationTree(); // TODO: Initialize to an appropriate value -// // byte expected = 0; // TODO: Initialize to an appropriate value -// // byte actual; -// // target.SortOrder = expected; -// // actual = target.SortOrder; -// // Assert.AreEqual(expected, actual); -// // Assert.Inconclusive("Verify the correctness of this test method."); -// //} - -// ///// -// /////A test for SqlHelper -// ///// -// //[TestMethod()] -// //public void SqlHelperTest() -// //{ -// // ISqlHelper actual; -// // actual = ApplicationTree.SqlHelper; -// // Assert.Inconclusive("Verify the correctness of this test method."); -// //} - -// ///// -// /////A test for Title -// ///// -// //[TestMethod()] -// //public void TitleTest() -// //{ -// // ApplicationTree target = new ApplicationTree(); // TODO: Initialize to an appropriate value -// // string expected = string.Empty; // TODO: Initialize to an appropriate value -// // string actual; -// // target.Title = expected; -// // actual = target.Title; -// // Assert.AreEqual(expected, actual); -// // Assert.Inconclusive("Verify the correctness of this test method."); -// //} - -// ///// -// /////A test for Type -// ///// -// //[TestMethod()] -// //public void TypeTest() -// //{ -// // ApplicationTree target = new ApplicationTree(); // TODO: Initialize to an appropriate value -// // string expected = string.Empty; // TODO: Initialize to an appropriate value -// // string actual; -// // target.Type = expected; -// // actual = target.Type; -// // Assert.AreEqual(expected, actual); -// // Assert.Inconclusive("Verify the correctness of this test method."); -// //} -// #endregion - -// #region Additional test attributes -// // -// //You can use the following additional attributes as you write your tests: -// // -// //Use ClassInitialize to run code before running the first test in the class -// //[ClassInitialize()] -// //public static void MyClassInitialize(TestContext testContext) -// //{ -// //} -// // -// //Use ClassCleanup to run code after all tests in a class have run -// //[ClassCleanup()] -// //public static void MyClassCleanup() -// //{ -// //} -// // -// //Use TestInitialize to run code before running each test -// //[TestInitialize()] -// //public void MyTestInitialize() -// //{ -// //} -// // -// //Use TestCleanup to run code after each test has run -// //[TestCleanup()] -// //public void MyTestCleanup() -// //{ -// //} -// // -// #endregion -// } -//} diff --git a/src/Umbraco.Tests/TreesAndSections/ResourceFiles.Designer.cs b/src/Umbraco.Tests/TreesAndSections/ResourceFiles.Designer.cs deleted file mode 100644 index 02bc84649e..0000000000 --- a/src/Umbraco.Tests/TreesAndSections/ResourceFiles.Designer.cs +++ /dev/null @@ -1,91 +0,0 @@ -//------------------------------------------------------------------------------ -// -// This code was generated by a tool. -// Runtime Version:4.0.30319.42000 -// -// Changes to this file may cause incorrect behavior and will be lost if -// the code is regenerated. -// -//------------------------------------------------------------------------------ - -namespace Umbraco.Tests.TreesAndSections { - using System; - - - /// - /// A strongly-typed resource class, for looking up localized strings, etc. - /// - // This class was auto-generated by the StronglyTypedResourceBuilder - // class via a tool like ResGen or Visual Studio. - // To add or remove a member, edit your .ResX file then rerun ResGen - // with the /str option, or rebuild your VS project. - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "15.0.0.0")] - [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] - [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] - internal class ResourceFiles { - - private static global::System.Resources.ResourceManager resourceMan; - - private static global::System.Globalization.CultureInfo resourceCulture; - - [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] - internal ResourceFiles() { - } - - /// - /// Returns the cached ResourceManager instance used by this class. - /// - [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] - internal static global::System.Resources.ResourceManager ResourceManager { - get { - if (object.ReferenceEquals(resourceMan, null)) { - global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("Umbraco.Tests.TreesAndSections.ResourceFiles", typeof(ResourceFiles).Assembly); - resourceMan = temp; - } - return resourceMan; - } - } - - /// - /// Overrides the current thread's CurrentUICulture property for all - /// resource lookups using this strongly typed resource class. - /// - [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] - internal static global::System.Globalization.CultureInfo Culture { - get { - return resourceCulture; - } - set { - resourceCulture = value; - } - } - - /// - /// Looks up a localized string similar to <?xml version="1.0" encoding="utf-8"?> - ///<applications> - /// <add alias="content" name="content" icon="file" sortOrder="0" /> - /// <add alias="0b486ac9c0f1456996192c6ed1f03e57" name="0b486ac9c0f1456996192c6ed1f03e57" icon="icon.jpg" sortOrder="1" /> - /// <add alias="1ffbc301744c4e75ae3054d741954c7b" name="1ffbc301744c4e75ae3054d741954c7b" icon="icon.jpg" sortOrder="2" /> - /// <add alias="1838c3e1591f4008bbafe59a06a00a31" name="1838c3e1591f4008bbafe59a06a00a31" icon="icon.jpg" sortOrder="3" /> - /// <add alias="e5badae2 [rest of string was truncated]";. - /// - internal static string applications { - get { - return ResourceManager.GetString("applications", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to <?xml version="1.0" encoding="utf-8"?> - ///<trees> - /// <add initialize="false" sortOrder="0" alias="1838c3e1591f4008bbafe59a06a00a31" application="1838c3e1591f4008bbafe59a06a00a31" title="1838c3e1591f4008bbafe59a06a00a31" iconClosed="icon.jpg" iconOpen="icon.jpg" type="nulltype" /> - /// <add initialize="false" sortOrder="0" alias="e5badae2fc5e4cd7acb3700320e33b8b" application="e5badae2fc5e4cd7acb3700320e33b8b" title="e5badae2fc5e4cd7acb3700320e33b8b" iconClosed="icon.jpg" iconOpen="icon.jpg" type="nulltype" /> - /// [rest of string was truncated]";. - /// - internal static string trees { - get { - return ResourceManager.GetString("trees", resourceCulture); - } - } - } -} diff --git a/src/Umbraco.Tests/TreesAndSections/ResourceFiles.resx b/src/Umbraco.Tests/TreesAndSections/ResourceFiles.resx deleted file mode 100644 index fac58dc842..0000000000 --- a/src/Umbraco.Tests/TreesAndSections/ResourceFiles.resx +++ /dev/null @@ -1,127 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - text/microsoft-resx - - - 2.0 - - - System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - - applications.config;System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089;utf-8 - - - trees.config;System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089;utf-8 - - \ No newline at end of file diff --git a/src/Umbraco.Tests/TreesAndSections/SectionTests.cs b/src/Umbraco.Tests/TreesAndSections/SectionTests.cs deleted file mode 100644 index 83de6c4479..0000000000 --- a/src/Umbraco.Tests/TreesAndSections/SectionTests.cs +++ /dev/null @@ -1,252 +0,0 @@ -//using System.IO; -//using NUnit.Framework; -//using Umbraco.Core.Services; -//using Umbraco.Tests.TestHelpers; -//using System; -//using Umbraco.Core.Composing; -//using Umbraco.Tests.Testing; -//using Umbraco.Web.Services; - -//namespace Umbraco.Tests.TreesAndSections -//{ -// /// -// ///This is a test class for ApplicationTest and is intended -// ///to contain all ApplicationTest Unit Tests -// /// -// [TestFixture] -// [UmbracoTest(AutoMapper = true, Database = UmbracoTestOptions.Database.NewSchemaPerTest)] -// public class SectionTests : TestWithDatabaseBase -// { -// protected override void Compose() -// { -// base.Compose(); -// Composition.RegisterUnique(); -// } - -// public override void SetUp() -// { -// base.SetUp(); - -// var treesConfig = TestHelper.MapPathForTest("~/TEMP/TreesAndSections/trees.config"); -// var appConfig = TestHelper.MapPathForTest("~/TEMP/TreesAndSections/applications.config"); -// Directory.CreateDirectory(TestHelper.MapPathForTest("~/TEMP/TreesAndSections")); -// using (var writer = File.CreateText(treesConfig)) -// { -// writer.Write(ResourceFiles.trees); -// } -// using (var writer = File.CreateText(appConfig)) -// { -// writer.Write(ResourceFiles.applications); -// } - -// ApplicationTreeService.TreeConfigFilePath = treesConfig; -// SectionService.AppConfigFilePath = appConfig; -// } - -// public override void TearDown() -// { -// base.TearDown(); - -// if (Directory.Exists(TestHelper.MapPathForTest("~/TEMP/TreesAndSections"))) -// { -// Directory.Delete(TestHelper.MapPathForTest("~/TEMP/TreesAndSections"), true); -// } -// ApplicationTreeService.TreeConfigFilePath = null; -// SectionService.AppConfigFilePath = null; -// } - -// ///// -// ///// Create a new application and delete it -// ///// -// //[Test()] -// //public void Application_Make_New() -// //{ -// // var name = Guid.NewGuid().ToString("N"); -// // ServiceContext.SectionService.MakeNew(name, name, "icon.jpg"); - -// // //check if it exists -// // var app = ServiceContext.SectionService.GetByAlias(name); -// // Assert.IsNotNull(app); - -// // //now remove it -// // ServiceContext.SectionService.DeleteSection(app); -// // Assert.IsNull(ServiceContext.SectionService.GetByAlias(name)); -// //} - -// #region Tests to write - - -// ///// -// /////A test for Application Constructor -// ///// -// //[TestMethod()] -// //public void ApplicationConstructorTest() -// //{ -// // string name = string.Empty; // TODO: Initialize to an appropriate value -// // string alias = string.Empty; // TODO: Initialize to an appropriate value -// // string icon = string.Empty; // TODO: Initialize to an appropriate value -// // Application target = new Application(name, alias, icon); -// // Assert.Inconclusive("TODO: Implement code to verify target"); -// //} - -// ///// -// /////A test for Application Constructor -// ///// -// //[TestMethod()] -// //public void ApplicationConstructorTest1() -// //{ -// // Application target = new Application(); -// // Assert.Inconclusive("TODO: Implement code to verify target"); -// //} - -// ///// -// /////A test for Delete -// ///// -// //[TestMethod()] -// //public void DeleteTest() -// //{ -// // Application target = new Application(); // TODO: Initialize to an appropriate value -// // target.Delete(); -// // Assert.Inconclusive("A method that does not return a value cannot be verified."); -// //} - - - -// ///// -// /////A test for MakeNew -// ///// -// //[TestMethod()] -// //public void MakeNewTest1() -// //{ -// // string name = string.Empty; // TODO: Initialize to an appropriate value -// // string alias = string.Empty; // TODO: Initialize to an appropriate value -// // string icon = string.Empty; // TODO: Initialize to an appropriate value -// // Application.MakeNew(name, alias, icon); -// // Assert.Inconclusive("A method that does not return a value cannot be verified."); -// //} - -// ///// -// /////A test for RegisterIApplications -// ///// -// //[TestMethod()] -// //public void RegisterIApplicationsTest() -// //{ -// // Application.RegisterIApplications(); -// // Assert.Inconclusive("A method that does not return a value cannot be verified."); -// //} - -// ///// -// /////A test for getAll -// ///// -// //[TestMethod()] -// //public void getAllTest() -// //{ -// // List expected = null; // TODO: Initialize to an appropriate value -// // List actual; -// // actual = Application.getAll(); -// // Assert.AreEqual(expected, actual); -// // Assert.Inconclusive("Verify the correctness of this test method."); -// //} - -// ///// -// /////A test for getByAlias -// ///// -// //[TestMethod()] -// //public void getByAliasTest() -// //{ -// // string appAlias = string.Empty; // TODO: Initialize to an appropriate value -// // Application expected = null; // TODO: Initialize to an appropriate value -// // Application actual; -// // actual = Application.getByAlias(appAlias); -// // Assert.AreEqual(expected, actual); -// // Assert.Inconclusive("Verify the correctness of this test method."); -// //} - -// ///// -// /////A test for SqlHelper -// ///// -// //[TestMethod()] -// //public void SqlHelperTest() -// //{ -// // ISqlHelper actual; -// // actual = Application.SqlHelper; -// // Assert.Inconclusive("Verify the correctness of this test method."); -// //} - -// ///// -// /////A test for alias -// ///// -// //[TestMethod()] -// //public void aliasTest() -// //{ -// // Application target = new Application(); // TODO: Initialize to an appropriate value -// // string expected = string.Empty; // TODO: Initialize to an appropriate value -// // string actual; -// // target.alias = expected; -// // actual = target.alias; -// // Assert.AreEqual(expected, actual); -// // Assert.Inconclusive("Verify the correctness of this test method."); -// //} - -// ///// -// /////A test for icon -// ///// -// //[TestMethod()] -// //public void iconTest() -// //{ -// // Application target = new Application(); // TODO: Initialize to an appropriate value -// // string expected = string.Empty; // TODO: Initialize to an appropriate value -// // string actual; -// // target.icon = expected; -// // actual = target.icon; -// // Assert.AreEqual(expected, actual); -// // Assert.Inconclusive("Verify the correctness of this test method."); -// //} - -// ///// -// /////A test for name -// ///// -// //[TestMethod()] -// //public void nameTest() -// //{ -// // Application target = new Application(); // TODO: Initialize to an appropriate value -// // string expected = string.Empty; // TODO: Initialize to an appropriate value -// // string actual; -// // target.name = expected; -// // actual = target.name; -// // Assert.AreEqual(expected, actual); -// // Assert.Inconclusive("Verify the correctness of this test method."); -// //} -// #endregion - -// #region Additional test attributes -// // -// //You can use the following additional attributes as you write your tests: -// // -// //Use ClassInitialize to run code before running the first test in the class -// //[ClassInitialize()] -// //public static void MyClassInitialize(TestContext testContext) -// //{ -// //} -// // -// //Use ClassCleanup to run code after all tests in a class have run -// //[ClassCleanup()] -// //public static void MyClassCleanup() -// //{ -// //} -// // -// //Use TestInitialize to run code before running each test -// //[TestInitialize()] -// //public void MyTestInitialize() -// //{ -// //} -// // -// //Use TestCleanup to run code after each test has run -// //[TestCleanup()] -// //public void MyTestCleanup() -// //{ -// //} -// // -// #endregion -// } -//} diff --git a/src/Umbraco.Tests/TreesAndSections/applications.config b/src/Umbraco.Tests/TreesAndSections/applications.config deleted file mode 100644 index aadd1c5407..0000000000 --- a/src/Umbraco.Tests/TreesAndSections/applications.config +++ /dev/null @@ -1,16 +0,0 @@ - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/src/Umbraco.Tests/TreesAndSections/trees.config b/src/Umbraco.Tests/TreesAndSections/trees.config deleted file mode 100644 index d21fea28a9..0000000000 --- a/src/Umbraco.Tests/TreesAndSections/trees.config +++ /dev/null @@ -1,8 +0,0 @@ - - - - - - - - \ No newline at end of file diff --git a/src/Umbraco.Tests/Umbraco.Tests.csproj b/src/Umbraco.Tests/Umbraco.Tests.csproj index e49ba250fa..408b0f96ca 100644 --- a/src/Umbraco.Tests/Umbraco.Tests.csproj +++ b/src/Umbraco.Tests/Umbraco.Tests.csproj @@ -423,13 +423,6 @@ - - True - True - ResourceFiles.resx - - - @@ -525,8 +518,6 @@ Designer Always - - Designer @@ -561,10 +552,6 @@ ImportResources.Designer.cs Designer - - ResXFileCodeGenerator - ResourceFiles.Designer.cs - ResXFileCodeGenerator TestFiles.Designer.cs diff --git a/src/Umbraco.Web/Cache/ApplicationTreeCacheRefresher.cs b/src/Umbraco.Web/Cache/ApplicationTreeCacheRefresher.cs deleted file mode 100644 index 4d6740a0b1..0000000000 --- a/src/Umbraco.Web/Cache/ApplicationTreeCacheRefresher.cs +++ /dev/null @@ -1,46 +0,0 @@ -//using System; -//using Umbraco.Core.Cache; - -//namespace Umbraco.Web.Cache -//{ -// public sealed class ApplicationTreeCacheRefresher : CacheRefresherBase -// { -// public ApplicationTreeCacheRefresher(CacheHelper cacheHelper) -// : base(cacheHelper) -// { } - -// #region Define - -// protected override ApplicationTreeCacheRefresher This => this; - -// public static readonly Guid UniqueId = Guid.Parse("0AC6C028-9860-4EA4-958D-14D39F45886E"); - -// public override Guid RefresherUniqueId => UniqueId; - -// public override string Name => "Application Tree Cache Refresher"; - -// #endregion - -// #region Refresher - -// public override void RefreshAll() -// { -// CacheHelper.RuntimeCache.ClearCacheItem(CacheKeys.ApplicationTreeCacheKey); -// base.RefreshAll(); -// } - -// public override void Refresh(int id) -// { -// Remove(id); -// base.Refresh(id); -// } - -// public override void Remove(int id) -// { -// CacheHelper.RuntimeCache.ClearCacheItem(CacheKeys.ApplicationTreeCacheKey); -// base.Remove(id); -// } - -// #endregion -// } -//} diff --git a/src/Umbraco.Web/Cache/DistributedCacheBinder_Handlers.cs b/src/Umbraco.Web/Cache/DistributedCacheBinder_Handlers.cs index 421eb546a4..3a3eb1b8fb 100644 --- a/src/Umbraco.Web/Cache/DistributedCacheBinder_Handlers.cs +++ b/src/Umbraco.Web/Cache/DistributedCacheBinder_Handlers.cs @@ -46,20 +46,6 @@ namespace Umbraco.Web.Cache _logger.Info("Initializing Umbraco internal event handlers for cache refreshing."); - //// bind to application tree events - //Bind(() => ApplicationTreeService.Deleted += ApplicationTreeService_Deleted, - // () => ApplicationTreeService.Deleted -= ApplicationTreeService_Deleted); - //Bind(() => ApplicationTreeService.Updated += ApplicationTreeService_Updated, - // () => ApplicationTreeService.Updated -= ApplicationTreeService_Updated); - //Bind(() => ApplicationTreeService.New += ApplicationTreeService_New, - // () => ApplicationTreeService.New -= ApplicationTreeService_New); - - //// bind to application events - //Bind(() => SectionService.Deleted += SectionService_Deleted, - // () => SectionService.Deleted -= SectionService_Deleted); - //Bind(() => SectionService.New += SectionService_New, - // () => SectionService.New -= SectionService_New); - // bind to user and user group events Bind(() => UserService.SavedUserGroup += UserService_SavedUserGroup, () => UserService.SavedUserGroup -= UserService_SavedUserGroup); @@ -231,39 +217,6 @@ namespace Umbraco.Web.Cache #endregion - //#region ApplicationTreeService - - //private void ApplicationTreeService_New(ApplicationTree sender, EventArgs e) - //{ - // _distributedCache.RefreshAllApplicationTreeCache(); - //} - - //private void ApplicationTreeService_Updated(ApplicationTree sender, EventArgs e) - //{ - // _distributedCache.RefreshAllApplicationTreeCache(); - //} - - //private void ApplicationTreeService_Deleted(ApplicationTree sender, EventArgs e) - //{ - // _distributedCache.RefreshAllApplicationTreeCache(); - //} - - //#endregion - - //#region Application event handlers - - //private void SectionService_New(ISectionService sender, EventArgs e) - //{ - // _distributedCache.RefreshAllApplicationCache(); - //} - - //private void SectionService_Deleted(ISectionService sender, EventArgs e) - //{ - // _distributedCache.RefreshAllApplicationCache(); - //} - - //#endregion - #region LocalizationService / Dictionary private void LocalizationService_SavedDictionaryItem(ILocalizationService sender, SaveEventArgs e) diff --git a/src/Umbraco.Web/Cache/DistributedCacheExtensions.cs b/src/Umbraco.Web/Cache/DistributedCacheExtensions.cs index aab0f9b157..80c49e279c 100644 --- a/src/Umbraco.Web/Cache/DistributedCacheExtensions.cs +++ b/src/Umbraco.Web/Cache/DistributedCacheExtensions.cs @@ -18,24 +18,6 @@ namespace Umbraco.Web.Cache #endregion - //#region ApplicationTreeCache - - //public static void RefreshAllApplicationTreeCache(this DistributedCache dc) - //{ - // dc.RefreshAll(ApplicationTreeCacheRefresher.UniqueId); - //} - - //#endregion - - //#region ApplicationCache - - //public static void RefreshAllApplicationCache(this DistributedCache dc) - //{ - // dc.RefreshAll(ApplicationCacheRefresher.UniqueId); - //} - - //#endregion - #region User cache public static void RemoveUserCache(this DistributedCache dc, int userId) @@ -74,7 +56,6 @@ namespace Umbraco.Web.Cache #endregion - #region TemplateCache public static void RefreshTemplateCache(this DistributedCache dc, int templateId) diff --git a/src/Umbraco.Web/Models/ContentEditing/IBackOfficeSection.cs b/src/Umbraco.Web/Models/ContentEditing/IBackOfficeSection.cs deleted file mode 100644 index f27941035a..0000000000 --- a/src/Umbraco.Web/Models/ContentEditing/IBackOfficeSection.cs +++ /dev/null @@ -1,15 +0,0 @@ -using Umbraco.Core.Composing; - -namespace Umbraco.Web.Models.ContentEditing -{ - - /// - /// Defines a back office section - /// - public interface IBackOfficeSection : IDiscoverable - { - string Alias { get; } - string Name { get; } - int SortOrder { get; } - } -} diff --git a/src/Umbraco.Web/Models/Mapping/SectionMapperProfile.cs b/src/Umbraco.Web/Models/Mapping/SectionMapperProfile.cs index 683fce36e8..5aa99e4652 100644 --- a/src/Umbraco.Web/Models/Mapping/SectionMapperProfile.cs +++ b/src/Umbraco.Web/Models/Mapping/SectionMapperProfile.cs @@ -3,6 +3,7 @@ using AutoMapper; using Umbraco.Core.Models.ContentEditing; using Umbraco.Core.Services; using Umbraco.Web.Models.ContentEditing; +using Umbraco.Web.Models.Trees; namespace Umbraco.Web.Models.Mapping { diff --git a/src/Umbraco.Web/Models/Trees/ApplicationDefinitions.cs b/src/Umbraco.Web/Models/Trees/ApplicationDefinitions.cs deleted file mode 100644 index ba48c9e240..0000000000 --- a/src/Umbraco.Web/Models/Trees/ApplicationDefinitions.cs +++ /dev/null @@ -1,77 +0,0 @@ -using Umbraco.Core; -using Umbraco.Core.Models; -using Umbraco.Core.Models.ContentEditing; -using Umbraco.Web.Models.ContentEditing; - -namespace Umbraco.Web.Models.Trees -{ - /// - /// Defines the back office content section - /// - public class ContentBackOfficeSectionDefinition : IBackOfficeSection - { - public string Alias => Constants.Applications.Content; - public string Name => "Content"; - public int SortOrder => 0; - } - - /// - /// Defines the back office media section - /// - public class MediaBackOfficeSectionDefinition : IBackOfficeSection - { - public string Alias => Constants.Applications.Media; - public string Name => "Media"; - public int SortOrder => 1; - } - - /// - /// Defines the back office settings section - /// - public class SettingsBackOfficeSectionDefinition : IBackOfficeSection - { - public string Alias => Constants.Applications.Settings; - public string Name => "Settings"; - public int SortOrder => 2; - } - - /// - /// Defines the back office packages section - /// - public class PackagesBackOfficeSectionDefinition : IBackOfficeSection - { - public string Alias => Constants.Applications.Packages; - public string Name => "Packages"; - public int SortOrder => 3; - } - - /// - /// Defines the back office users section - /// - public class UsersBackOfficeSectionDefinition : IBackOfficeSection - { - public string Alias => Constants.Applications.Users; - public string Name => "Users"; - public int SortOrder => 4; - } - - /// - /// Defines the back office members section - /// - public class MembersBackOfficeSectionDefinition : IBackOfficeSection - { - public string Alias => Constants.Applications.Members; - public string Name => "Members"; - public int SortOrder => 5; - } - - /// - /// Defines the back office translation section - /// - public class TranslationBackOfficeSectionDefinition : IBackOfficeSection - { - public string Alias => Constants.Applications.Translation; - public string Name => "Translation"; - public int SortOrder => 6; - } -} diff --git a/src/Umbraco.Web/Models/Trees/IBackOfficeSection.cs b/src/Umbraco.Web/Models/Trees/IBackOfficeSection.cs new file mode 100644 index 0000000000..0cc505fb19 --- /dev/null +++ b/src/Umbraco.Web/Models/Trees/IBackOfficeSection.cs @@ -0,0 +1,12 @@ +namespace Umbraco.Web.Models.Trees +{ + + /// + /// Defines a back office section + /// + public interface IBackOfficeSection + { + string Alias { get; } + string Name { get; } + } +} diff --git a/src/Umbraco.Web/Models/Trees/SectionRootNode.cs b/src/Umbraco.Web/Models/Trees/TreeRootNode.cs similarity index 100% rename from src/Umbraco.Web/Models/Trees/SectionRootNode.cs rename to src/Umbraco.Web/Models/Trees/TreeRootNode.cs diff --git a/src/Umbraco.Web/Runtime/WebRuntimeComposer.cs b/src/Umbraco.Web/Runtime/WebRuntimeComposer.cs index 047d080a88..134ed7b1d0 100644 --- a/src/Umbraco.Web/Runtime/WebRuntimeComposer.cs +++ b/src/Umbraco.Web/Runtime/WebRuntimeComposer.cs @@ -25,6 +25,7 @@ using Umbraco.Web.Features; using Umbraco.Web.HealthCheck; using Umbraco.Web.Models.ContentEditing; using Umbraco.Web.Models.PublishedContent; +using Umbraco.Web.Models.Trees; using Umbraco.Web.Mvc; using Umbraco.Web.PublishedCache; using Umbraco.Web.Routing; @@ -195,9 +196,15 @@ namespace Umbraco.Web.Runtime .Append() .Append(); - // register back office sections + // register back office sections in the order we want them rendered composition.WithCollectionBuilder() - .Add(() => composition.TypeLoader.GetTypes()); + .Append() + .Append() + .Append() + .Append() + .Append() + .Append() + .Append(); // register back office trees foreach (var treeControllerType in umbracoApiControllerTypes) diff --git a/src/Umbraco.Web/Services/ISectionService.cs b/src/Umbraco.Web/Services/ISectionService.cs index c325020cf1..f0a16dc965 100644 --- a/src/Umbraco.Web/Services/ISectionService.cs +++ b/src/Umbraco.Web/Services/ISectionService.cs @@ -2,6 +2,7 @@ using Umbraco.Core.Models; using Umbraco.Core.Models.ContentEditing; using Umbraco.Web.Models.ContentEditing; +using Umbraco.Web.Models.Trees; namespace Umbraco.Web.Services { diff --git a/src/Umbraco.Web/Services/ITreeService.cs b/src/Umbraco.Web/Services/ITreeService.cs index ce734cc5e4..17998ae1a7 100644 --- a/src/Umbraco.Web/Services/ITreeService.cs +++ b/src/Umbraco.Web/Services/ITreeService.cs @@ -29,15 +29,7 @@ namespace Umbraco.Web.Services /// The application alias. /// Returns a ApplicationTree Array IEnumerable GetApplicationTrees(string applicationAlias); - - ///// - ///// Gets the application tree for the applcation with the specified alias - ///// - ///// The application alias. - ///// - ///// Returns a ApplicationTree Array - //IEnumerable GetApplicationTrees(string applicationAlias, bool onlyInitialized); - + /// /// Gets the grouped application trees for the application with the specified alias /// diff --git a/src/Umbraco.Web/Services/SectionService.cs b/src/Umbraco.Web/Services/SectionService.cs index bb154976f0..e6af27534c 100644 --- a/src/Umbraco.Web/Services/SectionService.cs +++ b/src/Umbraco.Web/Services/SectionService.cs @@ -25,270 +25,31 @@ namespace Umbraco.Web.Services private readonly IUserService _userService; private readonly BackOfficeSectionCollection _sectionCollection; - private readonly Lazy> _allAvailableSections; - //private readonly IApplicationTreeService _applicationTreeService; - //private readonly IScopeProvider _scopeProvider; - private readonly CacheHelper _cache; - //internal const string AppConfigFileName = "applications.config"; - //private static string _appConfig; - //private static readonly object Locker = new object(); - public SectionService( IUserService userService, - BackOfficeSectionCollection sectionCollection, - CacheHelper cache) + BackOfficeSectionCollection sectionCollection) { - //_applicationTreeService = applicationTreeService ?? throw new ArgumentNullException(nameof(applicationTreeService)); - _cache = cache ?? throw new ArgumentNullException(nameof(cache)); _userService = userService; _sectionCollection = sectionCollection; - //_scopeProvider = scopeProvider; - //_allAvailableSections = new Lazy>(() => new LazyEnumerableSections()); } - - - ///// - ///// gets/sets the application.config file path - ///// - ///// - ///// The setter is generally only going to be used in unit tests, otherwise it will attempt to resolve it using the IOHelper.MapPath - ///// - //internal static string AppConfigFilePath - //{ - // get - // { - // if (string.IsNullOrWhiteSpace(_appConfig)) - // { - // _appConfig = IOHelper.MapPath(SystemDirectories.Config + "/" + AppConfigFileName); - // } - // return _appConfig; - // } - // set => _appConfig = value; - //} - + /// /// The cache storage for all applications /// - public IEnumerable GetSections() - { - return _sectionCollection; - } + public IEnumerable GetSections() => _sectionCollection; - //internal void LoadXml(Func callback, bool saveAfterCallbackIfChanged) - //{ - // lock (Locker) - // { - // var doc = File.Exists(AppConfigFilePath) - // ? XDocument.Load(AppConfigFilePath) - // : XDocument.Parse(""); - - // if (doc.Root != null) - // { - // var changed = callback.Invoke(doc); - - // if (saveAfterCallbackIfChanged && changed) - // { - // //ensure the folder is created! - // Directory.CreateDirectory(Path.GetDirectoryName(AppConfigFilePath)); - - // doc.Save(AppConfigFilePath); - - // //remove the cache so it gets re-read ... SD: I'm leaving this here even though it - // // is taken care of by events as well, I think unit tests may rely on it being cleared here. - // _cache.RuntimeCache.ClearCacheItem(CacheKeys.ApplicationsCacheKey); - // } - // } - // } - //} - - /// - /// Get the user's allowed sections - /// - /// - /// + /// public IEnumerable GetAllowedSections(int userId) { - var user = _userService.GetUserById(userId); if (user == null) - { throw new InvalidOperationException("No user found with id " + userId); - } return GetSections().Where(x => user.AllowedSections.Contains(x.Alias)); } - /// - /// Gets the application by its alias. - /// - /// The application alias. - /// - public IBackOfficeSection GetByAlias(string appAlias) - { - return GetSections().FirstOrDefault(t => t.Alias == appAlias); - } - - ///// - ///// Creates a new applcation if no application with the specified alias is found. - ///// - ///// The application name. - ///// The application alias. - ///// The application icon, which has to be located in umbraco/images/tray folder. - //public void MakeNew(string name, string alias, string icon) - //{ - // var sections = GetSections(); - // var nextSortOrder = sections.Any() ? sections.Max(x => x.SortOrder) + 1 : 1; - // MakeNew(name, alias, icon, nextSortOrder); - //} - - ///// - ///// Makes the new. - ///// - ///// The name. - ///// The alias. - ///// The icon. - ///// The sort order. - //public void MakeNew(string name, string alias, string icon, int sortOrder) - //{ - // if (GetSections().All(x => x.Alias != alias)) - // { - // LoadXml(doc => - // { - // doc.Root.Add(new XElement("add", - // new XAttribute("alias", alias), - // new XAttribute("name", name), - // new XAttribute("icon", icon), - // new XAttribute("sortOrder", sortOrder))); - // return true; - // }, true); - - // //raise event - // OnNew(this /*new Section(name, alias, sortOrder)*/, new EventArgs()); - // } - //} - - ///// - ///// Deletes the section - ///// - //public void DeleteSection(Section section) - //{ - // lock (Locker) - // { - // //delete the assigned applications - // using (var scope = _scopeProvider.CreateScope()) - // { - // scope.Database.Execute("delete from umbracoUserGroup2App where app = @appAlias", - // new { appAlias = section.Alias }); - // scope.Complete(); - // } - - // //delete the assigned trees - // var trees = _applicationTreeService.GetApplicationTrees(section.Alias); - // foreach (var t in trees) - // { - // _applicationTreeService.DeleteTree(t); - // } - - // LoadXml(doc => - // { - // doc.Root.Elements("add").Where(x => x.Attribute("alias") != null && x.Attribute("alias").Value == section.Alias) - // .Remove(); - - // return true; - // }, true); - - // //raise event - // OnDeleted(this, new EventArgs()); - // } - //} - - //private List
ReadFromXmlAndSort() - //{ - // var tmp = new List
(); - - // LoadXml(doc => - // { - // foreach (var addElement in doc.Root.Elements("add").OrderBy(x => - // { - // var sortOrderAttr = x.Attribute("sortOrder"); - // return sortOrderAttr != null ? Convert.ToInt32(sortOrderAttr.Value) : 0; - // })) - // { - // var sortOrderAttr = addElement.Attribute("sortOrder"); - // tmp.Add(new Section(addElement.Attribute("name").Value, - // addElement.Attribute("alias").Value, - // sortOrderAttr != null ? Convert.ToInt32(sortOrderAttr.Value) : 0)); - // } - // return false; - // }, false); - - // return tmp; - //} - - //internal static event TypedEventHandler Deleted; - //private static void OnDeleted(ISectionService app, EventArgs args) - //{ - // if (Deleted != null) - // { - // Deleted(app, args); - // } - //} - - //internal static event TypedEventHandler New; - //private static void OnNew(ISectionService app, EventArgs args) - //{ - // if (New != null) - // { - // New(app, args); - // } - //} - - ///// - ///// This class is here so that we can provide lazy access to tree scanning for when it is needed - ///// - //private class LazyEnumerableSections : IEnumerable
- //{ - // public LazyEnumerableSections() - // { - // _lazySections = new Lazy>(() => - // { - // // Load all Applications by attribute and add them to the XML config - - // //don't cache the result of this because it is only used once during app startup, caching will just add a bit more mem overhead for no reason - // var types = Current.TypeLoader.GetTypesWithAttribute(cache: false); // fixme - inject - - // //since applications don't populate their metadata from the attribute and because it is an interface, - // //we need to interrogate the attributes for the data. Would be better to have a base class that contains - // //metadata populated by the attribute. Oh well i guess. - // var attrs = types.Select(x => x.GetCustomAttributes(false).Single()); - // return attrs.Select(x => new Section(x.Name, x.Alias, x.SortOrder)).ToArray(); - // }); - // } - - // private readonly Lazy> _lazySections; - - // /// - // /// Returns an enumerator that iterates through the collection. - // /// - // /// - // /// A that can be used to iterate through the collection. - // /// - // public IEnumerator
GetEnumerator() - // { - // return _lazySections.Value.GetEnumerator(); - // } - - // /// - // /// Returns an enumerator that iterates through a collection. - // /// - // /// - // /// An object that can be used to iterate through the collection. - // /// - // IEnumerator IEnumerable.GetEnumerator() - // { - // return GetEnumerator(); - // } - //} - + /// + public IBackOfficeSection GetByAlias(string appAlias) => GetSections().FirstOrDefault(t => t.Alias == appAlias); + } } diff --git a/src/Umbraco.Web/Services/TreeService.cs b/src/Umbraco.Web/Services/TreeService.cs index cf010f1480..670f57ce49 100644 --- a/src/Umbraco.Web/Services/TreeService.cs +++ b/src/Umbraco.Web/Services/TreeService.cs @@ -1,237 +1,22 @@ using System; -using System.Collections; using System.Collections.Generic; -using System.IO; using System.Linq; -using System.Xml.Linq; using Umbraco.Core; -using Umbraco.Core.Cache; -using Umbraco.Core.Events; -using Umbraco.Core.IO; -using Umbraco.Core.Logging; -using Umbraco.Core.Models; -using Umbraco.Core.Composing; -using Umbraco.Core.Models.ContentEditing; -using Umbraco.Core.Services; -using Umbraco.Web.Models.ContentEditing; using Umbraco.Web.Trees; namespace Umbraco.Web.Services { internal class TreeService : ITreeService { - private readonly ILogger _logger; private readonly TreeCollection _treeCollection; - private static readonly object Locker = new object(); private readonly Lazy>> _groupedTrees; - public TreeService(ILogger logger, TreeCollection treeCollection) + public TreeService(TreeCollection treeCollection) { - _logger = logger; _treeCollection = treeCollection; _groupedTrees = new Lazy>>(InitGroupedTrees); } - ///// - ///// gets/sets the trees.config file path - ///// - ///// - ///// The setter is generally only going to be used in unit tests, otherwise it will attempt to resolve it using the IOHelper.MapPath - ///// - //internal static string TreeConfigFilePath - //{ - // get - // { - // if (string.IsNullOrWhiteSpace(_treeConfig)) - // { - // _treeConfig = IOHelper.MapPath(SystemDirectories.Config + "/" + TreeConfigFileName); - // } - // return _treeConfig; - // } - // set { _treeConfig = value; } - //} - - ///// - ///// The main entry point to get application trees - ///// - ///// - ///// This lazily on first access will scan for plugin trees and ensure the trees.config is up-to-date with the plugins. If plugins - ///// haven't changed on disk then the file will not be saved. The trees are all then loaded from this config file into cache and returned. - ///// - //private List GetAppTrees() - //{ - // return _cache.RuntimeCache.GetCacheItem>( - // CacheKeys.ApplicationTreeCacheKey, - // () => - // { - // var list = ReadFromXmlAndSort(); - - // //now we can check the non-volatile flag - // if (_allAvailableTrees != null) - // { - // var hasChanges = false; - - // LoadXml(doc => - // { - // //Now, load in the xml structure and update it with anything that is not declared there and save the file. - - // //NOTE: On the first iteration here, it will lazily scan all trees, etc... this is because this ienumerable is lazy - // // based on the ApplicationTreeRegistrar - and as noted there this is not an ideal way to do things but were stuck like this - // // currently because of the legacy assemblies and types not in the Core. - - // //Get all the trees not registered in the config (those not matching by alias casing will be detected as "unregistered") - // var unregistered = _allAvailableTrees.Value - // .Where(x => list.Any(l => l.Alias == x.Alias) == false) - // .ToArray(); - - // hasChanges = unregistered.Any(); - - // if (hasChanges == false) return false; - - // //add or edit the unregistered ones and re-save the file if any changes were found - // var count = 0; - // foreach (var tree in unregistered) - // { - // var existingElement = doc.Root.Elements("add").SingleOrDefault(x => - // string.Equals(x.Attribute("alias").Value, tree.Alias, - // StringComparison.InvariantCultureIgnoreCase) && - // string.Equals(x.Attribute("application").Value, tree.ApplicationAlias, - // StringComparison.InvariantCultureIgnoreCase)); - // if (existingElement != null) - // { - // existingElement.SetAttributeValue("alias", tree.Alias); - // } - // else - // { - // if (tree.Title.IsNullOrWhiteSpace()) - // { - // doc.Root.Add(new XElement("add", - // new XAttribute("initialize", tree.Initialize), - // new XAttribute("sortOrder", tree.SortOrder), - // new XAttribute("alias", tree.Alias), - // new XAttribute("application", tree.ApplicationAlias), - // new XAttribute("iconClosed", tree.IconClosed), - // new XAttribute("iconOpen", tree.IconOpened), - // new XAttribute("type", tree.Type))); - // } - // else - // { - // doc.Root.Add(new XElement("add", - // new XAttribute("initialize", tree.Initialize), - // new XAttribute("sortOrder", tree.SortOrder), - // new XAttribute("alias", tree.Alias), - // new XAttribute("application", tree.ApplicationAlias), - // new XAttribute("title", tree.Title), - // new XAttribute("iconClosed", tree.IconClosed), - // new XAttribute("iconOpen", tree.IconOpened), - // new XAttribute("type", tree.Type))); - // } - - // } - // count++; - // } - - // //don't save if there's no changes - // return count > 0; - // }, true); - - // if (hasChanges) - // { - // //If there were changes, we need to re-read the structures from the XML - // list = ReadFromXmlAndSort(); - // } - // } - - // return list; - // }, new TimeSpan(0, 10, 0)); - //} - - ///// - ///// Creates a new application tree. - ///// - ///// if set to true [initialize]. - ///// The sort order. - ///// The application alias. - ///// The alias. - ///// The title. - ///// The icon closed. - ///// The icon opened. - ///// The type. - //public void MakeNew(bool initialize, int sortOrder, string applicationAlias, string alias, string title, string iconClosed, string iconOpened, string type) - //{ - // LoadXml(doc => - // { - // var el = doc.Root.Elements("add").SingleOrDefault(x => x.Attribute("alias").Value == alias && x.Attribute("application").Value == applicationAlias); - - // if (el == null) - // { - // doc.Root.Add(new XElement("add", - // new XAttribute("initialize", initialize), - // new XAttribute("sortOrder", sortOrder), - // new XAttribute("alias", alias), - // new XAttribute("application", applicationAlias), - // new XAttribute("title", title), - // new XAttribute("iconClosed", iconClosed), - // new XAttribute("iconOpen", iconOpened), - // new XAttribute("type", type))); - // } - - // return true; - - // }, true); - - // OnNew(new ApplicationTree(initialize, sortOrder, applicationAlias, alias, title, iconClosed, iconOpened, type), new EventArgs()); - //} - - ///// - ///// Saves this instance. - ///// - //public void SaveTree(ApplicationTree tree) - //{ - // LoadXml(doc => - // { - // var el = doc.Root.Elements("add").SingleOrDefault(x => x.Attribute("alias").Value == tree.Alias && x.Attribute("application").Value == tree.ApplicationAlias); - - // if (el != null) - // { - // el.RemoveAttributes(); - - // el.Add(new XAttribute("initialize", tree.Initialize)); - // el.Add(new XAttribute("sortOrder", tree.SortOrder)); - // el.Add(new XAttribute("alias", tree.Alias)); - // el.Add(new XAttribute("application", tree.ApplicationAlias)); - // el.Add(new XAttribute("title", tree.Title)); - // el.Add(new XAttribute("iconClosed", tree.IconClosed)); - // el.Add(new XAttribute("iconOpen", tree.IconOpened)); - // el.Add(new XAttribute("type", tree.Type)); - // } - - // return true; - - // }, true); - - // OnUpdated(tree, new EventArgs()); - //} - - ///// - ///// Deletes this instance. - ///// - //public void DeleteTree(ApplicationTree tree) - //{ - // LoadXml(doc => - // { - // doc.Root.Elements("add") - // .Where(x => x.Attribute("application") != null - // && x.Attribute("application").Value == tree.ApplicationAlias - // && x.Attribute("alias") != null && x.Attribute("alias").Value == tree.Alias).Remove(); - - // return true; - - // }, true); - - // OnDeleted(tree, new EventArgs()); - //} - /// public ApplicationTree GetByAlias(string treeAlias) => _treeCollection.FirstOrDefault(t => t.TreeAlias == treeAlias); @@ -242,26 +27,6 @@ namespace Umbraco.Web.Services public IEnumerable GetApplicationTrees(string applicationAlias) => GetAll().Where(x => x.ApplicationAlias.InvariantEquals(applicationAlias)).OrderBy(x => x.SortOrder).ToList(); - ///// - ///// Gets the application tree for the applcation with the specified alias - ///// - ///// The application alias. - ///// - ///// Returns a ApplicationTree Array - //public IEnumerable GetApplicationTrees(string applicationAlias, bool onlyInitialized) - //{ - // var list = GetAppTrees().FindAll( - // t => - // { - // if (onlyInitialized) - // return (t.ApplicationAlias == applicationAlias && t.Initialize); - // return (t.ApplicationAlias == applicationAlias); - // } - // ); - - // return list.OrderBy(x => x.SortOrder).ToArray(); - //} - public IDictionary> GetGroupedApplicationTrees(string applicationAlias) { var result = new Dictionary>(); @@ -273,11 +38,10 @@ namespace Umbraco.Web.Services { foreach(var treeAliasInGroup in treeGroup) { - if (tree.TreeAlias == treeAliasInGroup) - { - if (resultGroup == null) resultGroup = new List(); - resultGroup.Add(tree); - } + if (tree.TreeAlias != treeAliasInGroup) continue; + + if (resultGroup == null) resultGroup = new List(); + resultGroup.Add(tree); } } if (resultGroup != null) @@ -302,169 +66,5 @@ namespace Umbraco.Web.Services return result; } - ///// - ///// Loads in the xml structure from disk if one is found, otherwise loads in an empty xml structure, calls the - ///// callback with the xml document and saves the structure back to disk if saveAfterCallback is true. - ///// - ///// - ///// - //internal void LoadXml(Func callback, bool saveAfterCallbackIfChanges) - //{ - // lock (Locker) - // { - // var doc = System.IO.File.Exists(TreeConfigFilePath) - // ? XDocument.Load(TreeConfigFilePath) - // : XDocument.Parse(""); - - // if (doc.Root != null) - // { - // var hasChanges = callback.Invoke(doc); - - // if (saveAfterCallbackIfChanges && hasChanges - // //Don't save it if it is empty, in some very rare cases if the app domain get's killed in the middle of this process - // // in some insane way the file saved will be empty. I'm pretty sure it's not actually anything to do with the xml doc and - // // more about the IO trying to save the XML doc, but it doesn't hurt to check. - // && doc.Root != null && doc.Root.Elements().Any()) - // { - // //ensures the folder exists - // Directory.CreateDirectory(Path.GetDirectoryName(TreeConfigFilePath)); - - // //saves it - // doc.Save(TreeConfigFilePath); - - // //remove the cache now that it has changed SD: I'm leaving this here even though it - // // is taken care of by events as well, I think unit tests may rely on it being cleared here. - // _cache.RuntimeCache.ClearCacheItem(CacheKeys.ApplicationTreeCacheKey); - // } - // } - // } - //} - - //private List ReadFromXmlAndSort() - //{ - // var list = new List(); - - // //read in the xml file containing trees and convert them all to ApplicationTree instances - // LoadXml(doc => - // { - // foreach (var addElement in doc.Root.Elements("add").OrderBy(x => - // { - // var sortOrderAttr = x.Attribute("sortOrder"); - // return sortOrderAttr != null ? Convert.ToInt32(sortOrderAttr.Value) : 0; - // })) - // { - // var applicationAlias = (string)addElement.Attribute("application"); - // var type = (string)addElement.Attribute("type"); - // var assembly = (string)addElement.Attribute("assembly"); - - // var clrType = Type.GetType(type); - // if (clrType == null) - // { - // _logger.Warn("The tree definition: {AddElement} could not be resolved to a .Net object type", addElement); - // continue; - // } - - // //check if the tree definition (applicationAlias + type + assembly) is already in the list - - // if (list.Any(tree => tree.ApplicationAlias.InvariantEquals(applicationAlias) && tree.GetRuntimeType() == clrType) == false) - // { - // list.Add(new ApplicationTree( - // addElement.Attribute("initialize") == null || Convert.ToBoolean(addElement.Attribute("initialize").Value), - // addElement.Attribute("sortOrder") != null - // ? Convert.ToByte(addElement.Attribute("sortOrder").Value) - // : (byte)0, - // (string)addElement.Attribute("application"), - // (string)addElement.Attribute("alias"), - // (string)addElement.Attribute("title"), - // (string)addElement.Attribute("iconClosed"), - // (string)addElement.Attribute("iconOpen"), - // (string)addElement.Attribute("type"))); - // } - // } - - // return false; - - // }, false); - - // return list; - //} - - - //internal static event TypedEventHandler Deleted; - //private static void OnDeleted(ApplicationTree app, EventArgs args) - //{ - // if (Deleted != null) - // { - // Deleted(app, args); - // } - //} - - //internal static event TypedEventHandler New; - //private static void OnNew(ApplicationTree app, EventArgs args) - //{ - // if (New != null) - // { - // New(app, args); - // } - //} - - //internal static event TypedEventHandler Updated; - //private static void OnUpdated(ApplicationTree app, EventArgs args) - //{ - // if (Updated != null) - // { - // Updated(app, args); - // } - //} - - ///// - ///// This class is here so that we can provide lazy access to tree scanning for when it is needed - ///// - //private class LazyEnumerableTrees : IEnumerable - //{ - // public LazyEnumerableTrees(TypeLoader typeLoader) - // { - // _lazyTrees = new Lazy>(() => - // { - // var added = new List(); - - // // Load all Controller Trees by attribute - // var types = typeLoader.GetTypesWithAttribute(); // fixme inject - // //convert them to ApplicationTree instances - // var items = types - // .Select(x => (tree: x, treeAttribute: x.GetCustomAttributes(false).Single())) - // .Select(x => new ApplicationTree(x.treeAttribute.Initialize, x.treeAttribute.SortOrder, x.treeAttribute.ApplicationAlias, x.treeAttribute.Alias, x.treeAttribute.Title, x.treeAttribute.IconClosed, x.treeAttribute.IconOpen, x.tree.GetFullNameWithAssembly())) - // .ToArray(); - - // added.AddRange(items.Select(x => x.Alias)); - - // return items.ToArray(); - // }); - // } - - // private readonly Lazy> _lazyTrees; - - // /// - // /// Returns an enumerator that iterates through the collection. - // /// - // /// - // /// A that can be used to iterate through the collection. - // /// - // public IEnumerator GetEnumerator() - // { - // return _lazyTrees.Value.GetEnumerator(); - // } - - // /// - // /// Returns an enumerator that iterates through a collection. - // /// - // /// - // /// An object that can be used to iterate through the collection. - // /// - // IEnumerator IEnumerable.GetEnumerator() - // { - // return GetEnumerator(); - // } - //} } } diff --git a/src/Umbraco.Web/Trees/BackOfficeSectionCollection.cs b/src/Umbraco.Web/Trees/BackOfficeSectionCollection.cs index 2b5a78d758..54762e73d8 100644 --- a/src/Umbraco.Web/Trees/BackOfficeSectionCollection.cs +++ b/src/Umbraco.Web/Trees/BackOfficeSectionCollection.cs @@ -2,6 +2,7 @@ using Umbraco.Core.Composing; using Umbraco.Core.Models.ContentEditing; using Umbraco.Web.Models.ContentEditing; +using Umbraco.Web.Models.Trees; namespace Umbraco.Web.Trees { @@ -11,11 +12,4 @@ namespace Umbraco.Web.Trees : base(items) { } } - - public class BackOfficeSectionCollectionBuilder : LazyCollectionBuilderBase - { - protected override BackOfficeSectionCollectionBuilder This => this; - - //TODO: can we allow for re-ordering OOTB without exposing other methods? - } } diff --git a/src/Umbraco.Web/Trees/BackOfficeSectionCollectionBuilder.cs b/src/Umbraco.Web/Trees/BackOfficeSectionCollectionBuilder.cs new file mode 100644 index 0000000000..62d61a4090 --- /dev/null +++ b/src/Umbraco.Web/Trees/BackOfficeSectionCollectionBuilder.cs @@ -0,0 +1,10 @@ +using Umbraco.Core.Composing; +using Umbraco.Web.Models.Trees; + +namespace Umbraco.Web.Trees +{ + public class BackOfficeSectionCollectionBuilder : OrderedCollectionBuilderBase + { + protected override BackOfficeSectionCollectionBuilder This => this; + } +} diff --git a/src/Umbraco.Web/Trees/ContentBackOfficeSection.cs b/src/Umbraco.Web/Trees/ContentBackOfficeSection.cs new file mode 100644 index 0000000000..0109a6916d --- /dev/null +++ b/src/Umbraco.Web/Trees/ContentBackOfficeSection.cs @@ -0,0 +1,15 @@ +using Umbraco.Core; +using Umbraco.Web.Models.ContentEditing; +using Umbraco.Web.Models.Trees; + +namespace Umbraco.Web.Trees +{ + /// + /// Defines the back office content section + /// + public class ContentBackOfficeSection : IBackOfficeSection + { + public string Alias => Constants.Applications.Content; + public string Name => "Content"; + } +} diff --git a/src/Umbraco.Web/Trees/ITree.cs b/src/Umbraco.Web/Trees/ITree.cs index 40be7338b0..f408ce5e60 100644 --- a/src/Umbraco.Web/Trees/ITree.cs +++ b/src/Umbraco.Web/Trees/ITree.cs @@ -1,5 +1,6 @@ namespace Umbraco.Web.Trees { + //fixme - we don't really use this, it is nice to have the treecontroller, attribute and ApplicationTree streamlined to implement this but it's not used public interface ITree { /// diff --git a/src/Umbraco.Web/Trees/MediaBackOfficeSection.cs b/src/Umbraco.Web/Trees/MediaBackOfficeSection.cs new file mode 100644 index 0000000000..aac4fd036f --- /dev/null +++ b/src/Umbraco.Web/Trees/MediaBackOfficeSection.cs @@ -0,0 +1,15 @@ +using Umbraco.Core; +using Umbraco.Web.Models.ContentEditing; +using Umbraco.Web.Models.Trees; + +namespace Umbraco.Web.Trees +{ + /// + /// Defines the back office media section + /// + public class MediaBackOfficeSection : IBackOfficeSection + { + public string Alias => Constants.Applications.Media; + public string Name => "Media"; + } +} \ No newline at end of file diff --git a/src/Umbraco.Web/Trees/MembersBackOfficeSection.cs b/src/Umbraco.Web/Trees/MembersBackOfficeSection.cs new file mode 100644 index 0000000000..bfaead33d5 --- /dev/null +++ b/src/Umbraco.Web/Trees/MembersBackOfficeSection.cs @@ -0,0 +1,15 @@ +using Umbraco.Core; +using Umbraco.Web.Models.ContentEditing; +using Umbraco.Web.Models.Trees; + +namespace Umbraco.Web.Trees +{ + /// + /// Defines the back office members section + /// + public class MembersBackOfficeSection : IBackOfficeSection + { + public string Alias => Constants.Applications.Members; + public string Name => "Members"; + } +} \ No newline at end of file diff --git a/src/Umbraco.Web/Trees/PackagesBackOfficeSection.cs b/src/Umbraco.Web/Trees/PackagesBackOfficeSection.cs new file mode 100644 index 0000000000..41f049c092 --- /dev/null +++ b/src/Umbraco.Web/Trees/PackagesBackOfficeSection.cs @@ -0,0 +1,15 @@ +using Umbraco.Core; +using Umbraco.Web.Models.ContentEditing; +using Umbraco.Web.Models.Trees; + +namespace Umbraco.Web.Trees +{ + /// + /// Defines the back office packages section + /// + public class PackagesBackOfficeSection : IBackOfficeSection + { + public string Alias => Constants.Applications.Packages; + public string Name => "Packages"; + } +} \ No newline at end of file diff --git a/src/Umbraco.Web/Trees/SettingsBackOfficeSection.cs b/src/Umbraco.Web/Trees/SettingsBackOfficeSection.cs new file mode 100644 index 0000000000..623f593c30 --- /dev/null +++ b/src/Umbraco.Web/Trees/SettingsBackOfficeSection.cs @@ -0,0 +1,15 @@ +using Umbraco.Core; +using Umbraco.Web.Models.ContentEditing; +using Umbraco.Web.Models.Trees; + +namespace Umbraco.Web.Trees +{ + /// + /// Defines the back office settings section + /// + public class SettingsBackOfficeSection : IBackOfficeSection + { + public string Alias => Constants.Applications.Settings; + public string Name => "Settings"; + } +} \ No newline at end of file diff --git a/src/Umbraco.Web/Trees/TranslationBackOfficeSection.cs b/src/Umbraco.Web/Trees/TranslationBackOfficeSection.cs new file mode 100644 index 0000000000..41254b3179 --- /dev/null +++ b/src/Umbraco.Web/Trees/TranslationBackOfficeSection.cs @@ -0,0 +1,15 @@ +using Umbraco.Core; +using Umbraco.Web.Models.ContentEditing; +using Umbraco.Web.Models.Trees; + +namespace Umbraco.Web.Trees +{ + /// + /// Defines the back office translation section + /// + public class TranslationBackOfficeSection : IBackOfficeSection + { + public string Alias => Constants.Applications.Translation; + public string Name => "Translation"; + } +} \ No newline at end of file diff --git a/src/Umbraco.Web/Trees/TreeCollection.cs b/src/Umbraco.Web/Trees/TreeCollection.cs index c7b60dea16..51b79ce67b 100644 --- a/src/Umbraco.Web/Trees/TreeCollection.cs +++ b/src/Umbraco.Web/Trees/TreeCollection.cs @@ -16,31 +16,4 @@ namespace Umbraco.Web.Trees : base(items) { } } - - public class TreeCollectionBuilder : LazyCollectionBuilderBase - { - protected override TreeCollectionBuilder This => this; - - private readonly List _instances = new List(); - - public void AddTree(ApplicationTree tree) - { - _instances.Add(tree); - } - - protected override IEnumerable CreateItems(IFactory factory) - { - return _instances; - - //var items = base.CreateItems(factory).ToList(); - //throw new NotImplementedException(); - ////validate the items, no actions should exist that do not either expose notifications or permissions - //var invalidItems = items.Where(x => !x.CanBePermissionAssigned && !x.ShowInNotifier).ToList(); - //if (invalidItems.Count == 0) return items; - - //var invalidActions = string.Join(", ", invalidItems.Select(x => "'" + x.Alias + "'")); - //throw new InvalidOperationException($"Invalid actions {invalidActions}'. All {typeof(IAction)} implementations must be true for either {nameof(IAction.CanBePermissionAssigned)} or {nameof(IAction.ShowInNotifier)}."); - } - } - } diff --git a/src/Umbraco.Web/Trees/TreeCollectionBuilder.cs b/src/Umbraco.Web/Trees/TreeCollectionBuilder.cs new file mode 100644 index 0000000000..2f92e72419 --- /dev/null +++ b/src/Umbraco.Web/Trees/TreeCollectionBuilder.cs @@ -0,0 +1,18 @@ +using System.Collections.Generic; +using Umbraco.Core.Composing; + +namespace Umbraco.Web.Trees +{ + //fixme - how will we allow users to modify these items? they will need to be able to change the ApplicationTree's registered (i.e. sort order, section) + public class TreeCollectionBuilder : CollectionBuilderBase + { + private readonly List _instances = new List(); + + public void AddTree(ApplicationTree tree) + { + _instances.Add(tree); + } + + protected override IEnumerable CreateItems(IFactory factory) => _instances; + } +} diff --git a/src/Umbraco.Web/Trees/UsersBackOfficeSection.cs b/src/Umbraco.Web/Trees/UsersBackOfficeSection.cs new file mode 100644 index 0000000000..90a65cb508 --- /dev/null +++ b/src/Umbraco.Web/Trees/UsersBackOfficeSection.cs @@ -0,0 +1,15 @@ +using Umbraco.Core; +using Umbraco.Web.Models.ContentEditing; +using Umbraco.Web.Models.Trees; + +namespace Umbraco.Web.Trees +{ + /// + /// Defines the back office users section + /// + public class UsersBackOfficeSection : IBackOfficeSection + { + public string Alias => Constants.Applications.Users; + public string Name => "Users"; + } +} \ No newline at end of file diff --git a/src/Umbraco.Web/Umbraco.Web.csproj b/src/Umbraco.Web/Umbraco.Web.csproj index 0b1603c9e3..161f6c6689 100755 --- a/src/Umbraco.Web/Umbraco.Web.csproj +++ b/src/Umbraco.Web/Umbraco.Web.csproj @@ -166,8 +166,16 @@ + + + + + + + + - + @@ -591,7 +599,7 @@ - + @@ -673,7 +681,6 @@ - @@ -970,7 +977,7 @@ - + From 77dd816c514e13c487ce6b258af0dbdde4d932cb Mon Sep 17 00:00:00 2001 From: Shannon Date: Thu, 17 Jan 2019 17:06:22 +1100 Subject: [PATCH 04/11] more cleanup --- .../UI/Pages/UmbracoEnsuredPage.cs | 14 ++--- src/Umbraco.Web/Umbraco.Web.csproj | 1 - .../_Legacy/PackageActions/addApplication.cs | 61 ------------------- 3 files changed, 6 insertions(+), 70 deletions(-) delete mode 100644 src/Umbraco.Web/_Legacy/PackageActions/addApplication.cs diff --git a/src/Umbraco.Web/UI/Pages/UmbracoEnsuredPage.cs b/src/Umbraco.Web/UI/Pages/UmbracoEnsuredPage.cs index 9e632eabc9..cafdfb0e04 100644 --- a/src/Umbraco.Web/UI/Pages/UmbracoEnsuredPage.cs +++ b/src/Umbraco.Web/UI/Pages/UmbracoEnsuredPage.cs @@ -29,14 +29,12 @@ namespace Umbraco.Web.UI.Pages var treeAuth = this.GetType().GetCustomAttribute(true); if (treeAuth != null) { - throw new NotImplementedException(); - - //var treeByAlias = Current.Services.ApplicationTreeService - // .GetByAlias(treeAuth.TreeAlias); - //if (treeByAlias != null) - //{ - // CurrentApp = treeByAlias.ApplicationAlias; - //} + var treeByAlias = Current.TreeService + .GetByAlias(treeAuth.TreeAlias); + if (treeByAlias != null) + { + CurrentApp = treeByAlias.ApplicationAlias; + } } } diff --git a/src/Umbraco.Web/Umbraco.Web.csproj b/src/Umbraco.Web/Umbraco.Web.csproj index 161f6c6689..8c1a0639c4 100755 --- a/src/Umbraco.Web/Umbraco.Web.csproj +++ b/src/Umbraco.Web/Umbraco.Web.csproj @@ -1138,7 +1138,6 @@ - diff --git a/src/Umbraco.Web/_Legacy/PackageActions/addApplication.cs b/src/Umbraco.Web/_Legacy/PackageActions/addApplication.cs deleted file mode 100644 index c6d5ba30d9..0000000000 --- a/src/Umbraco.Web/_Legacy/PackageActions/addApplication.cs +++ /dev/null @@ -1,61 +0,0 @@ -//using System; -//using System.Xml; -//using System.Xml.Linq; -//using Umbraco.Core; -//using Umbraco.Core._Legacy.PackageActions; -//using Umbraco.Web.Composing; - -//namespace Umbraco.Web._Legacy.PackageActions -//{ -// /// -// /// This class implements the IPackageAction Interface, used to execute code when packages are installed. -// /// All IPackageActions only takes a PackageName and a XmlNode as input, and executes based on the data in the xmlnode. -// /// -// public class AddApplication : IPackageAction -// { - -// #region IPackageAction Members - -// /// -// /// Installs a new application in umbraco. -// /// -// /// Name of the package. -// /// The XML data. -// /// -// /// -// /// -// /// true if successfull -// public bool Execute(string packageName, XElement xmlData) -// { -// string name = xmlData.AttributeValue("appName"); -// string alias = xmlData.AttributeValue("appAlias"); -// string icon = xmlData.AttributeValue("appIcon"); - -// Current.Services.SectionService.MakeNew(name, alias, icon); - -// return true; -// } - -// public bool Undo(string packageName, XElement xmlData) -// { -// string alias = xmlData.AttributeValue("appAlias"); -// var section = Current.Services.SectionService.GetByAlias(alias); -// if (section != null) -// { -// Current.Services.SectionService.DeleteSection(section); -// } -// return true; -// } -// /// -// /// Action alias. -// /// -// /// -// public string Alias() -// { -// return "addApplication"; -// } - -// #endregion - -// } -//} From 9df1773b78d38a3ff59c65193702ef7e3ba73cfe Mon Sep 17 00:00:00 2001 From: Shannon Date: Thu, 17 Jan 2019 17:08:58 +1100 Subject: [PATCH 05/11] more cleanup --- build/NuSpecs/UmbracoCms.nuspec | 2 -- src/Umbraco.Core/Composing/TypeLoader.cs | 4 +-- src/Umbraco.Web.UI/Umbraco.Web.UI.csproj | 11 ------ .../config/applications.Release.config | 11 ------ src/Umbraco.Web.UI/config/applications.config | 11 ------ .../config/trees.Release.config | 34 ------------------ src/Umbraco.Web.UI/config/trees.config | 36 ------------------- 7 files changed, 1 insertion(+), 108 deletions(-) delete mode 100644 src/Umbraco.Web.UI/config/applications.Release.config delete mode 100644 src/Umbraco.Web.UI/config/applications.config delete mode 100644 src/Umbraco.Web.UI/config/trees.Release.config delete mode 100644 src/Umbraco.Web.UI/config/trees.config diff --git a/build/NuSpecs/UmbracoCms.nuspec b/build/NuSpecs/UmbracoCms.nuspec index 3cb3d0d875..a188377c19 100644 --- a/build/NuSpecs/UmbracoCms.nuspec +++ b/build/NuSpecs/UmbracoCms.nuspec @@ -52,10 +52,8 @@ - - diff --git a/src/Umbraco.Core/Composing/TypeLoader.cs b/src/Umbraco.Core/Composing/TypeLoader.cs index acb12ab575..4c4139848d 100644 --- a/src/Umbraco.Core/Composing/TypeLoader.cs +++ b/src/Umbraco.Core/Composing/TypeLoader.cs @@ -185,9 +185,7 @@ namespace Umbraco.Core.Composing // the app code folder and everything in it new Tuple(new DirectoryInfo(IOHelper.MapPath("~/App_Code")), false), // global.asax (the app domain also monitors this, if it changes will do a full restart) - new Tuple(new FileInfo(IOHelper.MapPath("~/global.asax")), false), - // trees.config - use the contents to create the hash since this gets resaved on every app startup! - new Tuple(new FileInfo(IOHelper.MapPath(SystemDirectories.Config + "/trees.config")), true) + new Tuple(new FileInfo(IOHelper.MapPath("~/global.asax")), false) }, _logger); return _currentAssembliesHash; diff --git a/src/Umbraco.Web.UI/Umbraco.Web.UI.csproj b/src/Umbraco.Web.UI/Umbraco.Web.UI.csproj index c21bf7fef6..778ab188cd 100644 --- a/src/Umbraco.Web.UI/Umbraco.Web.UI.csproj +++ b/src/Umbraco.Web.UI/Umbraco.Web.UI.csproj @@ -241,9 +241,6 @@ umbracoSettings.config Designer - - trees.config - tinyMceConfig.config Designer @@ -301,14 +298,6 @@ - - - Designer - - - applications.config - Designer - diff --git a/src/Umbraco.Web.UI/config/applications.Release.config b/src/Umbraco.Web.UI/config/applications.Release.config deleted file mode 100644 index 5c8dee3b8a..0000000000 --- a/src/Umbraco.Web.UI/config/applications.Release.config +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - diff --git a/src/Umbraco.Web.UI/config/applications.config b/src/Umbraco.Web.UI/config/applications.config deleted file mode 100644 index 5c8dee3b8a..0000000000 --- a/src/Umbraco.Web.UI/config/applications.config +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - diff --git a/src/Umbraco.Web.UI/config/trees.Release.config b/src/Umbraco.Web.UI/config/trees.Release.config deleted file mode 100644 index bd75e97c38..0000000000 --- a/src/Umbraco.Web.UI/config/trees.Release.config +++ /dev/null @@ -1,34 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/Umbraco.Web.UI/config/trees.config b/src/Umbraco.Web.UI/config/trees.config deleted file mode 100644 index 5892545682..0000000000 --- a/src/Umbraco.Web.UI/config/trees.config +++ /dev/null @@ -1,36 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - From 1a734141f18a6e25493e1b6fef7ab0188b5ec3d6 Mon Sep 17 00:00:00 2001 From: Shannon Date: Thu, 17 Jan 2019 17:31:29 +1100 Subject: [PATCH 06/11] Allows package manifest to declare a section --- src/Umbraco.Core/Manifest/ManifestParser.cs | 7 +++- src/Umbraco.Core/Manifest/PackageManifest.cs | 7 ++++ .../Manifest/ManifestParserTests.cs | 18 ++++++++++ src/Umbraco.Web/Services/SectionService.cs | 13 ------- .../Trees/BackOfficeSectionCollection.cs | 1 + .../BackOfficeSectionCollectionBuilder.cs | 35 ++++++++++++++++++- 6 files changed, 66 insertions(+), 15 deletions(-) diff --git a/src/Umbraco.Core/Manifest/ManifestParser.cs b/src/Umbraco.Core/Manifest/ManifestParser.cs index 59753df66a..28493fe20f 100644 --- a/src/Umbraco.Core/Manifest/ManifestParser.cs +++ b/src/Umbraco.Core/Manifest/ManifestParser.cs @@ -101,6 +101,7 @@ namespace Umbraco.Core.Manifest var gridEditors = new List(); var contentApps = new List(); var dashboards = new List(); + var sections = new Dictionary(); foreach (var manifest in manifests) { @@ -111,6 +112,9 @@ namespace Umbraco.Core.Manifest if (manifest.GridEditors != null) gridEditors.AddRange(manifest.GridEditors); if (manifest.ContentApps != null) contentApps.AddRange(manifest.ContentApps); if (manifest.Dashboards != null) dashboards.AddRange(manifest.Dashboards); + if (manifest.Sections != null) + foreach (var (key, value) in manifest.Sections) + sections[key] = value; } return new PackageManifest @@ -121,7 +125,8 @@ namespace Umbraco.Core.Manifest ParameterEditors = parameterEditors.ToArray(), GridEditors = gridEditors.ToArray(), ContentApps = contentApps.ToArray(), - Dashboards = dashboards.ToArray() + Dashboards = dashboards.ToArray(), + Sections = sections }; } diff --git a/src/Umbraco.Core/Manifest/PackageManifest.cs b/src/Umbraco.Core/Manifest/PackageManifest.cs index cd806ac847..a0546f3629 100644 --- a/src/Umbraco.Core/Manifest/PackageManifest.cs +++ b/src/Umbraco.Core/Manifest/PackageManifest.cs @@ -1,4 +1,5 @@ using System; +using System.Collections.Generic; using Newtonsoft.Json; using Umbraco.Core.Models.ContentEditing; using Umbraco.Core.PropertyEditors; @@ -30,5 +31,11 @@ namespace Umbraco.Core.Manifest [JsonProperty("dashboards")] public ManifestDashboardDefinition[] Dashboards { get; set; } = Array.Empty(); + + /// + /// Declares the back office sections that this package installs + /// + [JsonProperty("sections")] + public IReadOnlyDictionary Sections { get; set; } = new Dictionary(); } } diff --git a/src/Umbraco.Tests/Manifest/ManifestParserTests.cs b/src/Umbraco.Tests/Manifest/ManifestParserTests.cs index ce3d1d705c..9970d5f6b0 100644 --- a/src/Umbraco.Tests/Manifest/ManifestParserTests.cs +++ b/src/Umbraco.Tests/Manifest/ManifestParserTests.cs @@ -429,5 +429,23 @@ javascript: ['~/test.js',/*** some note about stuff asd09823-4**09234*/ '~/test2 Assert.AreEqual(1, db1.Sections.Length); Assert.AreEqual("forms", db1.Sections[0]); } + + [Test] + public void CanParseManifest_Sections() + { + const string json = @"{'sections': { + 'content': 'Content', + 'hello': 'World' + } +}"; + + var manifest = _parser.ParseManifest(json); + Assert.AreEqual(2, manifest.Sections.Count); + Assert.AreEqual("content", manifest.Sections.Keys.ElementAt(0)); + Assert.AreEqual("hello", manifest.Sections.Keys.ElementAt(1)); + Assert.AreEqual("Content", manifest.Sections["content"]); + Assert.AreEqual("World", manifest.Sections["hello"]); + + } } } diff --git a/src/Umbraco.Web/Services/SectionService.cs b/src/Umbraco.Web/Services/SectionService.cs index e6af27534c..b17b9f965a 100644 --- a/src/Umbraco.Web/Services/SectionService.cs +++ b/src/Umbraco.Web/Services/SectionService.cs @@ -1,22 +1,9 @@ using System; -using System.Collections; using System.Collections.Generic; -using System.IO; using System.Linq; -using System.Xml.Linq; -using Umbraco.Core; -using Umbraco.Core.Cache; -using Umbraco.Core.Events; -using Umbraco.Core.IO; -using Umbraco.Core.Models; -using Umbraco.Core.Composing; -using Umbraco.Core.Models.ContentEditing; -using Umbraco.Core.Scoping; using Umbraco.Core.Services; -using Umbraco.Web.Models.ContentEditing; using Umbraco.Web.Models.Trees; using Umbraco.Web.Trees; -using File = System.IO.File; namespace Umbraco.Web.Services { diff --git a/src/Umbraco.Web/Trees/BackOfficeSectionCollection.cs b/src/Umbraco.Web/Trees/BackOfficeSectionCollection.cs index 54762e73d8..fdeb812363 100644 --- a/src/Umbraco.Web/Trees/BackOfficeSectionCollection.cs +++ b/src/Umbraco.Web/Trees/BackOfficeSectionCollection.cs @@ -11,5 +11,6 @@ namespace Umbraco.Web.Trees public BackOfficeSectionCollection(IEnumerable items) : base(items) { } + } } diff --git a/src/Umbraco.Web/Trees/BackOfficeSectionCollectionBuilder.cs b/src/Umbraco.Web/Trees/BackOfficeSectionCollectionBuilder.cs index 62d61a4090..ec5833f79c 100644 --- a/src/Umbraco.Web/Trees/BackOfficeSectionCollectionBuilder.cs +++ b/src/Umbraco.Web/Trees/BackOfficeSectionCollectionBuilder.cs @@ -1,10 +1,43 @@ -using Umbraco.Core.Composing; +using System.Collections.Generic; +using System.Linq; +using Umbraco.Core.Composing; +using Umbraco.Core.Manifest; +using Umbraco.Core.Models.ContentEditing; using Umbraco.Web.Models.Trees; namespace Umbraco.Web.Trees { + //fixme: how can a developer re-sort the items in this collection ? public class BackOfficeSectionCollectionBuilder : OrderedCollectionBuilderBase { protected override BackOfficeSectionCollectionBuilder This => this; + + // need to inject dependencies in the collection, so override creation + public override BackOfficeSectionCollection CreateCollection(IFactory factory) + { + return new BackOfficeSectionCollection(CreateItems(factory)); + } + + protected override IEnumerable CreateItems(IFactory factory) + { + // get the manifest parser just-in-time - injecting it in the ctor would mean that + // simply getting the builder in order to configure the collection, would require + // its dependencies too, and that can create cycles or other oddities + var manifestParser = factory.GetInstance(); + + return base.CreateItems(factory).Concat(manifestParser.Manifest.Sections.Select(x => new ManifestBackOfficeSection(x.Key, x.Value))); + } + + private class ManifestBackOfficeSection : IBackOfficeSection + { + public ManifestBackOfficeSection(string @alias, string name) + { + Alias = alias; + Name = name; + } + + public string Alias { get; } + public string Name { get; } + } } } From 356209e013f93cf9b7b890a3c7067ce6830dac42 Mon Sep 17 00:00:00 2001 From: Shannon Date: Thu, 17 Jan 2019 17:33:38 +1100 Subject: [PATCH 07/11] renames ApplicationTree to just Tree --- src/Umbraco.Web/Editors/EntityController.cs | 2 +- src/Umbraco.Web/Runtime/WebRuntimeComposer.cs | 2 +- src/Umbraco.Web/Services/ITreeService.cs | 8 ++++---- src/Umbraco.Web/Services/TreeService.cs | 14 +++++++------- src/Umbraco.Web/Trees/ApplicationTreeController.cs | 8 ++++---- .../Trees/{ApplicationTree.cs => Tree.cs} | 4 ++-- src/Umbraco.Web/Trees/TreeCollection.cs | 4 ++-- src/Umbraco.Web/Trees/TreeCollectionBuilder.cs | 8 ++++---- src/Umbraco.Web/Trees/TreeController.cs | 2 +- src/Umbraco.Web/Umbraco.Web.csproj | 2 +- 10 files changed, 27 insertions(+), 27 deletions(-) rename src/Umbraco.Web/Trees/{ApplicationTree.cs => Tree.cs} (91%) diff --git a/src/Umbraco.Web/Editors/EntityController.cs b/src/Umbraco.Web/Editors/EntityController.cs index ca1a6a12bb..e376f9ad5b 100644 --- a/src/Umbraco.Web/Editors/EntityController.cs +++ b/src/Umbraco.Web/Editors/EntityController.cs @@ -148,7 +148,7 @@ namespace Umbraco.Web.Editors var searchableTreeAttribute = searchableTree.Value.SearchableTree.GetType().GetCustomAttribute(false); - result[ApplicationTree.GetRootNodeDisplayName(tree, Services.TextService)] = new TreeSearchResult + result[Tree.GetRootNodeDisplayName(tree, Services.TextService)] = new TreeSearchResult { Results = searchableTree.Value.SearchableTree.Search(query, 200, 0, out var total), TreeAlias = searchableTree.Key, diff --git a/src/Umbraco.Web/Runtime/WebRuntimeComposer.cs b/src/Umbraco.Web/Runtime/WebRuntimeComposer.cs index 134ed7b1d0..f21c040a37 100644 --- a/src/Umbraco.Web/Runtime/WebRuntimeComposer.cs +++ b/src/Umbraco.Web/Runtime/WebRuntimeComposer.cs @@ -211,7 +211,7 @@ namespace Umbraco.Web.Runtime { var attribute = treeControllerType.GetCustomAttribute(false); if (attribute == null) continue; - var tree = new ApplicationTree(attribute.SortOrder, attribute.ApplicationAlias, attribute.TreeAlias, attribute.TreeTitle, treeControllerType, attribute.IsSingleNodeTree); + var tree = new Tree(attribute.SortOrder, attribute.ApplicationAlias, attribute.TreeAlias, attribute.TreeTitle, treeControllerType, attribute.IsSingleNodeTree); composition.WithCollectionBuilder().AddTree(tree); } } diff --git a/src/Umbraco.Web/Services/ITreeService.cs b/src/Umbraco.Web/Services/ITreeService.cs index 17998ae1a7..5172e4b7b7 100644 --- a/src/Umbraco.Web/Services/ITreeService.cs +++ b/src/Umbraco.Web/Services/ITreeService.cs @@ -15,27 +15,27 @@ namespace Umbraco.Web.Services /// /// The tree alias. /// An ApplicationTree instance - ApplicationTree GetByAlias(string treeAlias); + Tree GetByAlias(string treeAlias); /// /// Gets all applicationTrees registered in umbraco from the umbracoAppTree table.. /// /// Returns a ApplicationTree Array - IEnumerable GetAll(); + IEnumerable GetAll(); /// /// Gets the application tree for the applcation with the specified alias /// /// The application alias. /// Returns a ApplicationTree Array - IEnumerable GetApplicationTrees(string applicationAlias); + IEnumerable GetApplicationTrees(string applicationAlias); /// /// Gets the grouped application trees for the application with the specified alias /// /// /// - IDictionary> GetGroupedApplicationTrees(string applicationAlias); + IDictionary> GetGroupedApplicationTrees(string applicationAlias); } } diff --git a/src/Umbraco.Web/Services/TreeService.cs b/src/Umbraco.Web/Services/TreeService.cs index 670f57ce49..8389c27a19 100644 --- a/src/Umbraco.Web/Services/TreeService.cs +++ b/src/Umbraco.Web/Services/TreeService.cs @@ -18,29 +18,29 @@ namespace Umbraco.Web.Services } /// - public ApplicationTree GetByAlias(string treeAlias) => _treeCollection.FirstOrDefault(t => t.TreeAlias == treeAlias); + public Tree GetByAlias(string treeAlias) => _treeCollection.FirstOrDefault(t => t.TreeAlias == treeAlias); /// - public IEnumerable GetAll() => _treeCollection; + public IEnumerable GetAll() => _treeCollection; /// - public IEnumerable GetApplicationTrees(string applicationAlias) + public IEnumerable GetApplicationTrees(string applicationAlias) => GetAll().Where(x => x.ApplicationAlias.InvariantEquals(applicationAlias)).OrderBy(x => x.SortOrder).ToList(); - public IDictionary> GetGroupedApplicationTrees(string applicationAlias) + public IDictionary> GetGroupedApplicationTrees(string applicationAlias) { - var result = new Dictionary>(); + var result = new Dictionary>(); var foundTrees = GetApplicationTrees(applicationAlias).ToList(); foreach(var treeGroup in _groupedTrees.Value) { - List resultGroup = null; + List resultGroup = null; foreach(var tree in foundTrees) { foreach(var treeAliasInGroup in treeGroup) { if (tree.TreeAlias != treeAliasInGroup) continue; - if (resultGroup == null) resultGroup = new List(); + if (resultGroup == null) resultGroup = new List(); resultGroup.Add(tree); } } diff --git a/src/Umbraco.Web/Trees/ApplicationTreeController.cs b/src/Umbraco.Web/Trees/ApplicationTreeController.cs index 0e405ca3f3..5a0f72c8dc 100644 --- a/src/Umbraco.Web/Trees/ApplicationTreeController.cs +++ b/src/Umbraco.Web/Trees/ApplicationTreeController.cs @@ -160,7 +160,7 @@ namespace Umbraco.Web.Trees /// /// /// - private async Task GetRootForMultipleAppTree(ApplicationTree tree, FormDataCollection queryStrings) + private async Task GetRootForMultipleAppTree(Tree tree, FormDataCollection queryStrings) { if (tree == null) throw new ArgumentNullException(nameof(tree)); try @@ -189,7 +189,7 @@ namespace Umbraco.Web.Trees /// /// /// - private async Task GetRootForSingleAppTree(ApplicationTree tree, string id, FormDataCollection queryStrings, string application) + private async Task GetRootForSingleAppTree(Tree tree, string id, FormDataCollection queryStrings, string application) { var rootId = Constants.System.Root.ToString(CultureInfo.InvariantCulture); if (tree == null) throw new ArgumentNullException(nameof(tree)); @@ -234,7 +234,7 @@ namespace Umbraco.Web.Trees /// /// This ensures that authorization filters are applied to the sub request /// - private async Task> TryGetRootNodeFromControllerTree(ApplicationTree appTree, FormDataCollection formCollection, HttpControllerContext controllerContext) + private async Task> TryGetRootNodeFromControllerTree(Tree appTree, FormDataCollection formCollection, HttpControllerContext controllerContext) { //instantiate it, since we are proxying, we need to setup the instance with our current context var instance = (TreeController)DependencyResolver.Current.GetService(appTree.TreeControllerType); @@ -290,7 +290,7 @@ namespace Umbraco.Web.Trees /// /// /// - private Attempt TryLoadFromControllerTree(ApplicationTree appTree, string id, FormDataCollection formCollection, HttpControllerContext controllerContext) + private Attempt TryLoadFromControllerTree(Tree appTree, string id, FormDataCollection formCollection, HttpControllerContext controllerContext) { // instantiate it, since we are proxying, we need to setup the instance with our current context var instance = (TreeController)DependencyResolver.Current.GetService(appTree.TreeControllerType); diff --git a/src/Umbraco.Web/Trees/ApplicationTree.cs b/src/Umbraco.Web/Trees/Tree.cs similarity index 91% rename from src/Umbraco.Web/Trees/ApplicationTree.cs rename to src/Umbraco.Web/Trees/Tree.cs index 5ed9847be3..3bac5bae58 100644 --- a/src/Umbraco.Web/Trees/ApplicationTree.cs +++ b/src/Umbraco.Web/Trees/Tree.cs @@ -6,9 +6,9 @@ using Umbraco.Web.Models.Trees; namespace Umbraco.Web.Trees { [DebuggerDisplay("Tree - {TreeAlias} ({ApplicationAlias})")] - public class ApplicationTree : ITree + public class Tree : ITree { - public ApplicationTree(int sortOrder, string applicationAlias, string alias, string title, Type treeControllerType, bool isSingleNodeTree) + public Tree(int sortOrder, string applicationAlias, string alias, string title, Type treeControllerType, bool isSingleNodeTree) { SortOrder = sortOrder; ApplicationAlias = applicationAlias; diff --git a/src/Umbraco.Web/Trees/TreeCollection.cs b/src/Umbraco.Web/Trees/TreeCollection.cs index 51b79ce67b..a7bfe52295 100644 --- a/src/Umbraco.Web/Trees/TreeCollection.cs +++ b/src/Umbraco.Web/Trees/TreeCollection.cs @@ -10,9 +10,9 @@ using Umbraco.Web.Models.ContentEditing; namespace Umbraco.Web.Trees { - public class TreeCollection : BuilderCollectionBase + public class TreeCollection : BuilderCollectionBase { - public TreeCollection(IEnumerable items) + public TreeCollection(IEnumerable items) : base(items) { } } diff --git a/src/Umbraco.Web/Trees/TreeCollectionBuilder.cs b/src/Umbraco.Web/Trees/TreeCollectionBuilder.cs index 2f92e72419..143b8e308b 100644 --- a/src/Umbraco.Web/Trees/TreeCollectionBuilder.cs +++ b/src/Umbraco.Web/Trees/TreeCollectionBuilder.cs @@ -4,15 +4,15 @@ using Umbraco.Core.Composing; namespace Umbraco.Web.Trees { //fixme - how will we allow users to modify these items? they will need to be able to change the ApplicationTree's registered (i.e. sort order, section) - public class TreeCollectionBuilder : CollectionBuilderBase + public class TreeCollectionBuilder : CollectionBuilderBase { - private readonly List _instances = new List(); + private readonly List _instances = new List(); - public void AddTree(ApplicationTree tree) + public void AddTree(Tree tree) { _instances.Add(tree); } - protected override IEnumerable CreateItems(IFactory factory) => _instances; + protected override IEnumerable CreateItems(IFactory factory) => _instances; } } diff --git a/src/Umbraco.Web/Trees/TreeController.cs b/src/Umbraco.Web/Trees/TreeController.cs index 63e8f5aad5..553cda255e 100644 --- a/src/Umbraco.Web/Trees/TreeController.cs +++ b/src/Umbraco.Web/Trees/TreeController.cs @@ -28,7 +28,7 @@ namespace Umbraco.Web.Trees } /// - public override string RootNodeDisplayName => ApplicationTree.GetRootNodeDisplayName(this, Services.TextService); + public override string RootNodeDisplayName => Tree.GetRootNodeDisplayName(this, Services.TextService); /// public override string TreeAlias => _attribute.TreeAlias; diff --git a/src/Umbraco.Web/Umbraco.Web.csproj b/src/Umbraco.Web/Umbraco.Web.csproj index 8c1a0639c4..23cbb7a416 100755 --- a/src/Umbraco.Web/Umbraco.Web.csproj +++ b/src/Umbraco.Web/Umbraco.Web.csproj @@ -174,7 +174,7 @@ - + From 6b9ba3c53c806b2943f531bb71e0fc247ee243e3 Mon Sep 17 00:00:00 2001 From: Shannon Date: Thu, 17 Jan 2019 17:50:59 +1100 Subject: [PATCH 08/11] Fixing tests --- src/Umbraco.Tests/Services/SectionServiceTests.cs | 9 +++------ src/Umbraco.Tests/Testing/UmbracoTestBase.cs | 11 +++++++++++ src/Umbraco.Web/Services/SectionService.cs | 4 ++-- 3 files changed, 16 insertions(+), 8 deletions(-) diff --git a/src/Umbraco.Tests/Services/SectionServiceTests.cs b/src/Umbraco.Tests/Services/SectionServiceTests.cs index 9211755251..87fcde34ad 100644 --- a/src/Umbraco.Tests/Services/SectionServiceTests.cs +++ b/src/Umbraco.Tests/Services/SectionServiceTests.cs @@ -1,6 +1,7 @@ using NUnit.Framework; using System.Linq; using System.Threading; +using Umbraco.Core.Composing; using Umbraco.Core.Models.Membership; using Umbraco.Tests.Testing; using Umbraco.Web.Services; @@ -15,15 +16,11 @@ namespace Umbraco.Tests.Services [UmbracoTest(Database = UmbracoTestOptions.Database.NewSchemaPerTest, WithApplication = true)] public class SectionServiceTests : TestWithSomeContentBase { - //fixme - private ISectionService SectionService => new SectionService(ServiceContext.UserService, null); - + private ISectionService SectionService => Factory.GetInstance(); [Test] public void SectionService_Can_Get_Allowed_Sections_For_User() { - //fixme - need to mock - // Arrange var user = CreateTestUser(); @@ -60,7 +57,7 @@ namespace Umbraco.Tests.Services Name = "Group B" }; userGroupB.AddAllowedSection("settings"); - userGroupB.AddAllowedSection("developer"); + userGroupB.AddAllowedSection("member"); ServiceContext.UserService.Save(userGroupB, new[] { user.Id }, false); return ServiceContext.UserService.GetUserById(user.Id); diff --git a/src/Umbraco.Tests/Testing/UmbracoTestBase.cs b/src/Umbraco.Tests/Testing/UmbracoTestBase.cs index 0a0999f2dc..ace50917ba 100644 --- a/src/Umbraco.Tests/Testing/UmbracoTestBase.cs +++ b/src/Umbraco.Tests/Testing/UmbracoTestBase.cs @@ -40,6 +40,7 @@ using Umbraco.Web.Composing.Composers; using Umbraco.Web.ContentApps; using Current = Umbraco.Core.Composing.Current; using Umbraco.Web.Routing; +using Umbraco.Web.Trees; namespace Umbraco.Tests.Testing { @@ -216,6 +217,16 @@ namespace Umbraco.Tests.Testing Composition.WithCollectionBuilder(); Composition.RegisterUnique(); Composition.RegisterUnique(); + + // register back office sections in the order we want them rendered + Composition.WithCollectionBuilder().Append() + .Append() + .Append() + .Append() + .Append() + .Append() + .Append(); + Composition.RegisterUnique(); } protected virtual void ComposeWtf() diff --git a/src/Umbraco.Web/Services/SectionService.cs b/src/Umbraco.Web/Services/SectionService.cs index b17b9f965a..089bdc5bd3 100644 --- a/src/Umbraco.Web/Services/SectionService.cs +++ b/src/Umbraco.Web/Services/SectionService.cs @@ -16,8 +16,8 @@ namespace Umbraco.Web.Services IUserService userService, BackOfficeSectionCollection sectionCollection) { - _userService = userService; - _sectionCollection = sectionCollection; + _userService = userService ?? throw new ArgumentNullException(nameof(userService)); + _sectionCollection = sectionCollection ?? throw new ArgumentNullException(nameof(sectionCollection)); } /// From 3f89558ddbc3d37081eb50ce5360f476839499ed Mon Sep 17 00:00:00 2001 From: Shannon Date: Thu, 17 Jan 2019 17:51:38 +1100 Subject: [PATCH 09/11] Fixing tests --- src/Umbraco.Tests/Composing/TypeFinderTests.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Umbraco.Tests/Composing/TypeFinderTests.cs b/src/Umbraco.Tests/Composing/TypeFinderTests.cs index 49c807b19f..2b9474310b 100644 --- a/src/Umbraco.Tests/Composing/TypeFinderTests.cs +++ b/src/Umbraco.Tests/Composing/TypeFinderTests.cs @@ -90,7 +90,7 @@ namespace Umbraco.Tests.Composing Assert.AreEqual(0, typesFound.Count()); // 0 classes in _assemblies are marked with [Tree] typesFound = TypeFinder.FindClassesWithAttribute(new[] { typeof (UmbracoContext).Assembly }); - Assert.AreEqual(22, typesFound.Count()); // + classes in Umbraco.Web are marked with [Tree] + Assert.AreEqual(21, typesFound.Count()); // + classes in Umbraco.Web are marked with [Tree] } private static IProfilingLogger GetTestProfilingLogger() From 1667e914cd4354f9edcb45cedeaf0d4b3108faad Mon Sep 17 00:00:00 2001 From: Shannon Date: Thu, 17 Jan 2019 18:38:55 +1100 Subject: [PATCH 10/11] Allows the tree collection to be manipulated by devs on startup, renames some things --- src/Umbraco.Web/Runtime/WebRuntimeComposer.cs | 13 +++++-------- src/Umbraco.Web/Services/ITreeService.cs | 8 ++++---- src/Umbraco.Web/Services/TreeService.cs | 8 ++++---- .../Trees/ApplicationTreeController.cs | 2 +- .../Trees/BackOfficeSectionCollectionBuilder.cs | 9 ++------- src/Umbraco.Web/Trees/ITree.cs | 3 ++- src/Umbraco.Web/Trees/Tree.cs | 2 +- src/Umbraco.Web/Trees/TreeCollectionBuilder.cs | 15 +++++++-------- 8 files changed, 26 insertions(+), 34 deletions(-) diff --git a/src/Umbraco.Web/Runtime/WebRuntimeComposer.cs b/src/Umbraco.Web/Runtime/WebRuntimeComposer.cs index f21c040a37..1a0bf8d1b0 100644 --- a/src/Umbraco.Web/Runtime/WebRuntimeComposer.cs +++ b/src/Umbraco.Web/Runtime/WebRuntimeComposer.cs @@ -1,15 +1,13 @@ -using System.Web; +using System.Linq; +using System.Web; using System.Web.Security; using Examine; using Microsoft.AspNet.SignalR; using Umbraco.Core; using Umbraco.Core.Components; using Umbraco.Core.Composing; -using Umbraco.Core.Configuration; using Umbraco.Core.Dictionary; using Umbraco.Core.Events; -using Umbraco.Core.Models; -using Umbraco.Core.Models.ContentEditing; using Umbraco.Core.Models.PublishedContent; using Umbraco.Core.PropertyEditors; using Umbraco.Core.PropertyEditors.ValueConverters; @@ -23,9 +21,7 @@ using Umbraco.Web.Dictionary; using Umbraco.Web.Editors; using Umbraco.Web.Features; using Umbraco.Web.HealthCheck; -using Umbraco.Web.Models.ContentEditing; using Umbraco.Web.Models.PublishedContent; -using Umbraco.Web.Models.Trees; using Umbraco.Web.Mvc; using Umbraco.Web.PublishedCache; using Umbraco.Web.Routing; @@ -207,12 +203,13 @@ namespace Umbraco.Web.Runtime .Append(); // register back office trees - foreach (var treeControllerType in umbracoApiControllerTypes) + foreach (var treeControllerType in umbracoApiControllerTypes + .Where(x => typeof(TreeControllerBase).IsAssignableFrom(x))) { var attribute = treeControllerType.GetCustomAttribute(false); if (attribute == null) continue; var tree = new Tree(attribute.SortOrder, attribute.ApplicationAlias, attribute.TreeAlias, attribute.TreeTitle, treeControllerType, attribute.IsSingleNodeTree); - composition.WithCollectionBuilder().AddTree(tree); + composition.WithCollectionBuilder().Trees.Add(tree); } } } diff --git a/src/Umbraco.Web/Services/ITreeService.cs b/src/Umbraco.Web/Services/ITreeService.cs index 5172e4b7b7..96787086c6 100644 --- a/src/Umbraco.Web/Services/ITreeService.cs +++ b/src/Umbraco.Web/Services/ITreeService.cs @@ -26,16 +26,16 @@ namespace Umbraco.Web.Services /// /// Gets the application tree for the applcation with the specified alias /// - /// The application alias. + /// The application alias. /// Returns a ApplicationTree Array - IEnumerable GetApplicationTrees(string applicationAlias); + IEnumerable GetTrees(string sectionAlias); /// /// Gets the grouped application trees for the application with the specified alias /// - /// + /// /// - IDictionary> GetGroupedApplicationTrees(string applicationAlias); + IDictionary> GetGroupedTrees(string sectionAlias); } } diff --git a/src/Umbraco.Web/Services/TreeService.cs b/src/Umbraco.Web/Services/TreeService.cs index 8389c27a19..f58dce59bc 100644 --- a/src/Umbraco.Web/Services/TreeService.cs +++ b/src/Umbraco.Web/Services/TreeService.cs @@ -24,13 +24,13 @@ namespace Umbraco.Web.Services public IEnumerable GetAll() => _treeCollection; /// - public IEnumerable GetApplicationTrees(string applicationAlias) - => GetAll().Where(x => x.ApplicationAlias.InvariantEquals(applicationAlias)).OrderBy(x => x.SortOrder).ToList(); + public IEnumerable GetTrees(string sectionAlias) + => GetAll().Where(x => x.ApplicationAlias.InvariantEquals(sectionAlias)).OrderBy(x => x.SortOrder).ToList(); - public IDictionary> GetGroupedApplicationTrees(string applicationAlias) + public IDictionary> GetGroupedTrees(string sectionAlias) { var result = new Dictionary>(); - var foundTrees = GetApplicationTrees(applicationAlias).ToList(); + var foundTrees = GetTrees(sectionAlias).ToList(); foreach(var treeGroup in _groupedTrees.Value) { List resultGroup = null; diff --git a/src/Umbraco.Web/Trees/ApplicationTreeController.cs b/src/Umbraco.Web/Trees/ApplicationTreeController.cs index 5a0f72c8dc..5433f3c157 100644 --- a/src/Umbraco.Web/Trees/ApplicationTreeController.cs +++ b/src/Umbraco.Web/Trees/ApplicationTreeController.cs @@ -60,7 +60,7 @@ namespace Umbraco.Web.Trees if (string.IsNullOrEmpty(application)) throw new HttpResponseException(HttpStatusCode.NotFound); //find all tree definitions that have the current application alias - var groupedTrees = _treeService.GetGroupedApplicationTrees(application); + var groupedTrees = _treeService.GetGroupedTrees(application); var allTrees = groupedTrees.Values.SelectMany(x => x).ToList(); if (string.IsNullOrEmpty(tree) == false || allTrees.Count == 1) diff --git a/src/Umbraco.Web/Trees/BackOfficeSectionCollectionBuilder.cs b/src/Umbraco.Web/Trees/BackOfficeSectionCollectionBuilder.cs index ec5833f79c..3228cd309f 100644 --- a/src/Umbraco.Web/Trees/BackOfficeSectionCollectionBuilder.cs +++ b/src/Umbraco.Web/Trees/BackOfficeSectionCollectionBuilder.cs @@ -12,12 +12,6 @@ namespace Umbraco.Web.Trees { protected override BackOfficeSectionCollectionBuilder This => this; - // need to inject dependencies in the collection, so override creation - public override BackOfficeSectionCollection CreateCollection(IFactory factory) - { - return new BackOfficeSectionCollection(CreateItems(factory)); - } - protected override IEnumerable CreateItems(IFactory factory) { // get the manifest parser just-in-time - injecting it in the ctor would mean that @@ -25,7 +19,8 @@ namespace Umbraco.Web.Trees // its dependencies too, and that can create cycles or other oddities var manifestParser = factory.GetInstance(); - return base.CreateItems(factory).Concat(manifestParser.Manifest.Sections.Select(x => new ManifestBackOfficeSection(x.Key, x.Value))); + return base.CreateItems(factory) + .Concat(manifestParser.Manifest.Sections.Select(x => new ManifestBackOfficeSection(x.Key, x.Value))); } private class ManifestBackOfficeSection : IBackOfficeSection diff --git a/src/Umbraco.Web/Trees/ITree.cs b/src/Umbraco.Web/Trees/ITree.cs index f408ce5e60..867beda20e 100644 --- a/src/Umbraco.Web/Trees/ITree.cs +++ b/src/Umbraco.Web/Trees/ITree.cs @@ -1,7 +1,8 @@ namespace Umbraco.Web.Trees { //fixme - we don't really use this, it is nice to have the treecontroller, attribute and ApplicationTree streamlined to implement this but it's not used - public interface ITree + //leave as internal for now, maybe we'll use in the future, means we could pass around ITree + internal interface ITree { /// /// Gets or sets the sort order. diff --git a/src/Umbraco.Web/Trees/Tree.cs b/src/Umbraco.Web/Trees/Tree.cs index 3bac5bae58..39f5cec1eb 100644 --- a/src/Umbraco.Web/Trees/Tree.cs +++ b/src/Umbraco.Web/Trees/Tree.cs @@ -43,7 +43,7 @@ namespace Umbraco.Web.Trees public Type TreeControllerType { get; } - public static string GetRootNodeDisplayName(ITree tree, ILocalizedTextService textService) + internal static string GetRootNodeDisplayName(ITree tree, ILocalizedTextService textService) { var label = $"[{tree.TreeAlias}]"; diff --git a/src/Umbraco.Web/Trees/TreeCollectionBuilder.cs b/src/Umbraco.Web/Trees/TreeCollectionBuilder.cs index 143b8e308b..ae2675bac9 100644 --- a/src/Umbraco.Web/Trees/TreeCollectionBuilder.cs +++ b/src/Umbraco.Web/Trees/TreeCollectionBuilder.cs @@ -3,16 +3,15 @@ using Umbraco.Core.Composing; namespace Umbraco.Web.Trees { - //fixme - how will we allow users to modify these items? they will need to be able to change the ApplicationTree's registered (i.e. sort order, section) - public class TreeCollectionBuilder : CollectionBuilderBase + public class TreeCollectionBuilder : ICollectionBuilder { - private readonly List _instances = new List(); + /// + /// expose the list of trees which developers can manipulate before the collection is created + /// + public List Trees { get; } = new List(); - public void AddTree(Tree tree) - { - _instances.Add(tree); - } + public TreeCollection CreateCollection(IFactory factory) => new TreeCollection(Trees); - protected override IEnumerable CreateItems(IFactory factory) => _instances; + public void RegisterWith(IRegister register) => register.Register(CreateCollection, Lifetime.Singleton); } } From 437385fd61b9a905cb29df263246f39e182126a0 Mon Sep 17 00:00:00 2001 From: Stephan Date: Fri, 18 Jan 2019 10:02:47 +0100 Subject: [PATCH 11/11] Bit of cleanup --- .../Composing/Composers/ServicesComposer.cs | 3 +- .../Manifest/ManifestBackOfficeSection.cs | 15 ++++++++++ src/Umbraco.Core/Manifest/ManifestParser.cs | 9 +++--- src/Umbraco.Core/Manifest/PackageManifest.cs | 29 +++++++++++++++---- .../Models/Trees/IBackOfficeSection.cs | 18 ++++++++++++ src/Umbraco.Core/Umbraco.Core.csproj | 2 ++ .../Manifest/ManifestParserTests.cs | 20 ++++++------- .../Services/SectionServiceTests.cs | 2 +- .../Models/Mapping/SectionMapperProfile.cs | 3 +- .../Models/Trees/IBackOfficeSection.cs | 12 -------- src/Umbraco.Web/Services/ISectionService.cs | 7 +---- src/Umbraco.Web/Services/SectionService.cs | 11 +++---- .../Trees/BackOfficeSectionCollection.cs | 5 +--- .../BackOfficeSectionCollectionBuilder.cs | 19 ++---------- .../Trees/ContentBackOfficeSection.cs | 6 ++-- .../Trees/MediaBackOfficeSection.cs | 5 ++-- .../Trees/MembersBackOfficeSection.cs | 8 +++-- .../Trees/PackagesBackOfficeSection.cs | 8 +++-- .../Trees/SettingsBackOfficeSection.cs | 8 +++-- .../Trees/TranslationBackOfficeSection.cs | 8 +++-- .../Trees/UsersBackOfficeSection.cs | 8 +++-- src/Umbraco.Web/Umbraco.Web.csproj | 1 - 22 files changed, 116 insertions(+), 91 deletions(-) create mode 100644 src/Umbraco.Core/Manifest/ManifestBackOfficeSection.cs create mode 100644 src/Umbraco.Core/Models/Trees/IBackOfficeSection.cs delete mode 100644 src/Umbraco.Web/Models/Trees/IBackOfficeSection.cs diff --git a/src/Umbraco.Core/Composing/Composers/ServicesComposer.cs b/src/Umbraco.Core/Composing/Composers/ServicesComposer.cs index 0b83373d99..3f1bc1df5e 100644 --- a/src/Umbraco.Core/Composing/Composers/ServicesComposer.cs +++ b/src/Umbraco.Core/Composing/Composers/ServicesComposer.cs @@ -73,7 +73,6 @@ namespace Umbraco.Core.Composing.Composers factory.GetInstance(), factory.GetInstance(), new DirectoryInfo(IOHelper.GetRootDirectorySafe()))); - return composition; } @@ -84,7 +83,7 @@ namespace Umbraco.Core.Composing.Composers /// /// private static PackagesRepository CreatePackageRepository(IFactory factory, string packageRepoFileName) - => new PackagesRepository( + => new PackagesRepository( factory.GetInstance(), factory.GetInstance(), factory.GetInstance(), factory.GetInstance(), factory.GetInstance(), factory.GetInstance(), factory.GetInstance(), factory.GetInstance(), packageRepoFileName); diff --git a/src/Umbraco.Core/Manifest/ManifestBackOfficeSection.cs b/src/Umbraco.Core/Manifest/ManifestBackOfficeSection.cs new file mode 100644 index 0000000000..a1b89d9a01 --- /dev/null +++ b/src/Umbraco.Core/Manifest/ManifestBackOfficeSection.cs @@ -0,0 +1,15 @@ +using System.Runtime.Serialization; +using Umbraco.Core.Models.Trees; + +namespace Umbraco.Core.Manifest +{ + [DataContract(Name = "section", Namespace = "")] + public class ManifestBackOfficeSection : IBackOfficeSection + { + [DataMember(Name = "alias")] + public string Alias { get; set; } + + [DataMember(Name = "name")] + public string Name { get; set; } + } +} diff --git a/src/Umbraco.Core/Manifest/ManifestParser.cs b/src/Umbraco.Core/Manifest/ManifestParser.cs index 28493fe20f..c471bbcf2e 100644 --- a/src/Umbraco.Core/Manifest/ManifestParser.cs +++ b/src/Umbraco.Core/Manifest/ManifestParser.cs @@ -9,6 +9,7 @@ using Umbraco.Core.Exceptions; using Umbraco.Core.IO; using Umbraco.Core.Logging; using Umbraco.Core.Models.ContentEditing; +using Umbraco.Core.Models.Trees; using Umbraco.Core.PropertyEditors; namespace Umbraco.Core.Manifest @@ -101,7 +102,7 @@ namespace Umbraco.Core.Manifest var gridEditors = new List(); var contentApps = new List(); var dashboards = new List(); - var sections = new Dictionary(); + var sections = new List(); foreach (var manifest in manifests) { @@ -112,9 +113,7 @@ namespace Umbraco.Core.Manifest if (manifest.GridEditors != null) gridEditors.AddRange(manifest.GridEditors); if (manifest.ContentApps != null) contentApps.AddRange(manifest.ContentApps); if (manifest.Dashboards != null) dashboards.AddRange(manifest.Dashboards); - if (manifest.Sections != null) - foreach (var (key, value) in manifest.Sections) - sections[key] = value; + if (manifest.Sections != null) sections.AddRange(manifest.Sections.DistinctBy(x => x.Alias.ToLowerInvariant())); } return new PackageManifest @@ -126,7 +125,7 @@ namespace Umbraco.Core.Manifest GridEditors = gridEditors.ToArray(), ContentApps = contentApps.ToArray(), Dashboards = dashboards.ToArray(), - Sections = sections + Sections = sections.ToArray() }; } diff --git a/src/Umbraco.Core/Manifest/PackageManifest.cs b/src/Umbraco.Core/Manifest/PackageManifest.cs index a0546f3629..b29a28ab06 100644 --- a/src/Umbraco.Core/Manifest/PackageManifest.cs +++ b/src/Umbraco.Core/Manifest/PackageManifest.cs @@ -1,7 +1,5 @@ using System; -using System.Collections.Generic; using Newtonsoft.Json; -using Umbraco.Core.Models.ContentEditing; using Umbraco.Core.PropertyEditors; namespace Umbraco.Core.Manifest @@ -11,31 +9,52 @@ namespace Umbraco.Core.Manifest /// public class PackageManifest { + /// + /// Gets or sets the scripts listed in the manifest. + /// [JsonProperty("javascript")] public string[] Scripts { get; set; } = Array.Empty(); + /// + /// Gets or sets the stylesheets listed in the manifest. + /// [JsonProperty("css")] - public string[] Stylesheets { get; set; }= Array.Empty(); + public string[] Stylesheets { get; set; } = Array.Empty(); + /// + /// Gets or sets the property editors listed in the manifest. + /// [JsonProperty("propertyEditors")] public IDataEditor[] PropertyEditors { get; set; } = Array.Empty(); + /// + /// Gets or sets the parameter editors listed in the manifest. + /// [JsonProperty("parameterEditors")] public IDataEditor[] ParameterEditors { get; set; } = Array.Empty(); + /// + /// Gets or sets the grid editors listed in the manifest. + /// [JsonProperty("gridEditors")] public GridEditor[] GridEditors { get; set; } = Array.Empty(); + /// + /// Gets or sets the content apps listed in the manifest. + /// [JsonProperty("contentApps")] public ManifestContentAppDefinition[] ContentApps { get; set; } = Array.Empty(); + /// + /// Gets or sets the dashboards listed in the manifest. + /// [JsonProperty("dashboards")] public ManifestDashboardDefinition[] Dashboards { get; set; } = Array.Empty(); /// - /// Declares the back office sections that this package installs + /// Gets or sets the sections listed in the manifest. /// [JsonProperty("sections")] - public IReadOnlyDictionary Sections { get; set; } = new Dictionary(); + public ManifestBackOfficeSection[] Sections { get; set; } = Array.Empty(); } } diff --git a/src/Umbraco.Core/Models/Trees/IBackOfficeSection.cs b/src/Umbraco.Core/Models/Trees/IBackOfficeSection.cs new file mode 100644 index 0000000000..86e2a18fd5 --- /dev/null +++ b/src/Umbraco.Core/Models/Trees/IBackOfficeSection.cs @@ -0,0 +1,18 @@ +namespace Umbraco.Core.Models.Trees +{ + /// + /// Defines a back office section. + /// + public interface IBackOfficeSection + { + /// + /// Gets the alias of the section. + /// + string Alias { get; } + + /// + /// Gets the name of the section. + /// + string Name { get; } + } +} diff --git a/src/Umbraco.Core/Umbraco.Core.csproj b/src/Umbraco.Core/Umbraco.Core.csproj index 5c0c870d15..6c2b359684 100755 --- a/src/Umbraco.Core/Umbraco.Core.csproj +++ b/src/Umbraco.Core/Umbraco.Core.csproj @@ -355,6 +355,7 @@ + @@ -449,6 +450,7 @@ + diff --git a/src/Umbraco.Tests/Manifest/ManifestParserTests.cs b/src/Umbraco.Tests/Manifest/ManifestParserTests.cs index 9970d5f6b0..e77b9a6e10 100644 --- a/src/Umbraco.Tests/Manifest/ManifestParserTests.cs +++ b/src/Umbraco.Tests/Manifest/ManifestParserTests.cs @@ -433,19 +433,17 @@ javascript: ['~/test.js',/*** some note about stuff asd09823-4**09234*/ '~/test2 [Test] public void CanParseManifest_Sections() { - const string json = @"{'sections': { - 'content': 'Content', - 'hello': 'World' - } -}"; + const string json = @"{'sections': [ + { ""alias"": ""content"", ""name"": ""Content"" }, + { ""alias"": ""hello"", ""name"": ""World"" } +]}"; var manifest = _parser.ParseManifest(json); - Assert.AreEqual(2, manifest.Sections.Count); - Assert.AreEqual("content", manifest.Sections.Keys.ElementAt(0)); - Assert.AreEqual("hello", manifest.Sections.Keys.ElementAt(1)); - Assert.AreEqual("Content", manifest.Sections["content"]); - Assert.AreEqual("World", manifest.Sections["hello"]); - + Assert.AreEqual(2, manifest.Sections.Length); + Assert.AreEqual("content", manifest.Sections[0].Alias); + Assert.AreEqual("hello", manifest.Sections[1].Alias); + Assert.AreEqual("Content", manifest.Sections[0].Name); + Assert.AreEqual("World", manifest.Sections[1].Name); } } } diff --git a/src/Umbraco.Tests/Services/SectionServiceTests.cs b/src/Umbraco.Tests/Services/SectionServiceTests.cs index 87fcde34ad..84eb0d1cbc 100644 --- a/src/Umbraco.Tests/Services/SectionServiceTests.cs +++ b/src/Umbraco.Tests/Services/SectionServiceTests.cs @@ -17,7 +17,7 @@ namespace Umbraco.Tests.Services public class SectionServiceTests : TestWithSomeContentBase { private ISectionService SectionService => Factory.GetInstance(); - + [Test] public void SectionService_Can_Get_Allowed_Sections_For_User() { diff --git a/src/Umbraco.Web/Models/Mapping/SectionMapperProfile.cs b/src/Umbraco.Web/Models/Mapping/SectionMapperProfile.cs index 5aa99e4652..7e727a3752 100644 --- a/src/Umbraco.Web/Models/Mapping/SectionMapperProfile.cs +++ b/src/Umbraco.Web/Models/Mapping/SectionMapperProfile.cs @@ -1,9 +1,8 @@ using System.Collections.Generic; using AutoMapper; -using Umbraco.Core.Models.ContentEditing; +using Umbraco.Core.Models.Trees; using Umbraco.Core.Services; using Umbraco.Web.Models.ContentEditing; -using Umbraco.Web.Models.Trees; namespace Umbraco.Web.Models.Mapping { diff --git a/src/Umbraco.Web/Models/Trees/IBackOfficeSection.cs b/src/Umbraco.Web/Models/Trees/IBackOfficeSection.cs deleted file mode 100644 index 0cc505fb19..0000000000 --- a/src/Umbraco.Web/Models/Trees/IBackOfficeSection.cs +++ /dev/null @@ -1,12 +0,0 @@ -namespace Umbraco.Web.Models.Trees -{ - - /// - /// Defines a back office section - /// - public interface IBackOfficeSection - { - string Alias { get; } - string Name { get; } - } -} diff --git a/src/Umbraco.Web/Services/ISectionService.cs b/src/Umbraco.Web/Services/ISectionService.cs index f0a16dc965..1cb8b6d450 100644 --- a/src/Umbraco.Web/Services/ISectionService.cs +++ b/src/Umbraco.Web/Services/ISectionService.cs @@ -1,8 +1,5 @@ using System.Collections.Generic; -using Umbraco.Core.Models; -using Umbraco.Core.Models.ContentEditing; -using Umbraco.Web.Models.ContentEditing; -using Umbraco.Web.Models.Trees; +using Umbraco.Core.Models.Trees; namespace Umbraco.Web.Services { @@ -26,7 +23,5 @@ namespace Umbraco.Web.Services /// The application alias. /// IBackOfficeSection GetByAlias(string appAlias); - } - } diff --git a/src/Umbraco.Web/Services/SectionService.cs b/src/Umbraco.Web/Services/SectionService.cs index 089bdc5bd3..0be28b0294 100644 --- a/src/Umbraco.Web/Services/SectionService.cs +++ b/src/Umbraco.Web/Services/SectionService.cs @@ -1,8 +1,8 @@ using System; using System.Collections.Generic; using System.Linq; +using Umbraco.Core.Models.Trees; using Umbraco.Core.Services; -using Umbraco.Web.Models.Trees; using Umbraco.Web.Trees; namespace Umbraco.Web.Services @@ -19,11 +19,12 @@ namespace Umbraco.Web.Services _userService = userService ?? throw new ArgumentNullException(nameof(userService)); _sectionCollection = sectionCollection ?? throw new ArgumentNullException(nameof(sectionCollection)); } - + /// /// The cache storage for all applications /// - public IEnumerable GetSections() => _sectionCollection; + public IEnumerable GetSections() + => _sectionCollection; /// public IEnumerable GetAllowedSections(int userId) @@ -36,7 +37,7 @@ namespace Umbraco.Web.Services } /// - public IBackOfficeSection GetByAlias(string appAlias) => GetSections().FirstOrDefault(t => t.Alias == appAlias); - + public IBackOfficeSection GetByAlias(string appAlias) + => GetSections().FirstOrDefault(t => t.Alias == appAlias); } } diff --git a/src/Umbraco.Web/Trees/BackOfficeSectionCollection.cs b/src/Umbraco.Web/Trees/BackOfficeSectionCollection.cs index fdeb812363..f604fa1124 100644 --- a/src/Umbraco.Web/Trees/BackOfficeSectionCollection.cs +++ b/src/Umbraco.Web/Trees/BackOfficeSectionCollection.cs @@ -1,8 +1,6 @@ using System.Collections.Generic; using Umbraco.Core.Composing; -using Umbraco.Core.Models.ContentEditing; -using Umbraco.Web.Models.ContentEditing; -using Umbraco.Web.Models.Trees; +using Umbraco.Core.Models.Trees; namespace Umbraco.Web.Trees { @@ -11,6 +9,5 @@ namespace Umbraco.Web.Trees public BackOfficeSectionCollection(IEnumerable items) : base(items) { } - } } diff --git a/src/Umbraco.Web/Trees/BackOfficeSectionCollectionBuilder.cs b/src/Umbraco.Web/Trees/BackOfficeSectionCollectionBuilder.cs index 3228cd309f..452ac02f38 100644 --- a/src/Umbraco.Web/Trees/BackOfficeSectionCollectionBuilder.cs +++ b/src/Umbraco.Web/Trees/BackOfficeSectionCollectionBuilder.cs @@ -2,12 +2,10 @@ using System.Linq; using Umbraco.Core.Composing; using Umbraco.Core.Manifest; -using Umbraco.Core.Models.ContentEditing; -using Umbraco.Web.Models.Trees; +using Umbraco.Core.Models.Trees; namespace Umbraco.Web.Trees { - //fixme: how can a developer re-sort the items in this collection ? public class BackOfficeSectionCollectionBuilder : OrderedCollectionBuilderBase { protected override BackOfficeSectionCollectionBuilder This => this; @@ -19,20 +17,7 @@ namespace Umbraco.Web.Trees // its dependencies too, and that can create cycles or other oddities var manifestParser = factory.GetInstance(); - return base.CreateItems(factory) - .Concat(manifestParser.Manifest.Sections.Select(x => new ManifestBackOfficeSection(x.Key, x.Value))); - } - - private class ManifestBackOfficeSection : IBackOfficeSection - { - public ManifestBackOfficeSection(string @alias, string name) - { - Alias = alias; - Name = name; - } - - public string Alias { get; } - public string Name { get; } + return base.CreateItems(factory).Concat(manifestParser.Manifest.Sections); } } } diff --git a/src/Umbraco.Web/Trees/ContentBackOfficeSection.cs b/src/Umbraco.Web/Trees/ContentBackOfficeSection.cs index 0109a6916d..8b37ce0e12 100644 --- a/src/Umbraco.Web/Trees/ContentBackOfficeSection.cs +++ b/src/Umbraco.Web/Trees/ContentBackOfficeSection.cs @@ -1,6 +1,5 @@ using Umbraco.Core; -using Umbraco.Web.Models.ContentEditing; -using Umbraco.Web.Models.Trees; +using Umbraco.Core.Models.Trees; namespace Umbraco.Web.Trees { @@ -9,7 +8,10 @@ namespace Umbraco.Web.Trees /// public class ContentBackOfficeSection : IBackOfficeSection { + /// public string Alias => Constants.Applications.Content; + + /// public string Name => "Content"; } } diff --git a/src/Umbraco.Web/Trees/MediaBackOfficeSection.cs b/src/Umbraco.Web/Trees/MediaBackOfficeSection.cs index aac4fd036f..34ce6b89a9 100644 --- a/src/Umbraco.Web/Trees/MediaBackOfficeSection.cs +++ b/src/Umbraco.Web/Trees/MediaBackOfficeSection.cs @@ -1,6 +1,5 @@ using Umbraco.Core; -using Umbraco.Web.Models.ContentEditing; -using Umbraco.Web.Models.Trees; +using Umbraco.Core.Models.Trees; namespace Umbraco.Web.Trees { @@ -12,4 +11,4 @@ namespace Umbraco.Web.Trees public string Alias => Constants.Applications.Media; public string Name => "Media"; } -} \ No newline at end of file +} diff --git a/src/Umbraco.Web/Trees/MembersBackOfficeSection.cs b/src/Umbraco.Web/Trees/MembersBackOfficeSection.cs index bfaead33d5..1d1f66835c 100644 --- a/src/Umbraco.Web/Trees/MembersBackOfficeSection.cs +++ b/src/Umbraco.Web/Trees/MembersBackOfficeSection.cs @@ -1,6 +1,5 @@ using Umbraco.Core; -using Umbraco.Web.Models.ContentEditing; -using Umbraco.Web.Models.Trees; +using Umbraco.Core.Models.Trees; namespace Umbraco.Web.Trees { @@ -9,7 +8,10 @@ namespace Umbraco.Web.Trees ///
public class MembersBackOfficeSection : IBackOfficeSection { + /// public string Alias => Constants.Applications.Members; + + /// public string Name => "Members"; } -} \ No newline at end of file +} diff --git a/src/Umbraco.Web/Trees/PackagesBackOfficeSection.cs b/src/Umbraco.Web/Trees/PackagesBackOfficeSection.cs index 41f049c092..f59d368d91 100644 --- a/src/Umbraco.Web/Trees/PackagesBackOfficeSection.cs +++ b/src/Umbraco.Web/Trees/PackagesBackOfficeSection.cs @@ -1,6 +1,5 @@ using Umbraco.Core; -using Umbraco.Web.Models.ContentEditing; -using Umbraco.Web.Models.Trees; +using Umbraco.Core.Models.Trees; namespace Umbraco.Web.Trees { @@ -9,7 +8,10 @@ namespace Umbraco.Web.Trees ///
public class PackagesBackOfficeSection : IBackOfficeSection { + /// public string Alias => Constants.Applications.Packages; + + /// public string Name => "Packages"; } -} \ No newline at end of file +} diff --git a/src/Umbraco.Web/Trees/SettingsBackOfficeSection.cs b/src/Umbraco.Web/Trees/SettingsBackOfficeSection.cs index 623f593c30..71b9781cd1 100644 --- a/src/Umbraco.Web/Trees/SettingsBackOfficeSection.cs +++ b/src/Umbraco.Web/Trees/SettingsBackOfficeSection.cs @@ -1,6 +1,5 @@ using Umbraco.Core; -using Umbraco.Web.Models.ContentEditing; -using Umbraco.Web.Models.Trees; +using Umbraco.Core.Models.Trees; namespace Umbraco.Web.Trees { @@ -9,7 +8,10 @@ namespace Umbraco.Web.Trees ///
public class SettingsBackOfficeSection : IBackOfficeSection { + /// public string Alias => Constants.Applications.Settings; + + /// public string Name => "Settings"; } -} \ No newline at end of file +} diff --git a/src/Umbraco.Web/Trees/TranslationBackOfficeSection.cs b/src/Umbraco.Web/Trees/TranslationBackOfficeSection.cs index 41254b3179..bba1f5d8a3 100644 --- a/src/Umbraco.Web/Trees/TranslationBackOfficeSection.cs +++ b/src/Umbraco.Web/Trees/TranslationBackOfficeSection.cs @@ -1,6 +1,5 @@ using Umbraco.Core; -using Umbraco.Web.Models.ContentEditing; -using Umbraco.Web.Models.Trees; +using Umbraco.Core.Models.Trees; namespace Umbraco.Web.Trees { @@ -9,7 +8,10 @@ namespace Umbraco.Web.Trees ///
public class TranslationBackOfficeSection : IBackOfficeSection { + /// public string Alias => Constants.Applications.Translation; + + /// public string Name => "Translation"; } -} \ No newline at end of file +} diff --git a/src/Umbraco.Web/Trees/UsersBackOfficeSection.cs b/src/Umbraco.Web/Trees/UsersBackOfficeSection.cs index 90a65cb508..0096b2abbb 100644 --- a/src/Umbraco.Web/Trees/UsersBackOfficeSection.cs +++ b/src/Umbraco.Web/Trees/UsersBackOfficeSection.cs @@ -1,6 +1,5 @@ using Umbraco.Core; -using Umbraco.Web.Models.ContentEditing; -using Umbraco.Web.Models.Trees; +using Umbraco.Core.Models.Trees; namespace Umbraco.Web.Trees { @@ -9,7 +8,10 @@ namespace Umbraco.Web.Trees ///
public class UsersBackOfficeSection : IBackOfficeSection { + /// public string Alias => Constants.Applications.Users; + + /// public string Name => "Users"; } -} \ No newline at end of file +} diff --git a/src/Umbraco.Web/Umbraco.Web.csproj b/src/Umbraco.Web/Umbraco.Web.csproj index 23cbb7a416..71b0631c4f 100755 --- a/src/Umbraco.Web/Umbraco.Web.csproj +++ b/src/Umbraco.Web/Umbraco.Web.csproj @@ -175,7 +175,6 @@ -